混入
基础
混入 (mixin
) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能
。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。
当组件和混入对象含有同名选项时,这些选项将以恰当的方式进行“合并”。比如,数据对象在内部会进行递归合并,并在发生冲突时以组件数据优先。
同名钩子函数将合并为一个数组,因此都将被调用。另外,混入对象的钩子将在组件自身钩子之前调用。
1 | var mixin = { |
值为对象的选项,例如 methods
、components
和 directives
,将被合并为同一个对象。两个对象键名冲突时,取组件对象的键值对
。
全局混入
混入也可以进行全局注册。使用时格外小心!一旦使用全局混入,它将影响每一个之后创建的 Vue 实例。使用恰当时,这可以用来为自定义选项注入处理逻辑。
1 | // 为自定义的选项 'myOption' 注入一个处理器。 |
请谨慎使用全局混入,因为它会影响每个单独创建的 Vue 实例 (包括第三方组件)。大多数情况下,只应当应用于自定义选项,就像上面示例一样。推荐将其作为插件发布,以避免重复应用混入。
自定义选项合并策略
自定义选项将使用默认策略,即简单地覆盖已有值。如果想让自定义选项以自定义逻辑合并,可以向 Vue.config.optionMergeStrategies
添加一个函数:
1 | const merge = Vue.config.optionMergeStrategies.computed |
自定义命令
自定义指令
全局注册
1 | // 注册一个全局自定义指令 `v-focus` |
局部注册
1 | export default{ |
钩子函数
一个指令定义对象可以提供如下几个钩子函数 (均为可选):
bind
:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。inserted
:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。update
:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 。componentUpdated
:指令所在组件的 VNode 及其子 VNode 全部更新后调用。unbind
:只调用一次,指令与元素解绑时调用。钩子函数参数
指令钩子函数会被传入以下参数:el
:指令所绑定的元素,可以用来直接操作 DOM。binding
:一个对象,包含以下 property:
name
:指令名,不包括v-
前缀。
value
:指令的绑定值,例如:v-my-directive="1 + 1"
中,绑定值为 2。
oldValue
:指令绑定的前一个值,仅在update
和componentUpdated
钩子中可用。无论值是否改变都可用。
expression
:字符串形式的指令表达式。例如v-my-directive="1 + 1"
中,表达式为"1 + 1"
。
arg
:传给指令的参数,可选。例如v-my-directive:foo
中,参数为"foo"
。
modifiers
:一个包含修饰符的对象。例如:v-my-directive.foo.bar
中,修饰符对象为{ foo: true, bar: true }
。vnode
:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。oldVnode
:上一个虚拟节点,仅在update
和componentUpdated
钩子中可用。除了 el 之外,其它参数都应该是只读的,切勿进行修改。如果需要在钩子之间共享数据,建议通过元素的
dataset
来进行。
这是一个使用了这些 property 的自定义钩子样例:1
<div id="hook-arguments-example" v-demo:foo.a.b="message"></div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19Vue.directive('demo', {
bind: function (el, binding, vnode) {
var s = JSON.stringify
el.innerHTML =
'name: ' + s(binding.name) + '<br>' +
'value: ' + s(binding.value) + '<br>' +
'expression: ' + s(binding.expression) + '<br>' +
'argument: ' + s(binding.arg) + '<br>' +
'modifiers: ' + s(binding.modifiers) + '<br>' +
'vnode keys: ' + Object.keys(vnode).join(', ')
}
})
new Vue({
el: '#hook-arguments-example',
data: {
message: 'hello!'
}
})- 动态指令参数*
指令的参数可以是动态的。例如,在v-mydirective:[argument]="value"
中,argument
参数可以根据组件实例数据进行更新!这使得自定义指令可以在应用中被灵活使用。函数简写
在很多时候,你可能想在bind
和update
时触发相同行为,而不关心其它的钩子。比如这样写:1
2
3Vue.directive('color-swatch', function (el, binding) {
el.style.backgroundColor = binding.value
})对象字面量
如果指令需要多个值,可以传入一个 JavaScript 对象字面量。记住,指令函数能够接受所有合法的 JavaScript 表达式。1
<div v-demo="{ color: 'white', text: 'hello!' }"></div>
1
2
3
4Vue.directive('demo', function (el, binding) {
console.log(binding.value.color) // => "white"
console.log(binding.value.text) // => "hello!"
})渲染函数与JSX
1
2
3
4
5
6
7
8
9
10
11
12
13
14Vue.component('anchored-heading', {
render: function (createElement) {
return createElement(
'h' + this.level, // 标签名称
this.$slots.default // 子节点数组
)
},
props: {
level: {
type: Number,
required: true
}
}
})虚拟 DOM
Vue 通过建立一个虚拟 DOM 来追踪自己要如何改变真实 DOM。请仔细看这行代码:1
return createElement('h1', this.blogTitle)
createElement
到底会返回什么呢?其实不是一个实际的 DOM 元素。它更准确的名字可能是 createNodeDescription,因为它所包含的信息会告诉 Vue 页面上需要渲染什么样的节点,包括及其子节点的描述信息。我们把这样的节点描述为“虚拟节点 (virtual node)”,也常简写它为“VNode”。“虚拟 DOM”是我们对由 Vue 组件树建立起来的整个 VNode 树的称呼。createElement
参数
- 一个 HTML 标签名、组件选项对象,或者resolve 了上述任何一种的一个 async 函数。必填项。
- 一个与模板中 attribute 对应的数据对象。可选。
- 子级虚拟节点 (VNodes),由
createElement()
构建而成,也可以使用字符串来生成“文本虚拟节点”。可选。
见官方文档
插件
使用插件
通过全局方法 Vue.use()
使用插件。它需要在你调用 new Vue()
启动应用之前完成:Vue.use
会自动阻止多次注册相同插件,届时即使多次调用也只会注册一次该插件。
开发插件
Vue.js 的插件应该暴露一个 install
方法。这个方法的第一个参数是 Vue 构造器,第二个参数是一个可选的选项对象:
1 | MyPlugin.install = function (Vue, options) { |
过滤器
Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind
表达式 (后者从 2.1.0+ 开始支持)。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符号指示:
1 | <!-- 在双花括号中 --> |
你可以在一个组件的选项中定义本地的过滤器
(局部):
1 | filters: { |
或者在创建 Vue 实例之前全局定义过滤器
:
1 | Vue.filter('capitalize', function (value) { |
当全局过滤器和局部过滤器重名时,会采用局部过滤器。
过滤器可以串联:
1 | {{ message | filterA | filterB }} |
在这个例子中,filterA
被定义为接收单个参数的过滤器函数,表达式 message
的值将作为参数传入到函数中。然后继续调用同样被定义为接收单个参数的过滤器函数 filterB
,将 filterA
的结果传递到 filterB
中。
过滤器是 JavaScript 函数,因此可以接收参数:
1 | {{ message | filterA('arg1', arg2) }} |
这里,filterA 被定义为接收三个参数的过滤器函数。其中 message
的值作为第一个参数,普通字符串 'arg1'
作为第二个参数,表达式 arg2
的值作为第三个参数。