vue 进阶

  • render 函数
  1. Vue.component('anchored-heading', {
  2. render: function (createElement) {
  3. return createElement(
  4. 'h' + this.level, // tag name 标签名称
  5. this.$slots.default // 子组件中的阵列
  6. )
  7. },
  8. props: {
  9. level: {
  10. type: Number,
  11. required: true
  12. }
  13. }
  14. })

createElement 参数

  1. // @returns {VNode}
  2. createElement(
  3. // {String | Object | Function}
  4. // 一个 HTML 标签,组件选项,或一个函数
  5. // 必须 Return 上述其中一个
  6. 'div',
  7. // {Object}
  8. // 一个对应属性的数据对象
  9. // 您可以在 template 中使用.可选项.
  10. {
  11. // (下一章,将详细说明相关细节)
  12. },
  13. // {String | Array}
  14. // 子节点(VNodes). 可选项.
  15. [
  16. createElement('h1', 'hello world'),
  17. createElement(MyComponent, {
  18. props: {
  19. someProp: 'foo'
  20. }
  21. }),
  22. 'bar'
  23. ]
  24. )

有一件事要注意:在 templates 中,v-bind:classv-bind:style ,会有特别的处理,他们在 VNode 数据对象中,为最高级配置。

  1. {
  2. // 和`v-bind:class`一样的 API
  3. 'class': {
  4. foo: true,
  5. bar: false
  6. },
  7. // 和`v-bind:style`一样的 API
  8. style: {
  9. color: 'red',
  10. fontSize: '14px'
  11. },
  12. // 正常的 HTML 特性
  13. attrs: {
  14. id: 'foo'
  15. },
  16. // 组件 props
  17. props: {
  18. myProp: 'bar'
  19. },
  20. // DOM 属性
  21. domProps: {
  22. innerHTML: 'baz'
  23. },
  24. // 事件监听器基于 "on"
  25. // 所以不再支持如 v-on:keyup.enter 修饰器
  26. // 需要手动匹配 keyCode。
  27. on: {
  28. click: this.clickHandler
  29. },
  30. // 仅对于组件,用于监听原生事件,而不是组件使用 vm.$emit 触发的事件。
  31. nativeOn: {
  32. click: this.nativeClickHandler
  33. },
  34. // 自定义指令. 注意事项:不能对绑定的旧值设值
  35. // Vue 会为您持续追踨
  36. directives: [
  37. {
  38. name: 'my-custom-directive',
  39. value: '2'
  40. expression: '1 + 1',
  41. arg: 'foo',
  42. modifiers: {
  43. bar: true
  44. }
  45. }
  46. ],
  47. // Scoped slots in the form of
  48. // { name: props => VNode | Array<VNode> }
  49. scopedSlots: {
  50. default: props => h('span', props.text)
  51. },
  52. // 如果子组件有定义 slot 的名称
  53. slot: 'name-of-slot'
  54. // 其他特殊顶层属性
  55. key: 'myKey',
  56. ref: 'myRef'
  57. }

在添加 functional: true 之后,锚点标题组件的 render 函数之间简单更新增加 context 参数,this.$slots.default 更新为 context.children,之后this.level 更新为 context.props.level。

  1. var EmptyList = { /* ... */ }
  2. var TableList = { /* ... */ }
  3. var OrderedList = { /* ... */ }
  4. var UnorderedList = { /* ... */ }
  5. Vue.component('smart-list', {
  6. functional: true,
  7. render: function (createElement, context) {
  8. function appropriateListComponent () {
  9. var items = context.props.items
  10. if (items.length === 0) return EmptyList
  11. if (typeof items[0] === 'object') return TableList
  12. if (context.props.isOrdered) return OrderedList
  13. return UnorderedList
  14. }
  15. return createElement(
  16. appropriateListComponent(),
  17. context.data,
  18. context.children
  19. )
  20. },
  21. props: {
  22. items: {
  23. type: Array,
  24. required: true
  25. },
  26. isOrdered: Boolean
  27. }
  28. })
  • 自定义指令
  1. // 注册一个全局自定义指令 v-focus
  2. Vue.directive('focus', {
  3. // 当绑定元素插入到 DOM 中。
  4. inserted: function (el) {
  5. // 聚焦元素
  6. el.focus()
  7. }
  8. })

也可以注册局部指令,组件中接受一个 directives 的选项:

  1. directives: {
  2. focus: {
  3. // 指令的定义---
  4. }
  5. }

然后你可以在模板中任何元素上使用新的 v-focus 属性:

  1. <input v-focus>

钩子函数
指令定义函数提供了几个钩子函数(可选):

bind: 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。
inserted: 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。
update: 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新(详细的钩子函数参数见下)。
componentUpdated: 被绑定元素所在模板完成一次更新周期时调用。
unbind: 只调用一次, 指令与元素解绑时调用。
接下来我们来看一下钩子函数的参数 (包括 elbindingvnodeoldVnode) 。

  • 混合是一种灵活的分布式复用 Vue 组件的方式。混合对象可以包含任意组件选项。以组件使用混合对象时,所有混合对象的选项将被混入该组件本身的选项。
  1. // 定义一个混合对象
  2. var myMixin = {
  3. created: function () {
  4. this.hello()
  5. },
  6. methods: {
  7. hello: function () {
  8. console.log('hello from mixin!')
  9. }
  10. }
  11. }
  12. // 定义一个使用混合对象的组件
  13. var Component = Vue.extend({
  14. mixins: [myMixin]
  15. })
  16. var component = new Component() // -> "hello from mixin!"

值为对象的选项,例如 methods, componentsdirectives,将被混合为同一个对象。 两个对象键名冲突时,取组件对象的键值对。

  1. var mixin = {
  2. methods: {
  3. foo: function () {
  4. console.log('foo')
  5. },
  6. conflicting: function () {
  7. console.log('from mixin')
  8. }
  9. }
  10. }
  11. var vm = new Vue({
  12. mixins: [mixin],
  13. methods: {
  14. bar: function () {
  15. console.log('bar')
  16. },
  17. conflicting: function () {
  18. console.log('from self')
  19. }
  20. }
  21. })
  22. vm.foo() // -> "foo"
  23. vm.bar() // -> "bar"
  24. vm.conflicting() // -> "from self"

注意: Vue.extend() 也使用同样的策略进行合并。