一、混入
一个混入对象可以包含任意组件选项,当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。
var myMixin = { ... } //定义一个混入对象
var Component = Vue.extend({
mixins:[myMixin] //定义一个使用混入对象的组件
})
1、选项合并
当组件和混入对象有同名选项时,选项将会合并,Vue.extend()
也使用同样的策略进行合并:
①数据会递归合并,发生冲突时以组件数据优先。
②同名钩子函数会合并成一个数组,所以都会被调用,且混入对象钩子先调用
③值为对象的选项,如methods
、components
和 directives,会被合并成一个对象,键名冲突时取组件的值。
2、全局混入
混入也可全局注册,一旦使用全局混入,就会影响每一个之后创建的Vue实例。
3、自定义选项合并策略
可以向Vue.config.optionMergeStrategies
添加一个函数:
Vue.config.optionMergeStrategies.myOption = function (toVal, fromVal) {
// 返回合并后的值
}
二、自定义指令
1、注册全局指令
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
2、注册局部指令:组件中接收一个directives的选项
directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus()
}
}
}
可以在模板中的任何元素上使用指令自定义指令 <input v-focus>
3、钩子函数
一个指令定义对象可以提供以下几个钩子函数:
bind:只调用一次,第一次绑定到元素时调用
inserted:被绑定元素插入父节点时调用
updata:VNode更新时调用
componentUpdata:指令所在组件的VNode及其子VNode全部更新后调用
unbind:指令与元素解绑时调用
钩子函数参数(el,binding,vnode,oldVnode),除了el,其他都是只读
Vue.directive('demo', { //demo指令名
bind: function (el, binding, vnode) { //bind函数
var s = JSON.stringify
el.innerHTML =
'name: ' + s(binding.name) + '<br>' + //bingding的属性name,指令名
'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(', ')
}
})
4、动态指令参数
指令的参数可以是动态的。例如,在 v-mydirective:[argument]="value"
中,argument
参数可以根据组件实例数据进行更新!
5、对象字面量
如果指令需要多个值,可以传入一个 JavaScript 对象字面量。
<div v-demo="{ color: 'white', text: 'hello!' }"></div>
三、渲染函数render&JSX
在vue开发需要动态的生成页面,就是render函数,有时使用render比使用slot效率更高
Vue.component('anchored-heading', {
render: function (createElement) {
return createElement(
'h' + this.level, // 标签名称
this.$slots.default // 子节点数组
)
},
props: {
level: {
type: Number,
required: true
}
}
})
1、渲染函数render
return createElement('h1',this,blogTitle)
createElement会返回一个createNodeDescription,包含需要渲染的节点和子节点描述,称为虚拟节点VNode
(1)createElement参数
({标签、组件选项对象、函数},{数据对象可选},{子级VNode可选})
数据对象,{'class’:{ },style:{ },attrs:{普通的HTML特性},props:{组件prop},domProps:{DOM属性},
on:{事件监听},directives:[{自定义指令}],...}
(2)约束
组件树中的所有 VNode 必须是唯一的。可以使用工厂函数来重复很多次元素/组件
render: function (createElement) {
return createElement('div',
Array.apply(null, { length: 20 }).map(function () {
return createElement('p', 'hi')
})
)
}
(3)事件&按键修饰符
对于修饰符, 有前缀 可用于on
.passiv &
.capture !
.once ~
.caputure.once ~!
(4)插槽
可以通过this.$slots访问静态插槽的内容,每个插槽都是一个VNode数组
render: function (createElement) {
// `<div><slot></slot></div>`
return createElement('div', this.$slots.default)
}
也可以通过this.$scopeSlots访问作用域插槽,每个作用域插槽都是一个返回若干VNode的函数
props: ['message'],
render: function (createElement) {
// `<div><slot :text="message"></slot></div>`
return createElement('div', [
this.$scopedSlots.default({
text: this.message
})
])
}
可以用VNode数据对象中的scopedSlots字段,用渲染函数向子组件传递作用域插槽
2、JSX
Babel插件用于在Vue中使用JSX语法,
import AnchoredHeading from './AnchoredHeading.vue'
new Vue({
el: '#demo',
render: function (h) { //h为createElement的别名
return (
<AnchoredHeading level={1}>
<span>Hello</span> world!
</AnchoredHeading>
)
}
})
3、函数式组件
一个组件没有管理、监听状态,没有生命周期方法,只接受一些prop的函数,可标记为functional,函数式组件
Vue.component('my-component', {
functional: true, // Props 是可选的
props: { // ... },
render: function (createElement, context) { }})
在添加functional: true
之后,需要更新渲染函数,为其增加 context
参数,并将 this.$slots.default
更新为 context.children
,然后将 this.level
更新为 context.props.level
。
四、插件
1、插件的功能:
①添加全局方法或者属性 ②添加全局资源 ③全局混入来添加一些组件选项 ④添加Vue实例方法
2、使用插件
通过Vue.use( )使用插件,Vue.use(插件名,{可选的选项对象}),在调用new Vue()启动应用前完成。
Vue.use
会自动阻止多次注册相同插件。在webpack 提供的 CommonJS 模块环境中,应始终显式地调用 Vue.use()
3、开发插件
Vue.js 的插件应该暴露一个 install
方法。这个方法的第一个参数是 Vue
构造器,第二个参数是一个可选的选项对象
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) { ... }}
五、过滤器
过滤器可以用在两个地方:双花括号插值和 v-bind
表达式
可以在一个组件的选项中定义本地过滤器filters:{ },或者在创建Vue实例前全局定义过滤器Vue.filter( )
Vue.filter('capitalize', function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1) })
全局和局部过滤器重名时,采用局部过滤器。
过滤器函数总接收表达式的值 (之前的操作链的结果) 作为第一个参数。
过滤器可以串联{{ message | filterA | filterB }} message传入过滤器A,再传入B