-
Notifications
You must be signed in to change notification settings - Fork 0
/
vue.js.rst
811 lines (616 loc) · 27 KB
/
vue.js.rst
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
.. _vue.js-basic:
=======
Vue.js
=======
`Vue.js <https://v3.cn.vuejs.org/>`__ 是一个用于创建用户界面的开源 JavaScript 框架,也是一个创建单页应用的 Web 应用框架,能够简化 Web 开发。
Vue 所关注的核心是 MVC 模式中的视图层,同时,它也能方便地获取数据更新,并通过组件内部特定的方法实现视图与模型的交互。
Vue 主要特性包括:
- 组件:组件是基础 `HTML 元素 <https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element>`_\ 的扩展,可以方便地自定义其\ **数据**\ 与\ **行为**\。
- 模板:使用基于 `HTML 模板 <https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/template>`_\ 语法,可以将 `DOM <https://developer.mozilla.org/zh-CN/docs/Web/API/Document_Object_Model/Introduction>`_ 元素与底层 `Vue 实例 <https://cn.vuejs.org/v2/guide/instance.html>`_\ 中的数据\ **绑定**\。满足响应式设计。
- 响应式设计:在视图与对应的模型绑定后,Vue **自动观测模型的变动**\,并重新绘图。
- 过渡效果:Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。
- 单文件组件:为了更好地适应复杂的项目,Vue 支持以 ``.vue`` 为扩展名的文件来定义一个完整组件,用以替代使用 ``Vue.component`` 注册组件的方式。
安装与部署
----------
如果只是在一个页面中使用 Vue.js,那么普通的 JS 导入就可以直接使用了。
在项目中安装 Vue.js 只需要下载 `vue.js <https://vuejs.org/js/vue.js>`_ 然后,用代码引入就可以了。
.. code-block:: html
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
当然,如果项目更加复杂,一般通过单文件组件(后面会讲)的方式在构建应用,通常首先需要安装 npm、vue-cli、webpack 三个工具。
然后在命令行中键入 ``vue ui`` 创建一个项目。
创建第一个 Vue 应用
-------------------
在 JS 中用 ``new Vue()`` 即可创建一个 Vue 应用,它接收参数为 JSON 格式的对象。
众所周知,JSON 格式的对象是由很多键值对组成的,它的键一般都是字符串,而值的变化就比较多,可以是字符串,列表,也可以是函数。
这个 JSON 格式的对象负责完成 Vue.js 与 DOM 元素的数据绑定,采用 **声明式渲染** 的方式完成页面渲染。
JSON 对象中,除了 ``el`` 的值是一个字符串外,其他键(如 ``data`` 、 ``methods`` )的值都是一个对象。
代码清单 1:
.. code-block:: html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app"> <!-- 一般通过 id 索引模块 -->
{{ message }} {{name}} <!-- HTML 声明式模板语法,文本插值,双大括号 -->
</div>
<script type="text/javascript">
var app = new Vue({
el: '#app', // el:用于和对应的 DOM 元素一一对应(绑定)
data: { // data:为相应 DOM 元素下的变量赋值
message: 'Hello Vue!',
name: 'vue'
}
});
</script>
</body>
</html>
数据与方法
----------
在上一节,学习了如何修改 HTML 模板中的变量值,这一章学习如何修改 Vue 应用中的变量值。
在 Vue 实例中, ``$`` 表示该实例的属性或方法,访问 Vue 实例或 JS 对象的属性或方法用点操作符 ``.``\。
因为,在 JS 脚本中单大括号表示 ``{对象}``\,因此,下例中修改变量 a 的值时使用了两次点操作符,在默认情况下 ``$data`` 可以省略不写。
注意,\ ``vm.$watch`` 是 Vue 实例的方法,用于观测变量的值是否发生改变。
代码清单 2:
.. code-block:: html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
{{a}}
</div>
<script type="text/javascript">
var test = { a : 1 }; // 声明变量
var vm = new Vue({
el : "#app",
data : test // data 是 Vue 实例的属性
// data : { a : 3 } // data : test 的等价形式
});
// 观察 a 的变化,如果 a 发生了变化,就执行function
vm.$watch('a', function(to, from) {
console.log(to, from);
})
// vm.$data.a = "test...." // 访问 vue 实例 $data 属性下的 a 变量
vm.a = "123" // vm.$data.a 的等价形式,$data 可以省略不写
</script>
</body>
</html>
生命周期
---------
Vue 实例的生命周期如下图,要理解这个图现在还有些困难,随着学习的深入,后面可以回过头来回顾。
在 Vue 的生命周期中,他会做很多事情,图中的绿色部分时 Vue 的内部实现,红色部分使我们需要关注的。
红色部分表示钩子函数,也是我们在开发中 **可以重写** 的部分,在 Vue 运行到相应阶段的时候,会自动回调。
实际开发中,一般的工作流程是:
- 根组件在 ``created`` 阶段请求网络数据;
- 将数据保存在 Vue 实例的 ``data`` 部分;
- 通过父子组件之间的通信,子组件将数据展示在 DOM 上。
.. image:: ../_static/images/vue-lifecycle.*
代码清单 3:
.. code-block:: html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
{{msg}}
</div>
<script type="text/javascript">
var vm = new Vue({
el : "#app",
data : {
msg : "hi vue",
},
// 在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
beforeCreate : function(){
console.log('beforeCreate');
},
// 在实例创建完成后被立即调用。
// 在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。
// 然而,挂载阶段还没开始,$el 属性目前不可见。
created : function(){
console.log('created');
},
// 在挂载开始之前被调用:相关的渲染函数首次被调用
beforeMount : function(){
console.log('beforeMount');
},
// el 被新创建的 vm.$el 替换, 挂载成功
mounted : function(){
console.log('mounted');
},
// 数据更新时调用
beforeUpdate : function(){
console.log('beforeUpdate');
},
// 组件 DOM 已经更新, 组件更新完毕
updated : function(){
console.log('updated');
}
});
setTimeout(function(){
vm.msg = "change ......";
}, 3000);
</script>
</body>
</html>
模板语法-插值
-------------
双大括号可以实现文本插值,如果是 HTML 代码的话,那么无法进行解析,
这时候可以借助 Vue 提供的 ``v-html`` 命令,将插值解析成 HTML 代码。
``v-bind:class="表达式"``,暂时可以忽略,后面会讲。
代码清单 4:
.. code-block:: html
:emphasize-lines: 11, 12
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
{{msg}}
<p>Using mustaches: {{ rawHtml }}</p> <!-- 用 HTML 模板语法声明的变量 -->
<p v-html="rawHtml"></p> <!-- 用指令声明的变量(凡是带有 v- 开头的都是 Vue 指令) -->
<div v-bind:class="color">test...</div>
<p>{{ number + 1 }}</p>
<p>{{ ok ? 'YES' : 'NO' }}</p>
<p>{{ message.split('').reverse().join('') }}</p>
</div>
<script type="text/javascript">
var vm = new Vue({
el : "#app",
data : {
msg : "hi vue",
rawHtml : '<span style="color:red">This should be red</span>',
color : 'blue',
number : 10,
ok : 1,
message : "vue"
}
});
vm.msg = "hi....";
</script>
<style type="text/css">
.red {
color: red;
}
.blue {
color: blue;
font-size: 100px;
}
</style>
</body>
</html>
模板语法-指令
-------------
如下代码清单 5 所示,展示了一些比较常用的指令:
- ``v-if="表达式"``
- ``v-on:事件名="表达式"``
- ``v-bind:属性名="表达式"``
``v-if`` 中的表达式结果为真的时候,Vue 会渲染当前的 DOM 元素,如果为假,该元素将不会出现在网页上。
``v-if`` 和 ``v-show`` 的不同之处就在于 ``v-show`` 不管表达式是真还是假,都会出现在网页上,只不过为假的时候, ``display=none``。
``v-on`` 中的事件名可以是鼠标单击、双击、键盘按下、抬起等浏览器自动监听的时间,也可以是自定义事件,
比如我们在父子组件通信的时候,子组件向父组件通过 ``$emit("事件名", 变量名)`` 发送的事件。
``v-on`` 中的表达式可以是一个函数名,事件发生时触发这个函数,也可以是普通的表达式语句表示做出什么动作。
``v-bind`` 是用的比较多的一个指令了,因此也有语法糖的写法形式,就是省略 ``v-bind``,直接用冒号代替。
当属性名为普通的属性(如 ``href`` 、 ``src`` )时,我们可以在 Vue 实例的 ``data`` 选项中 **给表达式中的变量** 赋初值。
当属性名是 ``class`` 或 ``style`` 时,我们就可以动态地改变样式了,见下一节 ``class`` 与 ``style`` 绑定。
代码清单 5:
.. code-block:: text
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<p v-if="seen">现在你看到我了</p>
<a v-bind:href="url">可以更换的动态URL</a>
<div v-on:click="click1"> <!-- 因为下面的 click.stop 这里的 click1 不会触发了 -->
<div v-on:click.stop="click2">
<!-- <div @click.stop="click2"> 和上面一行效果一样 -->
click me
</div>
</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el : "#app",
data : {
seen : true,
url : "https://cn.vuejs.org/v2/guide/syntax.html"
},
methods:{
click1 : function () {
console.log('click1......');
},
click2 : function () {
console.log('click2......');
}
}
});
</script>
</body>
</html>
class 与 style 绑定
-------------------
``class`` 和 ``内联样式`` 是 HTML 元素的常用属性,通过 ``v-bind`` 可以将两者进行绑定。
有了这个绑定,我们后面可以通过 ``class`` 来动态地修改 HTML 元素的样式了。
代码清单 6:
.. code-block:: html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<div class="test"
v-bind:class="[ isActive ? 'active' : '', isGreen ? 'green' : '']"
style="width:200px; height:200px; text-align:center; line-height:200px;">
hi vue
</div>
<div :style="{color:color, fontSize:size, background: isRed ? '#FF0000' : ''}">
hi vue
</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el : "#app",
data : {
isActive : true,
isGreen : true,
color : "#FFFFFF",
size : '50px',
isRed : true
}
});
</script>
<style>
.test{font-size:30px;}
.green{color:#00FF00;}
.active{background:#FF0000;}
</style>
</body>
</html>
条件渲染
--------
``v-if`` 是 Vue 的一个指令,我们上面已经用过了,因此这一章比较容易理解。
代码清单 7:
.. code-block:: html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<div v-if="type === 'A'"> <!-- if 和 else-if 语法,选择某一个 div 进行渲染 -->
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else-if="type === 'C'">
C
</div>
<div v-else>
Not A/B/C
</div>
<h1 v-show="ok">Hello!</h1>
</div>
<script type="text/javascript">
var vm = new Vue({
el : "#app",
data : {
type : "B",
ok : true
}
});
</script>
<style type="text/css">
</style>
</body>
</html>
列表渲染
--------
列表渲染指的是有序列表或无序列表的渲染。通常用 ``v-for`` 来操作列表中的每个元素。语法为 ``v-for="表达式"``。
说到表达式,必然后变量和关键字,那么一般常用的表达式是 ``v-for="item,index in items"``。
这其中只有 ``in`` 是关键字,其他都是变量,可以在 ``data`` 选项中赋初值,在 ``methods`` 中定义函数进行修改(一般与 ``@click`` 搭配,有事件触发函数)。
需要注意的是,如果 ``items`` 是数组,第一个元素 ``item`` 表示数组的值,第二个返回值 ``index`` 表示数组的索引;
如果 ``items`` 是对象,第一个元素 ``item`` 表示对象的值,第二个返回值 ``index`` 表示对象的键。
代码清单 8:
.. code-block:: html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<ul>
<li v-for="(item, listindex) in items" :key="listindex">
{{ item }} : {{ listindex }} : {{ item.message }}
</li>
</ul>
<ul>
<li v-for="(value, key, objindex) in object" :key="objindex">
{{ key }} : {{ value }} : {{objindex}}
</li>
</ul>
</div>
<script type="text/javascript">
var vm = new Vue({
el : "#app",
data : {
items : [
{ message: 'Foo' },
{ message: 'Bar' }
],
object: {
title: 'How to do lists in Vue',
author: 'Jane Doe',
publishedAt: '2016-04-10'
}
}
});
</script>
</body>
</html>
事件绑定
--------
``v-on`` 用来监听 DOM 事件,比如鼠标点击( ``@click`` ),键盘抬起( ``@keyup`` ),Enter 键抬起( ``@keyup.enter`` )。
语法 ``v-on:click="表达式"``。这里的表达式,既可以是一个函数名,也可以是一个逻辑表达式。
实际开发中,因为 ``v-on`` 比较常用,语法糖的写法是用 ``@`` 符号代替 ``v-on:``。
代码清单 9:
.. code-block:: html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<div id="example-1">
<button v-on:click="counter += 1"> 数值 : {{ counter }} </button><br />
<button v-on:dblclick="greet('abc', $event)">Greet</button>
</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el : "#app",
data : {
counter: 0,
name : "vue"
},
methods:{
greet : function (str, e) {
alert(str);
console.log(e);
}
}
});
</script>
<style type="text/css">
</style>
</body>
</html>
表单输入绑定
------------
我们之前都是通过在后台修改数据,来让前端页面的内容得到修改,这时如果反过来,在前端页面修改值,
并不会修改后台中的 ``data`` 中变量的值,这是因为只有单向绑定。
而用 ``v-model`` 指令在表单 ``<input>`` 、 ``<textarea>`` 及 ``<select>`` 元素上创建\ **双向数据绑定**\。
使得前端页面的修改可以在后台收到改动,后台的改动也会在前端页面中展示出来。
尽管有些神奇,但 ``v-model`` 本质上不过是语法糖,它整合了 ``:value`` 和 ``@input`` 两个事件,是一个缩写版本。
但是双向绑定只在表单中实现了,如果想要自己在其他元素中实现双向绑定,则需要自己实现上面两个完整的事件。
代码清单 10:
.. code-block:: text
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<div id="example-1">
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
<textarea v-model="message2" placeholder="add multiple lines"></textarea>
<p style="white-space: pre-line;">{{ message2 }}</p>
<br />
<div style="margin-top:20px;">
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
<br>
<span>Checked names: {{ checkedNames }}</span>
</div>
<div style="margin-top:20px;">
<input type="radio" id="one" value="One" v-model="picked">
<label for="one">One</label>
<br>
<input type="radio" id="two" value="Two" v-model="picked">
<label for="two">Two</label>
<br>
<span>Picked: {{ picked }}</span>
</div>
<button type="button" @click="submit">提交</button>
</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el : "#app",
data : {
message : "test",
message2 : "hi",
checkedNames : ['Jack', 'John'],
picked : "Two"
},
methods: {
submit : function () {
console.log(this.message);
}
}
});
</script>
<style type="text/css">
</style>
</body>
</html>
父子组件通信
------------
组件是可复用的 Vue 实例,可以通过 ``Vue.component('组件名', JSON 对象)`` 创建组件。
``JSON 对象`` 的一般格式为:
.. code-block:: html
{
template: `<div>某些 HTML 代码</div>`,
...
}
关于组件,首先需要了解什么是全局组件和局部组件,然后还需要知道什么是父组件,什么是子组件。
子组件指的就是局部组件,而相应地,父组件就是包含局部注册的组件,简而言之,在组件中注册组件即构成父子关系。
可以推断, ``new Vue()`` 创建出来的就是根组件,它是所有组件的父组件。
- 全局组件:用 ``Vue.component('组件名', JSON 对象)`` 创建的组件;
- 局部组件:使用 ``component`` 属性注册的组件。
这里仅说明一下概念,更详细的内容参考 `组件注册 <https://v3.cn.vuejs.org/guide/component-registration.html>`_。
根据我们现有的编程基础,可以断定,父组件相比子组件而言,拥有更大的作用域和生命周期。
需要明白的是,组件之间有父子关系,父组件和子组件之间的通信因此成为了很关键的一环。
在真实业务中,一般是根组件向服务器发送请求,保存在 ``data`` 中,然后子组件获取父组件的 ``data``,进行展示。
子组件中的 ``data()`` 必须是函数,而不能是属性,这是因为每个子组件都希望有自己的数据空间,而不被共享。
父组件向子组件通信:在子组件中用 ``props: ['子组件变量名']`` **接收消息**\。
在父组件模板中的通过属性 ``v-bind:子组件变量名="父组件变量名"`` **中转消息**\。
在父组件中通过 ``data`` 初始化父组件变量的值来 **发送消息**\,
又因为 ``data`` 中的变量值可以通过 ``methods`` 或 ``computed`` 方法进行修改,从而实现对网页内容的实时渲染。
子组件向父组件通信:在子组件的某个方法中用 ``$emit('子组件事件名', 子组件变量名)`` **发送消息**\。
在父组件模板中用 ``@子组件事件名='父组件事件名'`` 监听子组件的事件,触发父组件事件。
**消息本体** 就是 ``子组件变量名`` 这个参数保存了数据,因此实现消息的传递。
这样当父组件拿到变量后,可以保存到自己的 ``data`` 部分,就可以 **实现持久化** 了。
代码清单 11:
.. code-block:: text
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<!-- HTML 代码中的变量只能在 根组件 中注册,不能在 子组件 中注册 -->
<div id="app">
<buttoncounter :ctitle="ptitle" @cclick="pclick"> <!-- 子组件向父组件发送事件 -->
<h2>上面这个按钮接收由子组件发送过来的 cclick 事件,触发父组件的 pclick 事件</h2>
</buttoncounter>
<buttoncounter :ctitle="ptitle"></buttoncounter>
</div>
<script type="text/javascript">
// 实现子组件
const buttoncounter = {
// 在子组件中写 props 列表/对象,获取父组件相关变量的值
props: ['ctitle'],
// 定义子组件的模板,在模板中使用变量
template:
`<div>
<button v-on:click="clickfunc">
{{ctitle}} 子组件在统计你点击了 {{ count }} 次.
</button>
<slot></slot>
</div>`,
// 子组件中的变量注册
// data() 必须为函数,因为每个组件都希望有自己的变量且互不干扰
data() {
return {
count: 0
}
},
// 定义子组件的方法
methods:{
clickfunc() { // ES6 的写法
this.count ++; // 你会发现子组件的 count 在增长
this.$emit('cclick', this.count); // 发出一个 cclick 事件,参数为 this.count
}
}
}
// Vue 实例(根组件、父组件)
var vm = new Vue({
el : "#app",
data : {
ptitle: '父组件赋予的标题:'
},
methods:{
pclick(e) { // ES6 写法
console.log(e);
}
},
// 局部组件注册,形成父子关系
components: {
buttoncounter // ES6 简写形式,全写是 buttoncounter: buttoncounter
}
});
</script>
<style type="text/css">
</style>
</body>
</html>
如果父组件想直接访问子组件的方法或属性可以用 ``$children[i].func()`` 或 ``$refs.name``。
如果子组件想访问父组件的方法或属性用 ``$parent.func()`` 或 ``$root.func()``。
实际开发中,用 ``$children`` 和 ``$root`` 都比较少,因为 ``$children`` 在增加或删除子组件时会发生索引错误。
单文件组件
----------
到目前为止,我们学完了 Vue 主要的基础内容。基于组件的开发方式更适用于大项目。
首先,安装准备环境:
1. 安装 npm:\ ``npm -v``
2. 由于网络原因 安装 cnpm:\ ``npm install -g cnpm --registry=https://registry.npm.taobao.org``
3. 安装 vue-cli:\ ``cnpm install -g @vue/cli``
4. 安装 webpack:\ ``cnpm install -g webpack``
然后,在命令行中使用 ``vue ui`` 创建一个 Vue 项目,包管理器选择 ``npm`` 其他保持默认即可。
创建完成后,关闭浏览器,用 IDE 打开项目。可以看到, ``public`` 是项目开发完成后部署的文件。
``src`` 是源代码文件,我们将在这里完成开发工作。
1. ``src/App.vue`` 是项目的入口文件,在 ``script`` 中 ``import`` 自定义的组件;
2. 在 ``script`` 中使用 ``export default`` 注册组件;
- 用 ``name:`` 给组件起个名字;
- 用 ``props`` 在子组件中声明需要向父组件请求的数据;
- 用 ``data() {}`` 给 ``template`` 中的变量赋予初值
- 用 ``methods: {}`` 定义函数方法实现
- 用 ``mounted() {}`` 自动调用函数(因为有些函数不需要监听鼠标或键盘事件)
3. 在 ``template`` 中使用已经注册的组件,即可完成整个开发流程。
以上,基础知识全部更新完毕。
进阶阅读
--------
实际项目开发中,我们可能需要 **频繁使用** 一些更加高级的功能,比如:
- 用 `插槽 <https://v3.cn.vuejs.org/guide/component-slots.html>`_ 占位,后面根据内容自定义补充到这个位置;
- 使用 `Vue Router <https://next.router.vuejs.org/>`_ 实现前端路由;
- 使用 `Vuex <https://next.vuex.vuejs.org/zh/>`_ 让多个组件可以共享某些信息,比如用户的登录状态等等;
- 使用 `Axios <https://cn.vuejs.org/v2/cookbook/using-axios-to-consume-apis.html>`_ 处理并发的网络请求,借助
`Promise 对象 <https://wangdoc.com/javascript/async/promise.html>`_ 良好的封装实现异步通信。
未来有更多的知识等待探索。比如,如何更加优雅地组织代码,如何尽量减少第三方库混在业务逻辑中。
当你检查是否已经掌握了上面的知识,可以通过阅读我的
`代码仓库笔记 <https://gitee.com/zhyantao/learn-programing-languages/tree/master/vue.js>`_
检查一下,或者也可以当做复习用。