14-1.访问元素 & 组件
在某些情况下,可以使用这些手段。
访问根实例,$root
访问父组件实例,$parent
访问子组件实例, $refs[childComponentName]
TIP
$refs 只会在组件渲染完成之后生效,并且它们不是响应式的。
这仅作为一个用于直接操作子组件的“逃生舱”——你应该避免在模板或计算属性中访问 $refs。
在使用 $parent 时,只能父子组件通信,如果想要更深层级的通信,Vue 提供了依赖注入:
它用到了两个新的实例选项:provide 和 inject。
祖先组件内:
provide: function () {
return {
getMap: this.getMap
}
}任何后代组件内:
inject: ['getMap']14-2.程序化的事件侦听器
$on监听一个事件$off停止监听一个事件$once一次性监听一个事件
在某些场景下,能够更好的管理维护自己的模块代码:
mounted: function () {
var picker = new Pikaday({
field: this.$refs.input,
format: 'YYYY-MM-DD'
})
this.$once('hook:beforeDestroy', function () {
picker.destroy()
})
}TIP
Vue 的事件系统不同于浏览器的 EventTarget API。
尽管它们工作起来是相似的,但是 $emit、$on, 和 $off 并不是 dispatchEvent、addEventListener 和 removeEventListener 的别名。
14-3.循环引用
组件是可以在它们自己的模板中调用自身的。
name: 'stack-overflow',
template: '<div><stack-overflow></stack-overflow></div>'类似上述的组件将会导致 max stack size exceeded 错误,所以请确保递归调用是条件性的 (例如使用一个最终会得到 false 的 v-if)。
当通过 Vue.component 全局注册组件的时候,这个循环引用悖论会被自动解开。
但如果是通过 webpack 构建工具,就有可能遇见一个错误:
Failed to mount component: template or render function not defined.对应的解决办法是在生命周期钩子 beforeCreate 时才注册引用组件:
beforeCreate: function () {
this.$options.components.TreeFolderContents = require('./tree-folder-contents.vue').default
}也可以利用 webpack 的异步 import:
components: {
TreeFolderContents: () => import('./tree-folder-contents.vue')
}14-4.模板定义的替代品
Vue 定义模板的推荐方式有二:
template选项.vue单文件中的<template>元素。
除此以外,还有两种方式:
14-5.控制更新
利用 $forceUpdate
渲染普通的 HTML 元素在 Vue 中是非常快速的,但有的时候你可能有一个组件,这个组件包含了大量静态内容。
在这种情况下,你可以在根元素上添加 v-once attribute 以确保这些内容只计算一次然后缓存起来。