一.使用
(1)注册
1)全局注册
全局注册后,任何Vue实例都可以使用。
Vue.component ('my-component', {
//逃项
template : '<div>这里是组件的内容</div>'
})
my-component 就是注册的组件自定义标签名称,推荐使用小写加减号分割的形式命名。
template的 DOM 结构必须被一个元素包含, 如果直接写成 “这里是组件的内容”, 不带“<div></ div>”是无法渲染的。
2)局部注册
在Vue 实例中,使用 components选项可以局部注册组件,注册后的组件只有在该实例作用域下有效。组件中也可以使用components 选项来注册组件,使组件可以嵌套。
<div id="app">
<my-component></my-component>
</div>
<script>
var Child = {
template:'<div>局部注册组件的内容</div>'
}
var app = new Vue({
el:'#app',
components:{
'my-component':Child
}
})
</script>
(2)组件失效
Vue组件的模板在某些情况下会受到 HTML 的限制,比如<table>内规定只允许是<tr>、<td>、<th>等这些表格元素。所以在<table>内直接使用组件是无效的。这种情况下,可以使用特殊的is属性来挂载组件。
<div id="app">
<table>
<tbody is="my-component"></tbody>
</table>
</div>
<script>
Vue.component('my-component',{
template:'<div>这里是组件的内容</div>'
});
var app = new Vue({
el:'#app'
})
</script>
tbody 在渲染时 会被替换为组件的内容。常见的限制元素还有<ul>、<ol>、<select>
注意:如果使用的是字符串模板,是不受限制的,比如.vue单文件用法等。
(3)选项
除了 template 选项外,组件中还可以像 Vue 实例那样使用其他的选项,比如data、computed、methods等。但是在使用data时,和实例稍有区别,data必须是函数,然后将数据return出去。
<div id="app">
<my-component></my-component>
</div>
<script>
Vue.component('my-component',{
template:'<div>{{message}}</div>',
data:function(){
return{
message:'组件内容'
}
}
});
var app = new Vue({
el:'#app'
})
</script>
注意:必须return一个对象,否则无法保证每个组件都是自己私有变量。
二.传值
使用 props 传递数据
1)在组件中,使用选项 props来声明需要从父级接收的数据, props的值可以是两种,一种是字符串数组,一种是对象。
2)props 中声明的数据与组件 data 函数 return 的数据主要区别就是 props 来自父级,而 data中的是组件自己的数据,作用域是组件本身,这两种数据都可以在模板 template 及计算属性 computed和方法 methods 中使用。
3)由于HTML特性不区分大小写,当使用 DOM 模板时,驼峰命名 CcamelCase )的 props 名称要转为短横分隔命名(kebab-case ),例如
<div id="app" >
<my-component warning-text="提示信息"></my-component>
</div>
<script>
Vue.component ('my-component', {
props: [ 'warningText'],
template :'<div>{{ warningText }} </div>'
})
var app =new Vue({
el :'#app'
})
</script>
注意:如果使用的是字符串模板,仍然可以忽略这些限制。
4)有时候,传递的数据并不是直接写死的,而是来自父级的动态数据,这时可以使用指令 -bind来动态绑定 props 值,当父组件的数据变化时,也会传递给子组件。
5)如果你要直接传递数字、布尔值、数组、对象,而且不使用 v-bind ,传递的仅仅是字符串。
(6)单向数据流
父向子传递数据:
(7)数据验证
当 prop 需要验证时,就需要对象写法。
三 .组件通信
组件关系可分为父子组件通信、兄弟组件通信、跨级组件通信。
(1)子向父传递数据
1)当子组件需要向父组件传递数据时,就要用到自定义事件。v-on 除了监昕 DOM 事件外,还可以用于组件之间的自定义事件。
2)子组件用 $emit()来触发事件,父组件用$on()来监昕子组件的事件。父组件也可以直萨在子组件的自定义标签上使用 v-on 来监昕子组件触发的自定义事件。$emit()方法的第一个参数是自定义事件的名称,例如示例的increase和reduce ,其后面的参数都是要传递的数据,可以不填或填写多个。
3)除了用 v-on 在组件上监听自定义事件外,也可以监昕 DOM 事件,这时可以用 native 修饰符表示监听的是一个原生事件,监听的是该组件的根元素,示例代码如下:
(2)使用v-model
1)Vue2.x 可以在自定义组件上使用 v-model 指令。
2)组件$emit()的事件名是特殊的 input,在使用组件的父级,井没有在<my-component>上使用@input= handler”,而是直接用了v -model 绑定的一个数据total 。这也可以称作是一个语法糖,因为上面的示例可以间接地用自定义事件来实现。
3)v-model还可以用来创建自定义的表单输入组件 进行数据双向绑定。
(3)非父子组件通信
1)非父子组件一般有两种,兄弟组件和跨多级组件。
2)Vue.js 2.x 推荐使用一个空的 Vue 实例作为中央事件总线( bus),也就是一个中介。
3)父链
在子组件中,使用 this.$parent 可以直接访问该组件的父实例或组件,父组件也可以通过this.$children 访问它所有的子组件,而且可以递归向上或向下无线访问, 直到根实例或最内层的组件。示例代码如下:
尽管 Vue 允许这样操作,但在业务中,子组件应该尽可能地避免依赖父组件的数据,更不应该去主动修改它的数据,因为这样使得父子组件紧藕合,只看父组件,很难理解父组件的状态,因为它可能被任意组件修改,理想情况下,只有组件自己能修改它的状态。父子组件最好还是通过props和$emit 来通信。
4)子组件索引
当子组件较多时 通过 this.$children 来一一遍历出我们需要的一个组件实例是比较困难的,尤其是组件动态渲染时,它们的序列是不固定的。 Vue 提供了子组件索引的方法,用特殊的属性 ref 来为子组件指定一个索引名称,示例代码如下:
在父组件模板中,子组件标签上使用 ref 指定一个名称,井在父组件内通过 this.$refs 来访问指定名称的子组件。
注意:$refs只在组件渲染完成后才填充,并且它是非响应式的 它仅仅作为一个直接访问子组件的应急方案,应当避免在模板或计算属性中使用$refs。
四.使用slot分发内容
(1)用法
1)单个Slot
在子组件内使用特殊的<slot>元素就可以为这个子组件开启一个 slot (插槽),在父组件模板里,插入在子组件标签内的所有内容将替代子组件的<slot> 标签及它的内容。示例代码如下
子组件 child-component 模板内定义了一个<slot>元素,并且用一个< p>作为默认的内容,在父组件没有使用 slot 时,会渲染这段默认的文本;如果写入了 slot 那就会替换整个<slot> 。
注意:子组件<slot> 内的备用内容,它的作用域是子组件本身。
2) 具名slot
给<slot>元素指定一个 name 后可以分发多个内容,具名 slot 可以与单个 slot 共存.
子组件内声明了3个< slot>元素,其中在<div class=”main>内的< slot> 没有使用 name 特性,它将作为默认 slot 出现,父组件没有使用slot 特性的元素与内容都将出现在这里。如果没有指定默认的匿名slot ,父组件内多余的内容片段都将被抛弃。
(3)作用于插槽
1)概念
作用域插槽是一种特殊的 slot ,使用一个可以复用的模板替换己渲染元素。
(5)访问slot
Vue.js 2.x 提供了用来访问被 slot 分发的内容的方法 slots 请看下面的示例
通过 $slots 可以访问某个具名 slot, this.$slots.default 包括了所有没有被包含在具名 slot 中的节点。
五.组件高级用法
(1)递归组件
组件在它的模板内可以递归地调用自己,只要给组件设置 name 选项就可以了 。
设置 name 后,在组件模板内就可以递归使用了,不过需要注意的是,必须给 一个条件来限制递归数量,否则会抛出错误 max stack size exceeded。
组件递归使用可以用来开发一些具有未知层级关系的独立组件,比如级联选择器和树形控件等。
(2)内联模板
组件的模板一般都是在 template 选项内定义的,vue 提供了一个内联模板的功能,在使用组件时,给组件标签使用 inline- mplate 特性,组件就会把它的内容当作模板,而不是把它当内容分发,这让模板更灵活。示例代码如下
(3)动态组件
Vue.js 提供了一个特殊的元素<component> 用来动态地挂载不同的组件 使用 is 特性来选择要挂载的组件。
动态地改变 currentView 的值就可以动态挂载组件了。也可以直接绑定在组件对象上。
(4)异步组件
六. 其他
(1)$nextTick
1)异步更新队列
Vue 在观察到数据变化时并不是直接更新 DOM,而是开启一个队列,并缓冲在同一事件循环中发生的所有数据改变。在缓冲时会去除重复数据,从而避免不必要的计算和 DOM 操作。然后,在下一个事件循环 tick 中, Vue 刷新队列井执行实际(己去重的)工作。所以如果你用一个 for循环来动态改变数据 100 次,其实它只会应用最后一次改变,如果没有这种机制, DOM 就要重绘 100次,这固然是一个很大的开销。
2)Vue 会根据当前浏览器环境优先使用原生的 Promise.then 和 MutationObserver ,如果都不支持,就会采用 setTimeout 代替。
3)$nextTick 就是用来知道什么时候 DOM 更新完成的。
(2)X-Templates
(3)手动挂载实例