ber*_*nie 5 javascript vue.js vuejs2
Vue.js 组件实例有一个vm.$em
属性,可以访问组件的根 DOM 元素。此属性的值在组件的生命周期中是否会发生变化,还是在组件安装后保持不变?换句话说,一旦创建了一个组件的根 DOM 元素,它是否可以在某些情况下被 Vue 替换?
我知道 DOM 元素的内容当然可以改变。
根据下面的组件生命周期图,当数据发生变化时,会出现“虚拟 DOM 重新渲染和补丁”。我阅读了文档并试图在 Vue 的源代码中找到答案,但到目前为止我还没有找到任何决定性的答案。
我最接近源代码的是src/core/instance/lifecycle.js
:
Vue.prototype._update = function (vnode: VNode, hydrating?: boolean) {
const vm: Component = this
const prevEl = vm.$el
const prevVnode = vm._vnode
const restoreActiveInstance = setActiveInstance(vm)
vm._vnode = vnode
// Vue.prototype.__patch__ is injected in entry points
// based on the rendering backend used.
if (!prevVnode) {
// initial render
vm.$el = vm.__patch__(vm.$el, vnode, hydrating, false /* removeOnly */)
} else {
// updates
vm.$el = vm.__patch__(prevVnode, vnode)
}
restoreActiveInstance()
// update __vue__ reference
if (prevEl) {
prevEl.__vue__ = null
}
if (vm.$el) {
vm.$el.__vue__ = vm
}
// etc.
}
Run Code Online (Sandbox Code Playgroud)
这表明vm.$el
可以在每个组件渲染上重新分配,但__patch__()
到目前为止我还没有破译它的工作原理以及_update()
确切的调用时间。
我有一些设置任务要直接在根 DOM 元素上完成(例如设置一个 jQuery 插件)。仅在mounted
钩子中执行此操作是否足够(如果vm.$el
是常量,则是),还是必须在检测到updated
更改时在钩子中执行此操作vm.$el
?
如果您完全控制组件内容,那么您可能会认为它vm.$el
不会改变。如果你正在制作(例如)一个 mixin 或指令,那么你就不能 - 完全有可能制作一个可以通过使用 is 来更改顶级元素的组件来更改顶级元素的组件。
例如,这定义了一个可以更改其顶级元素类型的组件:
\nVue.component(\'comp\',{\n props:{type:String},\n template:`\n <component :is="type">\n I am a {{type}}\n </component>\n `\n})\n
Run Code Online (Sandbox Code Playgroud)\n这是一个演示它的小提琴: https ://jsfiddle.net/tazfLqbh/1/
\n作为一个好的实践,我建议假设它可以改变,因为该行为似乎没有在文档中正式定义,所以行为可以随着未来的版本而改变。
\n问题仍然是,当切换类型时,fiddle 中的动态组件是否会触发新 Vue 组件的创建。在开发控制台中:
\n// "Inspect" the span\n> a = $0.__vue__\nVueComponent\xc2\xa0{_uid: 1, _isVue: true, $options: {\xe2\x80\xa6}, _renderProxy: Proxy, _self: VueComponent,\xc2\xa0\xe2\x80\xa6}\n// Toggle the type to div and "inspect" the div\n> b = $0.__vue__\nVueComponent\xc2\xa0{_uid: 1, _isVue: true, $options: {\xe2\x80\xa6}, _renderProxy: Proxy, _self: VueComponent,\xc2\xa0\xe2\x80\xa6}\n> a === b\ntrue\n
Run Code Online (Sandbox Code Playgroud)\n因此,在切换根元素类型时不会创建新的 Vue 组件实例。
\n正如预期的那样,这个小提琴显示动态组件类型确实会触发新的 Vue 组件实例的创建。在这种情况下,看来mounted
就足够了。像这样的东西:
<div id="app">\n <button @click="toggle">\n Toggle div or span element\n </button>\n <component :is="span?\'comp-span\':\'comp-div\'"></component>\n</div>\n\nVue.component(\'comp-span\',{\n template:`\n <span>\n I am a span\n </span>\n `\n})\n\nVue.component(\'comp-div\',{\n template:`\n <div>\n I am a div\n </div>\n `\n})\n
Run Code Online (Sandbox Code Playgroud)\n