Vue -- 可复用性
2018-10-21 本文已影响0人
Da_xiong
混入
- 通过mixins属性增加混入对象,格式为
[变量名]
。data以及值为对象的methods、components等会自动合并属性,相同则覆盖;钩子会合并,混入对象的钩子先执行。
var mixin = {
data: function () {
return {
message: 'hello',
foo: 'abc'
}
}
}
new Vue({
mixins: [mixin],
data: function () {
return {
message: 'goodbye',
bar: 'def'
}
},
created: function () {
console.log(this.$data) // => { message: "goodbye", foo: "abc", bar: "def" }
}
})
// 或者定义一个使用混入对象的组件
var Component = Vue.extend({
mixins: [myMixin]
})
var component = new Component() // => "hello from mixin!"
- 也可以全局定义混入对象,但会影响所有的实例,慎用。
// 为自定义的选项 'myOption' 注入一个处理器。
Vue.mixin({
created: function () {
var myOption = this.$options.myOption
if (myOption) {
console.log(myOption)
}
}
})
自定义指令
- 类似v-model和v-show,我们也可以自定义指令。(全局注册一般是
Vue.命令名
,局部是命令名s
)。
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
// 或者局部注册
directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus()
}
}
}
<input v-focus>
- 一个指令定义对象可以提供如下几个钩子函数 (均为可选):
- bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
- inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
- update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
- componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
- unbind:只调用一次,指令与元素解绑时调用。
- 指令钩子函数会被传入以下参数(除了
el
之外,其它参数都应该是只读的,切勿进行修改。如果需要在钩子之间共享数据,建议通过元素的dataset
来进行):-
el
:指令所绑定的元素,可以用来直接操作 DOM 。 -
binding
:一个对象,包含以下属性:
* `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 编译生成的虚拟节点。 -
oldVnode
:上一个虚拟节点,仅在update
和componentUpdated
钩子中可用。
-
- 函数简写:如果想要在 bind 和 update 时触发相同行为,而不关心其它的钩子,可以如下写法:
Vue.directive('color-swatch', function (el, binding) {
el.style.backgroundColor = binding.value
})
- 指令可以传入任意合法的js表达式,如对象字面量。
<div v-demo="{ color: 'white', text: 'hello!' }"></div>
Vue.directive('demo', function (el, binding) {
console.log(binding.value.color) // => "white"
console.log(binding.value.text) // => "hello!"
})
渲染函数
- render可以用js来写模板语法,如下面用level来拼接标签名,用template是做不到的。
Vue.component('anchored-heading', {
render: function (createElement) {
return createElement(
'h' + this.level, // tag name 标签名称
this.$slots.default // 子组件中的阵列
)
},
props: {
level: {
type: Number,
required: true
}
}
})
等同于如下,即用render替换了template:
Vue.component('anchored-heading', {
template: '#anchored-heading-template',
props: {
level: {
type: Number,
required: true
}
}
})
<script type="text/x-template" id="anchored-heading-template">
<h1 v-if="level === 1">
<slot></slot>
</h1>
<h2 v-else-if="level === 2">
<slot></slot>
</h2>
<h3 v-else-if="level === 3">
<slot></slot>
</h3>
<h4 v-else-if="level === 4">
<slot></slot>
</h4>
<h5 v-else-if="level === 5">
<slot></slot>
</h5>
<h6 v-else-if="level === 6">
<slot></slot>
</h6>
</script>
-
createElement(dom, descriptorObj, childNode)
第一个参数是最终的节点(可以为字符串/对象/异步函数);第二个参数是对节点的描述属性对象,可描述样式或attrs/on等(只能是对象);第三个是子节点(可以为字符串/数组)。其中他们的用到的Vnode也是createElement生成的。返回的都是虚拟节点(准确来说是虚拟节点的描述对象)。 -
this.$slot
可以用作createElement
第三个参数表示插入插槽,.default
获取匿名插槽,.name
获取具名插槽;this.$scopedSlots
可以指定属性描述对象。
render: function (createElement) {
// `<div><slot></slot></div>`
return createElement('div', this.$slots.default)
}
props: ['message'],
render: function (createElement) {
// `<div><slot :text="message"></slot></div>`
return createElement('div', [
this.$scopedSlots.default({
text: this.message
})
])
}
render: function (createElement) {
return createElement('div', [
createElement('child', {
// pass `scopedSlots` in the data object
// in the form of { name: props => VNode | Array<VNode> }
scopedSlots: {
default: function (props) {
return createElement('span', props.text)
}
}
})
])
}
插件
- vue可以通过全局的四种方法来开发插件,插件应当有一个公开的install方法:
MyPlugin.install = function (Vue, options) {
// 1. 添加全局方法或属性
Vue.myGlobalMethod = function () {
// 逻辑...
}
// 2. 添加全局资源
Vue.directive('my-directive', {
bind (el, binding, vnode, oldVnode) {
// 逻辑...
}
...
})
// 3. 注入组件
Vue.mixin({
created: function () {
// 逻辑...
}
...
})
// 4. 添加实例方法
Vue.prototype.$myMethod = function (methodOptions) {
// 逻辑...
}
}
- 插件通过全局方法
Vue.use(MyPlugin, { someOption: true })
来调用,第二个参数可选。Vue.use 会自动阻止多次注册相同插件,届时只会注册一次该插件。
过滤器
-
{{ message | filterA | filterB }}
将message作为filterA的参数,然后将filterA的结果作为filterB的参数;或者{{ message | filterA('arg1', arg2) }}
传入三个参数。