国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 語言 > JavaScript > 正文

vue數(shù)據(jù)控制視圖源碼解析

2024-05-06 15:20:20
字體:
供稿:網(wǎng)友

分析vue是如何實(shí)現(xiàn)數(shù)據(jù)改變更新視圖的.

前記

三個(gè)月前看了vue源碼來分析如何做到響應(yīng)式數(shù)據(jù)的, 文章名字叫vue源碼之響應(yīng)式數(shù)據(jù), 最后分析到, 數(shù)據(jù)變化后會(huì)調(diào)用Watcher的update()方法. 那么時(shí)隔三月讓我們繼續(xù)看看update()做了什么. (這三個(gè)月用react-native做了個(gè)項(xiàng)目, 也無心總結(jié)了, 因?yàn)楹孟裉?jiǎn)單了).

本文敘事方式為樹藤摸瓜, 順著看源碼的邏輯走一遍, 查看的vue的版本為2.5.2. 我fork了一份源碼用來記錄注釋.

目的

明確調(diào)查方向才能直至目標(biāo), 先說一下目標(biāo)行為: 數(shù)據(jù)變化以后執(zhí)行了什么方法來更新視圖的. 那么準(zhǔn)備開始以這個(gè)方向?yàn)槟繕?biāo)從vue源碼的入口開始找答案.

從之前的結(jié)論開始

先來復(fù)習(xí)一下之前的結(jié)論:

vue構(gòu)造的時(shí)候會(huì)在data(和一些別的字段)上建立Observer對(duì)象, getter和setter被做了攔截, getter觸發(fā)依賴收集, setter觸發(fā)notify.

另一個(gè)對(duì)象是Watcher, 注冊(cè)watch的時(shí)候會(huì)調(diào)用一次watch的對(duì)象, 這樣觸發(fā)了watch對(duì)象的getter, 把依賴收集到當(dāng)前Watcher的deps里, 當(dāng)任何dep的setter被觸發(fā)就會(huì)notify當(dāng)前Watcher來調(diào)用Watcher的update()方法.

那么這里就從注冊(cè)渲染相關(guān)的Watcher開始.

找到了文件在src/core/instance/lifecycle.js中.

new Watcher(vm, updateComponent, noop, null, true /* isRenderWatcher */)

mountComponent

渲染相關(guān)的Watcher是在mountComponent()這個(gè)方法中調(diào)用的, 那么我們搜一下這個(gè)方法是在哪里調(diào)用的. 只有2處, 分別是src/platforms/web/runtime/index.js和src/platforms/weex/runtime/index.js, 以web為例:

Vue.prototype.$mount = function ( el?: string | Element, hydrating?: boolean): Component { el = el && inBrowser ? query(el) : undefined return mountComponent(this, el, hydrating)}

原來如此, 是$mount()方法調(diào)用了mountComponent(), (或者在vue構(gòu)造時(shí)指定el字段也會(huì)自動(dòng)調(diào)用$mount()方法), 因?yàn)閣eb和weex(什么是weex?之前別的文章介紹過)渲染的標(biāo)的物不同, 所以在發(fā)布的時(shí)候應(yīng)該引入了不同的文件最后發(fā)不成不同的dist(這個(gè)問題留給之后來研究vue的整個(gè)流程).

下面是mountComponent方法:

export function mountComponent ( vm: Component, el: ?Element, hydrating?: boolean): Component { vm.$el = el // 放一份el到自己的屬性里 if (!vm.$options.render) { // render應(yīng)該經(jīng)過處理了, 因?yàn)槲覀兘?jīng)常都是用template或者vue文件 // 判斷是否存在render函數(shù), 如果沒有就把render函數(shù)寫成空VNode來避免紅錯(cuò), 并報(bào)出黃錯(cuò) vm.$options.render = createEmptyVNode if (process.env.NODE_ENV !== 'production') {  /* istanbul ignore if */  if ((vm.$options.template && vm.$options.template.charAt(0) !== '#') ||  vm.$options.el || el) {  warn(   'You are using the runtime-only build of Vue where the template ' +   'compiler is not available. Either pre-compile the templates into ' +   'render functions, or use the compiler-included build.',   vm  )  } else {  warn(   'Failed to mount component: template or render function not defined.',   vm  )  } } } callHook(vm, 'beforeMount') let updateComponent /* istanbul ignore if */ if (process.env.NODE_ENV !== 'production' && config.performance && mark) { // 不看這里的代碼了, 直接看else里的, 行為是一樣的 updateComponent = () => {  const name = vm._name  const id = vm._uid  const startTag = `vue-perf-start:${id}`  const endTag = `vue-perf-end:${id}`  mark(startTag)  const vnode = vm._render()  mark(endTag)  measure(`vue ${name} render`, startTag, endTag)  mark(startTag)  vm._update(vnode, hydrating)  mark(endTag)  measure(`vue ${name} patch`, startTag, endTag) } } else { updateComponent = () => {  vm._update(vm._render(), hydrating) } } // we set this to vm._watcher inside the watcher's constructor // since the watcher's initial patch may call $forceUpdate (e.g. inside child // component's mounted hook), which relies on vm._watcher being already defined // 注冊(cè)一個(gè)Watcher new Watcher(vm, updateComponent, noop, null, true /* isRenderWatcher */) hydrating = false // manually mounted instance, call mounted on self // mounted is called for render-created child components in its inserted hook if (vm.$vnode == null) { vm._isMounted = true callHook(vm, 'mounted') } return vm}            
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表

圖片精選

主站蜘蛛池模板: 嘉兴市| 湖北省| 章丘市| 南澳县| 呼玛县| 平定县| 大理市| 桂平市| 平乡县| 福清市| 横山县| 广平县| 静安区| 萍乡市| 广丰县| 祁阳县| 江油市| 泸水县| 蒙阴县| 七台河市| 建阳市| 邢台县| 铜梁县| 伊川县| 长治县| 吉首市| 环江| 梧州市| 北辰区| 信宜市| 边坝县| 莱芜市| 沙坪坝区| 教育| 饶河县| 台东县| 清水县| 明溪县| 贺兰县| 稻城县| 安吉县|