摘要:先問大家一個(gè)簡(jiǎn)單的問題還有人記得里面的方法是如何讓節(jié)點(diǎn)綁定對(duì)應(yīng)的數(shù)據(jù)對(duì)象的嗎有時(shí)候我們做節(jié)點(diǎn)關(guān)聯(lián)設(shè)計(jì)的思路其實(shí)有一點(diǎn)類似,但是在里面多了很多概念,比如如何生成的,包含子父關(guān)系屬性內(nèi)置的對(duì)象的如何注冊(cè)生命周期解析到根節(jié)點(diǎn)之后獲取再一步一步解析
先問大家一個(gè)簡(jiǎn)單的問題:
還有人記得 jquery 里面的 data 方法是如何讓 DOM 節(jié)點(diǎn)綁定對(duì)應(yīng)的數(shù)據(jù)對(duì)象的嗎
有時(shí)候我們做節(jié)點(diǎn)關(guān)聯(lián)設(shè)計(jì)的思路其實(shí)有一點(diǎn)類似,但是在 vue 里面多了很多概念,比如:
1、vnode: 如何生成的,包含子父關(guān)系、屬性 data
2、內(nèi)置的 ref 對(duì)象的 create 如何注冊(cè)
3、生命周期:解析到根節(jié)點(diǎn)之后獲取 outerHTML 再一步一步解析子元素
用慣 vue 的人都會(huì)很熟悉地:
使用 ref 來注冊(cè)引用信息,再通過 $refs 對(duì)象就可以做關(guān)聯(lián)
但是我們看看它們是如何關(guān)聯(lián)上的呢?
代碼片段來自 2.5.16 版本:
1、需要初始化 $refs,默認(rèn)是一個(gè)空對(duì)象
我們看到在函數(shù) initLifecycle 上會(huì)往 vm 上設(shè)置一個(gè) key 為 $refs 值為一個(gè)對(duì)象
function initLifecycle (vm) { vm.$refs = {}; }
2、獲取元素上的 ref 值:
在函數(shù) registerRef 上,它接受 2 個(gè)參數(shù):
vnode
isRemoval
function registerRef (vnode, isRemoval) {}
直接通過 vnode.data 獲取:
var key = vnode.data.ref;
然后獲取 $refs
在這之前需要獲取 vm:
從 vnode 上下文 context 獲取
var vm = vnode.context;
然后很簡(jiǎn)單的就是 vm.$refs
var refs = vm.$refs;
ref 其實(shí)是什么呢?
DOM 節(jié)點(diǎn)或組件實(shí)例
這里的:
componentInstance -- 組件實(shí)例
elm -- DOM 節(jié)點(diǎn)
var ref = vnode.componentInstance || vnode.elm;
這里需要處理一下 v-for 一起用的情況,官網(wǎng)也提過:
對(duì)應(yīng)的引用信息是包含 DOM 節(jié)點(diǎn)或組件實(shí)例的數(shù)組
if (vnode.data.refInFor) {}
情況一:如果不是數(shù)組格式,強(qiáng)制轉(zhuǎn)換一下,外層套一個(gè)數(shù)組
判斷方式:Array.isArray
if (!Array.isArray(refs[key])) { refs[key] = [ref]; }
情況二:看數(shù)組里面是否存在當(dāng)前這個(gè) ref,如果不存在,push 進(jìn)去
if (refs[key].indexOf(ref) < 0) { refs[key].push(ref); }
如果不是和 v-for 一起用:直接設(shè)置對(duì)象的 key 和 value:
refs[key] = ref;
最后一個(gè)問題,官網(wǎng)提到了:
ref 注冊(cè)時(shí)間 -- 因?yàn)?ref 本身是作為渲染結(jié)果被創(chuàng)建的,在初始渲染的時(shí)候你不能訪問它們 - 它們還不存在
那我們看看:
1、它到底是在什么時(shí)機(jī)綁定的
2、vnode 是如何產(chǎn)生的
最開始我們從 _init 開始
Vue.prototype._init = function (options) { // vm.$mount if (vm.$options.el) { vm.$mount(vm.$options.el); } }
生成 vnode 最核心的部分:
實(shí)例化 VNode
function _createElement ( var vnode; if (typeof tag === "string") { // ... vnode = new VNode( config.parsePlatformTagName(tag), data, children, undefined, undefined, context ); } }
我們以如下代碼為例:
我們的 VNode 如下:
最外層 app 轉(zhuǎn)換的 vnode:
children:[VNode] data: { attrs: { id: "app" } } tag: "div"
子 vnode 如下:
data: { ref: "imgbox", attrs: { src:"https://vuejs.org/images/logo.png", alt:"Vue logo" } } tag: "img"
內(nèi)置了一個(gè) ref 對(duì)象,里面有 create 函數(shù),調(diào)用了 registerRef
var ref = { create: function create (_, vnode) { registerRef(vnode); } }
在函數(shù) invokeCreateHooks 調(diào)用 create
注意兩點(diǎn):
1、cbs 是什么?
2、create又是什么,和 ref 對(duì)象的 create 有什么關(guān)系
function invokeCreateHooks (vnode, insertedVnodeQueue) { for (var i$1 = 0; i$1 < cbs.create.length; ++i$1) { cbs.create[i$1](emptyNode, vnode); } }
后面會(huì)提到:hooks
var hooks = ["create", "activate", "update", "remove", "destroy"];
核心部分:createPatchFunction,往 cbs 里面放置對(duì)應(yīng)的函數(shù)
function createPatchFunction (backend) { var cbs = {}; var modules = backend.modules; for (i = 0; i < hooks.length; ++i) { cbs[hooks[i]] = []; for (j = 0; j < modules.length; ++j) { // ... cbs[hooks[i]].push(modules[j][hooks[i]]); } } }
那誰調(diào)用了 createPatchFunction 函數(shù)呢:
var modules = platformModules.concat(baseModules); var patch = createPatchFunction({ nodeOps: nodeOps, modules: modules });
我們發(fā)現(xiàn) baseModules 關(guān)聯(lián)了 ref
var baseModules = [ ref, directives ]
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/97559.html
摘要:大家中秋假期快樂,假期分享一些原理設(shè)計(jì)文章給大家原創(chuàng)不易,歡迎轉(zhuǎn)發(fā),一起學(xué)習(xí)凌晨寫的,不容易哈,收藏或者點(diǎn)個(gè)贊吧在常見的單頁應(yīng)用中,我們都會(huì)有一個(gè)根文件,里面放置一個(gè)然后配置路由來切換很多人在子父組件嵌套關(guān)系下的生命周期鉤子函數(shù)如何應(yīng)用, 大家中秋假期快樂,假期分享一些原理設(shè)計(jì)文章給大家 原創(chuàng)不易,歡迎轉(zhuǎn)發(fā),一起學(xué)習(xí)(凌晨寫的,不容易哈,收藏或者點(diǎn)個(gè)贊吧) 在常見的單頁應(yīng)用中,我們都...
摘要:的組件化功能可謂是它的一大亮點(diǎn),通過將頁面上某一組件的代碼放入一個(gè)的文件中進(jìn)行管理可以大大提高代碼的維護(hù)性。項(xiàng)目中未做移動(dòng)端適配,在不同屏幕手機(jī)上打開,可能用戶體驗(yàn)會(huì)差些 一、項(xiàng)目展示: showImg(https://user-gold-cdn.xitu.io/2018/5/18/1637183ad14a696a?w=372&h=791&f=gif&s=2408442); 注意:如果...
摘要:主要是通過為我們屬性添加一些自定義的行為。方法用來初始化一些生命周期相關(guān)的屬性,以及為等屬性賦值,來看源碼。名稱說明指定已創(chuàng)建的實(shí)例之父實(shí)例,在兩者之間建立父子關(guān)系。一個(gè)對(duì)象,持有已注冊(cè)過的所有子組件。 上篇文章,我們講了vm._renderProxy相關(guān)的內(nèi)容。主要是通過Proxy為我們vm屬性添加一些自定義的行為。今天我們回到init方法中,為大家講解initLifecycle。i...
摘要:我們先來看下這個(gè)函數(shù)的一些神奇用法對(duì)于上述代碼,也就是函數(shù)來說返回值是。不管你第二個(gè)參數(shù)的函數(shù)返回值是幾維嵌套數(shù)組,函數(shù)都能幫你攤平到一維數(shù)組,并且每次遍歷后返回的數(shù)組中的元素個(gè)數(shù)代表了同一個(gè)節(jié)點(diǎn)需要復(fù)制幾次。這是我的 React 源碼解讀課的第一篇文章,首先來說說為啥要寫這個(gè)系列文章: 現(xiàn)在工作中基本都用 React 了,由此想了解下內(nèi)部原理 市面上 Vue 的源碼解讀數(shù)不勝數(shù),但是反觀...
閱讀 2220·2019-08-30 15:54
閱讀 1957·2019-08-30 13:49
閱讀 677·2019-08-29 18:44
閱讀 832·2019-08-29 18:39
閱讀 1114·2019-08-29 15:40
閱讀 1536·2019-08-29 12:56
閱讀 3148·2019-08-26 11:39
閱讀 3102·2019-08-26 11:37