Vue 推荐在绝大多数状况下使用 template 来建立你的 HTML。可是模板毕竟是模板,不是真实的dom节点。从模板到真实dom节点还须要通过一些步骤html
在咱们使用Vue的组件化进行开发应用的时候, 若是仔细的查看咱们要引入的组件, 例子以下vue
// App.vue <template> <div> hello word </div> </template> <script> export default { } </script> <style> </style>
在咱们的主入口main.jsreact
import Vue from 'vue' import App from './App' console.log(App) new Vue({ render: h => h(App) }).$mount('#app')
咱们可以看到在咱们引入的App这个模块,里面是一个对象,对象里面存在一个方法叫作render。在说render函数以前,咱们能够想想,每一次加载一个组件,而后对模板进行解析,解析完后,生成Dom,挂载到页面上。这样会致使效率很低效。而使用Vue-cli进行组件化开发,在咱们引入组件的后,其实会有一个解析器(vue-loader
)对此模板进行了解析,生成了render函数。固然,若是没有经过解析器解析为render函数,也没有关系,在组件第一次挂载的时候,Vue会本身进行解析。源码请参考: https://github.com/vuejs/vue/...
这样,能保证组件每次调用的都是render函数,使用render函数生成VNode。git
咱们把Vue的实例挂载到#app
, 会调用实例里面的render方法,生成虚拟DOM。来看看什么是虚拟节点,把例子修改一下。github
new Vue({ render: h => { let root = h(App) console.log('root:', root) return root } }).$mount('#app')
上面生成的VNode就是虚拟节点,虚拟节点里面有一个属性elm
, 这个属性指向真实的DOM节点。由于VNode指向了真实的DOM节点,那么虚拟节点通过对比后,生成的DOM节点就能够直接进行替换。
这样有什么好处呢?
一个组件对象,若是内部的data
发生变化,触发了render函数,从新生成了VNode节点。那么就能够直接找到所对应的节点,而后直接替换。那么这个过程只会在本组件内发生,不会影响其余的组件。因而组件与组件是隔离的。
例子以下:web
// main.js const root = new Vue({ data: { state: true }, mounted() { setTimeout(() => { console.log(this) this.state = false }, 1000) }, render: function(h) { const { state } = this // state 变化从新触发render let root = h(App) console.log('root:', root) return root } }).$mount('#app')
// App.vue <script> export default { render: (h) => { let app = h('h1', ['hello world']) console.log('app:', app) return app } } </script>
咱们能够看到,当main.js
中从新触发render函数的时候,render方法里面有引用App.vue这个子组件。可是并无触发App.vue组件的的render函数。app
在一个组件内,什么状况会触发render?
。dom
数据劫持是Vue的一大特点,原理官方已经讲的不少了深刻响应式原理。在咱们给组件的data的属性进行的赋值的时候(set),此属性若是在组件内部初次渲染过程被引用(data的属性被访问,也就是数据劫持的get
), 包括生命周期方法或者render方法。因而会触发组件的update(beforeUpdate -> render -> updated)。异步
注: 为了防止data被屡次set从而触发屡次update, Vue把update存放到异步队列中。这样就能保证屡次data的set只会触发一次update。
当props会触发组件的从新渲染是怎么发生的呢?
ide
把父组件的data经过props传递给子组件的时候,子组件在初次渲染的时候生命周期或者render方法,有调用data相关的props的属性, 这样子组件也被添加到父组件的data的相关属性依赖中,这样父组件的data在set的时候,就至关于触发自身和子组件的update。
例子以下:
// main.vue import Vue from 'vue' import App from './App' const root = new Vue({ data: { state: false }, mounted() { setTimeout(() => { this.state = true }, 1000) }, render: function(h) { const { state } = this // state 变化从新触发render let root = h(App, { props: { status: state } }) console.log('root:', root) return root } }).$mount('#app') window.root = root
// App.vue <script> export default { props: { status: Boolean }, render: function (h){ const { status } = this let app = h('h1', ['hello world']) console.log('app:', app) return app } } </script>
截图以下:
在main.js
中 state 状态发生了变化,由false
=> true
, 触发了自身与子组件的render方法。
上面的内容是本人的一些使用心得,因为水平有限, 内容有些错误或者表达不当。多欢迎大神来指导