可复用性&组合
混入
-
基础知识点
混入可以用来分发 Vue 组件中的可复用功能,一个混入对象可以包含任意组件选项。当组件使用混入对象时,混入对象的所有选项都会进入到该组件中
-
选项合并的注意点
在组件和混入对象含有同名选项发生冲突时,
- 会以组件数据优先的策略进行合并
- 同名的钩子函数都会被调用,混入对象的钩子会在组件自身钩子之前调用
- 值为对象的选项时,将会被合并为同一个对象,在对象的键名发生冲突时,取组件对象的键值对
-
自定义选项合并策略
自定义选项将使用默认策略,也可以让自定义选项以自定义逻辑合并,可以在
Vue.config.optionMergeStrategies添加一个函数:Vue.config.optionMergeStrategies.myOption = function (toVal, fromVal) { // 返回合并后的值 }
自定义指令
-
基本知识点
注册一个全局自定义指令:
Vue.directive('focus', { // 当被绑定的元素插入到 DOM 中时…… inserted: function (el) { // 聚焦元素 el.focus() } })注册一个局部指令:
directives: { focus: { // 指令的定义 inserted: function (el) { el.focus() } } } -
自定义指令的钩子函数
bind: 只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置inserted:被绑定元素插入父节点时调用(仅保证父节点存在,但不一定已被插入文档中)update: 所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有,可以通过比较更新前后的值来忽略不必要的模板更新componentUpdated: 指令所在组件的 VNode 及其子 VNode 全部更新后调用unbind: 只调用一次,指令与元素解绑时调用 -
钩子函数参数
el: 指令所绑定的元素,可以用来直接操作 DOMbinding: 一个对象,包含以下 property1. `name`: 指令名,不包括 `v-` 前缀 2. `value`: 指令的绑定值 3. `oldValue`: 指令绑定的前一个值,仅在 `update` 和 `componentUpdated` 钩子中可用 4. `expression`: 字符串形式的指令表达式 5. `arg`: 传给指令的参数 6. `modifiers`: 一个包含修饰符的对象vnode: Vue 编译生成的虚拟节点oldVnode: 上一个虚拟节点,仅在update和componentUpdated钩子中可用注意: 除了
el之外,其他参数都应该是只读的,尽量不要去修改 -
动态指令参数知识点
指令的参数可以是动态的。
v-mydirective:[argument] = "value"中,argument参数可以根据组件实例数据进行更新,在binding对象中可以通过arg来获得这个动态的参数 -
函数简写
在只关系
bind和update钩子,且两者触发相同的行为的情况下,可以进行函数的简写,如:Vue.directive('color-swatch', function (el, binding) { el.style.backgroundColor = binding.value })
渲染函数
-
基础知识点
渲染函数能够比模板更接近编译器,能够使用 JavaScript 的完全编程的能力,渲染函数的基本使用如下:
render: function (createElement) { return createElement('h1', this.blogTitle) } -
虚拟 DOM
Vue 通过建立一个虚拟 DOM来追踪如何改变真实DOM
createElement返回的不是一个实际的 DOM 元素,它创建的是虚拟节点,它所包含的信息会告诉 Vue 页面上应该渲染的节点类型等,包括其子节点的描述信息 -
createElement参数第一个参数: String | Object | Function,一个 HTML 标签名、组件选项对象或者 resolve 了上述任何一种的一个 async函数 (必填)
第二个参数: 一个与模板中 attribute 对象的数据对象 (可选)
第三个参数: String | Array,子级虚拟节点,由 createElement() 构建而成,也可以使用字符串来生成“文本虚拟节点”
-
createElement 数据对象参数注意点
on: { click: this.clickHandler }: 事件监听器在on内, 它不再支持v-on:keyup.enter这样的修饰器了nativeOn: { click: this.nativeClickHandler }: 仅用于组件,用于监听原生事件,而不是组件内部使用,vm.$emit触发的事件{ name: props => VNode | Array<VNode> }: 作用域插槽的格式slot: 'name-of-slot': 如果组件是其它组件的子组件,需要为插槽指定名称 -
渲染函数的约束
VNode 必须是唯一的! 组件数中的所有 VNode 必须是唯一的,如果想创建重复的多个元素/组件,可以使用工厂函数来实现,示例如下:
render: function (createElement) { return createElement('div', Array.apply(null, { length: 20 }).map(function () { return createElement('p', 'hi') }) ) } -
使用JavaScript代替模板功能知识点
只要在原生的 JavaScript 中可以轻松完成的操作, Vue 的渲染函数就不会提供专有的替代方法
v-if 和 v-for:可以使用
if/else和map来实现相关的功能v-model: 渲染函数中没有与
v-model的直接对应,需要自己实现相应的逻辑事件&按键修饰符: 对于
.passive、.capture和.once这些事件修饰符,可以在事件前面使用对应的前缀.passive=>&.capture=>!.once=>~,其它的修饰符,可以通过在事件处理函数中使用对应的事件方法来解决插槽: 可以通过
this.$slots来访问静态插槽的内容,每个插槽都是一个虚拟节点数组,也可以通过this.$scopedSlots访问作用域插槽,每个作用域插槽都是一个返回若干 VNode 的函数,如果要用渲染函数向子组件中传递作用域插槽,可以利用虚拟节点数据对象中的scopedSlots字段 -
JSX
需要使用一个 Babel插件,用于在 Vue 中使用 JSX语法,它可以回到更接近于模板的语法中,示例如下:
import AnchoredHeading from './AnchoredHeading.vue' new Vue({ el: '#demo', render: function (h) { return ( <AnchoredHeading level={1}> <span>Hello</span> world! </AnchoredHeading> ) } })注意: 将
h作为createElement的别名是 Vue 生态系统中的一个通用惯例 -
函数式组件知识点
一个组件如果没有管理任何状态,也没有监听任何传递给它的状态,也没有生命周期方法,只接收一些 prop 的函数,这样的组件成为
functional,它没有响应式数据,也没有实例,没有this上下文Vue.component('my-component', { functional: true, props: { // ... }, render: function (createElement, context) { // ... } })组件需要的一切都是通过
context参数传递的,该对象有如下字段:prop: 提供所有 prop 的对象children: VNode 子节点的数组slots: 一个函数,返回了包含所有插槽的对象scopedSlots: 一个暴露传入的作用域插槽的对象。也以函数形式暴露普通插槽data: 传递给组件的整个数据对象,作为createElement的第二个参数传入组件parent: 对父组件的引用listeners: 一个包含了所有父组件为当前组件注册的事件监听器的对象injections: 如果使用了inject选项,则该对象包含了应当被注入的 property函数式组件的好处在于它只是函数,所以渲染开销也低很多
函数式组件可以程序化地在多个组件中选择一个进行渲染,也可以在将
children、props、data传递给子组件之前操作它们在函数式组件中,需要显示定义将没有被定义为 prop 的 attribute 添加到组件的根元素上,如果是在
createElement中,可以通过context.data context.children来传递 attribute、事件监听器、子节点等,如果是在基于模板的函数式组件中,可以使用data.attrs来传递任何 HTML 属性,也可以使用listeners(data.on的别名)传递任何事件监听器
插件
-
基本知识点
插件通常用来为 Vue 添加全局功能,插件的功能范围没有严格的限制,一般用于 1.添加全局方法或者 property 2.添加全局资源:指令/过滤器/过渡等 3.通过全局混入来添加一些组件选项 4.添加 Vue 实例方法,通过把它们添加到
Vue.propertype上实现 5.一个库,提供自己的 API,同时提供上面提到的一个或多个功能 -
使用注意点
全局方法
Vue.use()需要在new Vue()启动之前使用插件Vue.use会自动阻止多次注册相同插件,即使是多次调用也只会注册一次该插件 -
开发插件知识点
插件需要暴露一个
install方法,这个方法的第一个参数是Vue构造器,第二个参数是一个可选的选项对象// 1. 添加全局方法或 property Vue.myMethod = function() { ... } // 2. 添加全局资源 Vue.directive('my-directive', { bind(el, binding, vnode, oldVnode) { ... } ... }) // 3. 使用混入 Vue.mixin({ created() { ... } ... }) // 4. 添加实例方法 Vue.prototype.demo = () => { ... }
过滤器
可以通过自定义过滤器,来对一些常见的文本格式化,过滤器可以在两个地方进行使用:双花括号插值和 v-bind 表达式。过滤器在使用时,需要通过管道符(|)来添加到 JS表达式的尾部
-
过滤器的定义
局部过滤器的定义:
filters: { filterName: function(value) { ... return } }全局过滤器的定义:
Vue.filter('filterName', function(value) { ... return })