前言
在这几天学习的过程中发现一个问题,有的时候老师在视频中出现Vue warn
的地方我都没有,而且可以正常显示.
一开始我以为是版本的问题,可能我现在用的是最新版Vue,一些问题都已经解决了.但是直到今天(2019年11月27日)我才发现原因.
在BootCDN
中引用Vue时,我选择了min版本的,这造成很多warn不会被报出来.
以后开发的时候还是使用common版或者未压缩的更好.
ES6多行字符串与连接字符串的表示方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 旧版写法
alert("你好,\n 我叫\n Olive");
// 新版写法
alert(`你好
我叫
olive`);//注意这里的两个点是键盘上数字键1左边的按键,而不是单引号哦
// 以前,把多个字符串连接起来,可以用+号连接
var name ="olive";
var age= 26;
var message='hello,my name is '+name+',I\'m '+age+' years old';
alert(message);
// 但要是有很多变量需要连接,用+号就比较麻烦了。ES6新增了一种字符串连接方式:
var name1 ="Mike";
var age1=20;
var message1=`hello,${name1},your age is ${age1}`;//同理,这里的两个点是键盘上数字键1左边的按键,而不是单引号哦
alert(message1);
正文
组件中使用的细节点
使用is
解决H5的小bug
先看一段代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div id="root">
<table>
<tbody>
<row></row>
<row></row>
<row></row>
</tbody>
</table>
</div>
<script>
Vue.component('row',{
template: '<tr><td>XXX</td></tr>'
})
var vm = new Vue({
el: '#root'
})
</script>
当我们这样使用组件时会出现以下问题:
这时,
row
组件中添加的tr
全部都在table
外面,原因是在H5的规范中,要求我们在tbody中只能放tr标签,当浏览器解析到的是row标签时,就会出现这样的问题.
解决这个问题可以使用Vue提供的is
属性.
1
2
3
4
5
6
7
8
9
<div id="root">
<table>
<tbody>
<tr is="row"></tr>
<tr is="row"></tr>
<tr is="row"></tr>
</tbody>
</table>
</div>
组件中的data
必须以函数形式定义
组件的 data
选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝.
如果 Vue 没有这条规则,改变一个组件中的data
会影响到其它所有实例.
ref
的使用
ref
被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs
对象上。
如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例.
父子组件的数据传递
单向数据流
父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。
额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。
如果你这样做了,Vue 会在浏览器的控制台中发出警告。
解决方法:
在子组件中加入data
,在其中定义一个空值接收父组件传入的值.后面对这个新定义的值进行改动即可.
vm.$emit的使用
《父子组件间通信实例讲解(props、$ref、$emit)》
1
vm.$emit( event, arg )
$emit
绑定一个自定义事件event,当这个这个语句被执行到的时候,就会将参数arg传递给父组件,父组件通过@event
监听并接收参数。
组件参数校验
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
var counter = {
// props: ['content'], 这是最普通的使用方法
props: {
// content: String 这种写法可以规定传入值的类型
content: {
// 检测类型,可以像上面一样只符合一种类型,也可以用数组包括很多种类型
type: [String,Number],
// 规定是否必须传入一个对应的参数
required: false,
// 规定如果没传入对应值,则使用该默认值
default: 'default value',
// 校验器(validator) value为传入的值,通过判断返回值来判断是否报出警告
validator: function(value){
return (value.length > 5)
}
}
},
template: '<div>{{content}}</div>'
}
非props特性与为组件绑定原生事件
非props特性
- 无法在子组件中调用
- 该属性会显示在DOM中
为组件绑定原生事件
在事件后加.native
即可,如:
1
<child @clcik.native="handleClick()"></child>
非父子组件间传值(Bus/总线/发布订阅模式/观察者模式)
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
<body>
<div id="root">
<child content="I am A"></child>
<child content="I am B"></child>
</div>
<script>
Vue.prototype.bus = new Vue();
Vue.component('child',{
props:{
content: String
},
data: function() {
return {
selfContent : this.content
}
},
methods: {
handleClick () {
this.bus.$emit('change', this.selfContent);
}
},
mounted() {
var this_ = this;
this.bus.$on('change',function (msg) {
// 注意:这里的alert函数会触发两次,因为两个父组件都被触发了change事件
// alert(msg);
this_.selfContent = msg
});
},
template: '<div @click="handleClick()">{{selfContent}}</div>'
})
var vm = new Vue({
el: '#root'
})
</script>
</body>
先为Vue的原型添加一个bus
的方法,然后当我们点击div
时,会向bus
提交一个当前content
的参数,因为其他父组件也会被触发事件,所以数值一起发生改变.
插槽
父组件向子组件传递DOM结构时使用.
使用方法,在子组件中添加slot标签
:
1
template: '<div><slot></slot></div>'
具名插槽
如果要选择性提取父组件元素,则在HTML元素中给对应的标签添加slot属性
:
1
<div class="header" slot="header">header</div>
再在子组件中使用name属性
调用:
1
template: '<div><slot name="header"></slot></div>'
作用域插槽
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
<body>
<div id="root">
<child>
<template slot-scope="listData">
<li> </li>
</template>
</child>
</div>
<script>
Vue.component('child',{
data() {
return {
list: [1,2,3,4]
}
},
template: `<div>
<ul>
<slot v-for="item of list" :item=item></slot>
</ul>
</div>`
})
var vm = new Vue({
el: '#root'
})
</script>
</body>
这里相当于把<li>标签
作为slot
传入子组件中,子组件再向其传递参数item
完成显示.在父组件中使用template
是模板格式.
为什么要是用作用域插槽?
有时候一个子组件被多个父组件调用,每个父组件想呈现的样式不同,如果在子组件中设定死了代码复用性下降.
v-slot
语法
v-slot
指令自 Vue 2.6.0 起被引入,提供更好的支持 slot
和 slot-scope
特性的 API 替代方案。在接下来所有的 2.x 版本中 slot
和 slot-scope
特性仍会被支持,但已经被官方废弃且不会出现在 Vue 3 中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 原slot语法
<div slot="header"></div>
// 使用v-slot语法,或使用简写'#'
<div v-slot:header></div>
<div #header></div>
// 原 slot-scope 语法
<template slot-scope="listData">
<li> </li>
</template>
// 使用 v-slot 语法
<template v-slot="listData">
<li> </li>
</template>
或者可以将具名插槽和作用域插槽结合起来,如:
1
2
3
<template v-slot:footer="listData">
<li> </li>
</template>
一句话概括就是v-slot :后边是插槽名称,=后边是组件内部绑定作用域值的映射。
动态组件与v-once指令
动态组件
1
<component :is="type"></component>
通过is
判断调用哪个组件,is
传入子组件名.
v-once
指令
只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。当元素不随数据的变化而变化,可以加上这个.
1
2
<!-- 单个元素 -->
<span v-once>This will never change: </span>