针对Vue文档中部分大家可能不会去研读的内容,我做了个小总结,作为有经验者的快餐,不是特别适合初学者,可能有不妥之处,希望大家多提建议。
节省代码量的mixin
mixin概念:组件级可复用逻辑,包括数据变量/生命周期钩子/公共方法,从而在混入的组件中可以直接使用,不用重复写冗余逻辑(类似继承)
使用方法:
在某一公共文件夹pub下创建mixin文件夹,其下创建mixinTest.js
const mixinTest = { created() { console.log(`components ${this.name} created`) }, methods: { hello() { console.log('mixin method hello') } } } export default mixinTest
在组件中引用刚才的公共混入文件并使用
import mixinTest from '../pub/mixin/mixinTest.js' export default { data() { return { name: 'hello' } }, mixins: [mixinTest], methods: { useMixin() { this.hello() } } }
ps: 若是使用Vue.mixin()这个方法,则会影响之后创建的所有Vue示例,慎用!
注意mixin的几个特性:
混入的数据变量是浅合并,冲突时以组件内的数据优先(对象里面的自定义变量)
混入的生命周期函数内的逻辑会与组件内定义的生命周期函数逻辑进行合并,并且先执行(created/mounted/destroy)
混入的值为对象的选项,会混合成一个对象,冲突后也是以组件内键名优先(data/method/components/directives)
slot内容分发
slot概念引入:Vue跟React在写法上的不同就在于组件与子组件内部元素的组织上,在组件里面没有children元素供我们访问和展现(暂不考虑render函数),取而代之的API是slot
使用场景定义:
自定义的子组件里面有嵌套的HTML或者其他自定义的标签组件
这个自定义的子组件是写在父组件里面,嵌套的东西也放在父组件里面
通过在子组件的模板里面使用<slot></slot>标签,从而达到渲染写在父组件里的嵌套标签的效果
本质是把父组件放在子组件里的内容,插到了子组件的位置,多个标签也会一起被插入
<template> <div> <self-component> <!--self-component表示自定义的组件--> <span>12345</span> <!--父组件里的嵌套标签--> </self-component> </div> </template> <script> export default { components: [selfComponent] } </script> <!--self-component的组件模板--> <template> <div> <button><slot></slot></button> </div> </template> <script> export default { // 只有子组件的模板里面有slot标签,才能取到写在自定义组件里面的标签的渲染引用 } </script>
slot特性的进阶两点:
slot插入内容的编译作用域:被分发的内容的作用域,根据其所在模板决定
具体内容写的位置,决定了编译的作用域(大部分情况都是在父组件作用域下)
2.1.0+新增作用域插槽,从而可以把子组件的属性暴露给父组件中写在子组件内的内容使用
子组件中的slot标签可以直接写自定义属性,然后父组件写在slot中的标签加上slot-scope属性
<!-- 父组件模板 --> <child :items="items"> <!-- 作用域插槽也可以是具名的 --> <li slot="item" slot-scope="props">{{ props.text }}</li> </child> <!-- 子组件模板 --> <ul> <slot v-for="item in items" :text="item.text"> <!-- 这里写当父组件引用子组件但没写内部内容时展示的东东 --> </slot> </ul>
slot的name属性来指定标签插入的位置,也就是文档里面的具名插槽(这个官方文档说的明白)
在子组件的模板里面写的slot有个name属性(<slot></slot>)
在父组件中写子组件里面的插槽内容,指明slot属性(<p slot="foo">123</p>)
父组件的内容就会对应slot==name放到正确的位置
没有指明slot属性的就会默认放到匿名插槽的位置上
动态组件
动态组件这个特性,很多人写的Vue项目也不少,但也没用到过这个,有必要多说几句
动态组件适用情况:
单页应用,部分组件的切换不涉及路由,只是页面有一块区域的组件要变更
变更的组件参数定义上是一致的,比如都是对话框,要传一个对象进去,但对象里面的数据结构不同
通过使用component的is属性,避免在template中的冗余组件代码,避免多个v-if模板代码更加整洁
使用的方法(借鉴文档):
<keep-alive> <component v-bind:is="currentView"> <!-- 组件在 vm.currentview (对应组件名称)变化时改变! --> <!-- 非活动组件将被缓存!可以保留它的状态或避免重新渲染 --> </component> </keep-alive>
注意点:
动态切换的组件都要引入到父组件中,渲染是动态的,但引入不是。
<keep-alive>包裹动态组件时,会缓存不活动的组件实例,提高性能,避免重复渲染(keep-alive不会渲染额外DOM结构)
<keep-alive>有include和exclude这两个属性,用于指定缓存和不缓存的组件(传入字符串/数组/正则)
另一种避免重新渲染的方法是为标签增加属性v-once,用于缓存大量的静态内容,避免重复渲染。
ps:<keep-alive>不会在函数式组件中正常工作,因为它们没有缓存实例。
动画与过渡