vue 进阶
render 函数
Vue.component('anchored-heading', {render: function (createElement) {return createElement('h' + this.level, // tag name 标签名称this.$slots.default // 子组件中的阵列)},props: {level: {type: Number,required: true}}})
createElement 参数
// @returns {VNode}createElement(// {String | Object | Function}// 一个 HTML 标签,组件选项,或一个函数// 必须 Return 上述其中一个'div',// {Object}// 一个对应属性的数据对象// 您可以在 template 中使用.可选项.{// (下一章,将详细说明相关细节)},// {String | Array}// 子节点(VNodes). 可选项.[createElement('h1', 'hello world'),createElement(MyComponent, {props: {someProp: 'foo'}}),'bar'])
有一件事要注意:在 templates 中,v-bind:class 和 v-bind:style ,会有特别的处理,他们在 VNode 数据对象中,为最高级配置。
{// 和`v-bind:class`一样的 API'class': {foo: true,bar: false},// 和`v-bind:style`一样的 APIstyle: {color: 'red',fontSize: '14px'},// 正常的 HTML 特性attrs: {id: 'foo'},// 组件 propsprops: {myProp: 'bar'},// DOM 属性domProps: {innerHTML: 'baz'},// 事件监听器基于 "on"// 所以不再支持如 v-on:keyup.enter 修饰器// 需要手动匹配 keyCode。on: {click: this.clickHandler},// 仅对于组件,用于监听原生事件,而不是组件使用 vm.$emit 触发的事件。nativeOn: {click: this.nativeClickHandler},// 自定义指令. 注意事项:不能对绑定的旧值设值// Vue 会为您持续追踨directives: [{name: 'my-custom-directive',value: '2'expression: '1 + 1',arg: 'foo',modifiers: {bar: true}}],// Scoped slots in the form of// { name: props => VNode | Array<VNode> }scopedSlots: {default: props => h('span', props.text)},// 如果子组件有定义 slot 的名称slot: 'name-of-slot'// 其他特殊顶层属性key: 'myKey',ref: 'myRef'}
在添加 functional: true 之后,锚点标题组件的 render 函数之间简单更新增加 context 参数,this.$slots.default 更新为 context.children,之后this.level 更新为 context.props.level。
var EmptyList = { /* ... */ }var TableList = { /* ... */ }var OrderedList = { /* ... */ }var UnorderedList = { /* ... */ }Vue.component('smart-list', {functional: true,render: function (createElement, context) {function appropriateListComponent () {var items = context.props.itemsif (items.length === 0) return EmptyListif (typeof items[0] === 'object') return TableListif (context.props.isOrdered) return OrderedListreturn UnorderedList}return createElement(appropriateListComponent(),context.data,context.children)},props: {items: {type: Array,required: true},isOrdered: Boolean}})
- 自定义指令
// 注册一个全局自定义指令 v-focusVue.directive('focus', {// 当绑定元素插入到 DOM 中。inserted: function (el) {// 聚焦元素el.focus()}})
也可以注册局部指令,组件中接受一个 directives 的选项:
directives: {focus: {// 指令的定义---}}
然后你可以在模板中任何元素上使用新的 v-focus 属性:
<input v-focus>
钩子函数
指令定义函数提供了几个钩子函数(可选):
bind: 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。inserted: 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。update: 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新(详细的钩子函数参数见下)。componentUpdated: 被绑定元素所在模板完成一次更新周期时调用。unbind: 只调用一次, 指令与元素解绑时调用。
接下来我们来看一下钩子函数的参数 (包括 el,binding,vnode,oldVnode) 。
- 混合是一种灵活的分布式复用 Vue 组件的方式。混合对象可以包含任意组件选项。以组件使用混合对象时,所有混合对象的选项将被混入该组件本身的选项。
// 定义一个混合对象var myMixin = {created: function () {this.hello()},methods: {hello: function () {console.log('hello from mixin!')}}}// 定义一个使用混合对象的组件var Component = Vue.extend({mixins: [myMixin]})var component = new Component() // -> "hello from mixin!"
值为对象的选项,例如 methods, components 和 directives,将被混合为同一个对象。 两个对象键名冲突时,取组件对象的键值对。
var mixin = {methods: {foo: function () {console.log('foo')},conflicting: function () {console.log('from mixin')}}}var vm = new Vue({mixins: [mixin],methods: {bar: function () {console.log('bar')},conflicting: function () {console.log('from self')}}})vm.foo() // -> "foo"vm.bar() // -> "bar"vm.conflicting() // -> "from self"
注意: Vue.extend() 也使用同样的策略进行合并。
