成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Vue 2.0源碼學(xué)習(xí)

Joyven / 2796人閱讀

摘要:今年的月日,的版本正式發(fā)布了,其中核心代碼都進(jìn)行了重寫(xiě),于是就專門花時(shí)間,對(duì)的源碼進(jìn)行了學(xué)習(xí)。本篇文章就是源碼學(xué)習(xí)的總結(jié)。實(shí)現(xiàn)了并且將靜態(tài)子樹(shù)進(jìn)行了提取,減少界面重繪時(shí)的對(duì)比。的最新源碼可以去獲得。

Vue2.0介紹

從去年9月份了解到Vue后,就被他簡(jiǎn)潔的API所吸引。1.0版本正式發(fā)布后,就在業(yè)務(wù)中開(kāi)始使用,將原先jQuery的功能逐步的進(jìn)行遷移。
今年的10月1日,Vue的2.0版本正式發(fā)布了,其中核心代碼都進(jìn)行了重寫(xiě),于是就專門花時(shí)間,對(duì)Vue 2.0的源碼進(jìn)行了學(xué)習(xí)。本篇文章就是2.0源碼學(xué)習(xí)的總結(jié)。

先對(duì)Vue 2.0的新特性做一個(gè)簡(jiǎn)單的介紹:

大小 & 性能。Vue 2.0的線上包gzip后只有12Kb,而1.0需要22Kb,react需要44Kb。而且,Vue 2.0的性能在react等幾個(gè)框架中,性能是最快的。

VDOM。實(shí)現(xiàn)了Virtual DOM, 并且將靜態(tài)子樹(shù)進(jìn)行了提取,減少界面重繪時(shí)的對(duì)比。與1.0對(duì)比性能有明顯提升。

template & JSX。眾所周知,Vue 1.0使用的是template來(lái)實(shí)現(xiàn)模板,而React使用了JSX實(shí)現(xiàn)模板。關(guān)于template和JSX的爭(zhēng)論也很多,很多人不使用React就是因?yàn)闆](méi)有支持template寫(xiě)法。Vue 2.0對(duì)template和JSX寫(xiě)法都做了支持。使用時(shí),可以根據(jù)具體業(yè)務(wù)細(xì)節(jié)進(jìn)行選擇,可以很好的發(fā)揮兩者的優(yōu)勢(shì)。就這一點(diǎn),Vue已經(jīng)超過(guò)React了。

Server Render。2.0還對(duì)了Server Render做了支持。這一點(diǎn)并沒(méi)有在業(yè)務(wù)中使用,不做評(píng)價(jià)。

Vue的最新源碼可以去 https://github.com/vuejs/vue 獲得。本文講的是 2.0.3版本,2.0.3可以去 https://github.com/vuejs/vue/... 這里獲得。

下面開(kāi)始進(jìn)入正題。首先從生命周期開(kāi)始。

生命周期

上圖就是官方給出的Vue 2.0的生命周期圖,其中包含了Vue對(duì)象生命周期過(guò)程中的幾個(gè)核心步驟。了解了這幾個(gè)過(guò)程,可以很好的幫助我們理解Vue的創(chuàng)建與銷毀過(guò)程。
從圖中我們可以看出,生命周期主要分為4個(gè)過(guò)程:

create。new Vue時(shí),會(huì)先進(jìn)行create,創(chuàng)建出Vue對(duì)象。

mount。根據(jù)el, template, render方法等屬性,會(huì)生成DOM,并添加到對(duì)應(yīng)位置。

update。當(dāng)數(shù)據(jù)發(fā)生變化后,會(huì)重新渲染DOM,并進(jìn)行替換。

destory。銷毀時(shí)運(yùn)行。

那么這4個(gè)過(guò)程在源碼中是怎么實(shí)現(xiàn)的呢?我們從new Vue開(kāi)始。

new Vue

為了更好的理解new的過(guò)程,我整理了一個(gè)序列圖:

new Vue的過(guò)程主要涉及到三個(gè)對(duì)象:vm、compiler、watcher。其中,vm表示Vue的具體對(duì)象;compiler負(fù)責(zé)將template解析為AST render方法;watcher用于觀察數(shù)據(jù)變化,以實(shí)現(xiàn)數(shù)據(jù)變化后進(jìn)行re-render。

下面來(lái)分析下具體的過(guò)程和代碼:
首先,運(yùn)行new Vue()的時(shí)候,會(huì)進(jìn)入代碼src/core/instance/index.js的Vue構(gòu)造方法中,并執(zhí)行this._init()方法。在_init中,會(huì)對(duì)各個(gè)功能進(jìn)行初始化,并執(zhí)行beforeCreatecreated兩個(gè)生命周期方法。核心代碼如下:

initLifecycle(vm)
initEvents(vm)
callHook(vm, "beforeCreate")
initState(vm)
callHook(vm, "created")
initRender(vm)

這個(gè)過(guò)程有一點(diǎn)需要注意:
beforeCreate和created之間只有initState,和官方給出的生命周期圖并不完全一樣。這里的initState是用于初始化data,props等的監(jiān)聽(tīng)的。

_init的最后,會(huì)運(yùn)行initRender方法。在該方法中,會(huì)運(yùn)行vm.$mount方法,代碼如下:

if (vm.$options.el) {
  vm.$mount(vm.$options.el)
}

這里的vm.$mount可以在業(yè)務(wù)代碼中調(diào)用,這樣,new 過(guò)程和 mount過(guò)程就可以根據(jù)業(yè)務(wù)情況進(jìn)行分離。

這里的$mountsrc/entries/web-runtime-with-compiler.js中,主要邏輯是根據(jù)el, template, render三個(gè)屬性來(lái)獲得AST render方法。代碼如下:

if (!options.render) {   // 如果有render方法,直接運(yùn)行mount
  let template = options.template
  if (template) {  // 如果有template, 獲取template參數(shù)對(duì)于的HTML作為模板
    if (typeof template === "string") {
      if (template.charAt(0) === "#") {
        template = idToTemplate(template)
      }
    } else if (template.nodeType) {
      template = template.innerHTML
    } else {
      if (process.env.NODE_ENV !== "production") {
        warn("invalid template option:" + template, this)
      }
      return this
    }
  } else if (el) {  // 如果沒(méi)有template, 且存在el,則獲取el的outerHTML作為模板
    template = getOuterHTML(el)
  }
  if (template) { // 如果獲取到了模板,則將模板轉(zhuǎn)化為render方法
    const { render, staticRenderFns } = compileToFunctions(template, {
      warn,
      shouldDecodeNewlines,
      delimiters: options.delimiters
    }, this)
    options.render = render
    options.staticRenderFns = staticRenderFns
  }
}
return mount.call(this, el, hydrating)

這個(gè)過(guò)程有三點(diǎn)需要注意:
compile時(shí),將最大靜態(tài)子樹(shù)提取出來(lái)作為多帶帶的AST渲染方法,以提升后面vNode對(duì)比時(shí)的性能。所以,當(dāng)存在多個(gè)連續(xù)的靜態(tài)標(biāo)簽時(shí),可以在外邊添加一個(gè)靜態(tài)父節(jié)點(diǎn),這樣,staticRenderFns數(shù)目可以減少,從而提升性能。
Vue 2.0中的模板有三種引用寫(xiě)法:el, template, render(JSX)。其中的優(yōu)先級(jí)是render > template > el。
el, template兩種寫(xiě)法,最后都會(huì)通過(guò)compiler轉(zhuǎn)化為render(JSX)來(lái)運(yùn)行,也就是說(shuō),直接寫(xiě)成render(JSX)是性能最優(yōu)的。當(dāng)然,如果使用了構(gòu)建工具,最終生成的包就是使用的render(JSX)。這樣子,在源碼上就可以不用過(guò)多考慮這一塊的性能了,直接用可維護(hù)性最好的方式就行。

將模板轉(zhuǎn)化為render,用到了compileToFunctions方法,該方法最后會(huì)通過(guò)src/compiler/index.js文件中的compile方法,將模板轉(zhuǎn)化為AST語(yǔ)法結(jié)構(gòu)的render方法,并對(duì)靜態(tài)子樹(shù)進(jìn)行分離。

完成render方法的生成后,會(huì)進(jìn)入_mount(src/core/instance.lifecycle.js)中進(jìn)行DOM更新。該方法的核心邏輯如下:

vm._watcher = new Watcher(vm, () => {
  vm._update(vm._render(), hydrating)
}, noop)

首先會(huì)new一個(gè)watcher對(duì)象,在watcher對(duì)象創(chuàng)建后,會(huì)運(yùn)行傳入的方法vm._update(vm._render(), hydrating)(watcher的邏輯在下面的watcher小節(jié)中細(xì)講)。其中的vm._render()主要作用就是運(yùn)行前面compiler生成的render方法,并返回一個(gè)vNode對(duì)象。這里的vNode就是一個(gè)虛擬的DOM節(jié)點(diǎn)。

拿到vNode后,傳入vm._update()方法,進(jìn)行DOM更新。

VDOM

上面已經(jīng)講完了new Vue過(guò)程中的主要步驟,其中涉及到template如何轉(zhuǎn)化為DOM的過(guò)程,這里多帶帶拿出來(lái)講下。先上序列圖:

從圖中可以看出,從template到DOM,有三個(gè)過(guò)程:

template -> AST render (compiler解析template)

AST render -> vNode (render方法運(yùn)行)

vNode -> DOM (vdom.patch)

首先是template在compiler中解析為AST render方法的過(guò)程。上一節(jié)中有說(shuō)到,initRender后,會(huì)調(diào)用到src/entries/web-runtime-with-compiler.js中的Vue.prototype.$mount方法。在$mount中,會(huì)獲取template,然后調(diào)用src/platforms/web/compiler/index.jscompileToFunctions方法。在該方法中,會(huì)運(yùn)行compile將template解析為多個(gè)render方法,也就是AST render。這里的compile在文件src/compiler/index.js中,代碼如下:

const ast = parse(template.trim(), options)   // 解析template為AST
optimize(ast, options)  // 提取static tree
const code = generate(ast, options)  // 生成render 方法
return {
  ast,
  render: code.render,
  staticRenderFns: code.staticRenderFns
}

可以看出,compile方法就是將template以AST的方式進(jìn)行解析,并轉(zhuǎn)化為render方法進(jìn)行返回。

再看第二個(gè)過(guò)程:AST render -> vNode。這個(gè)過(guò)程很簡(jiǎn)單,就是將AST render方法進(jìn)行運(yùn)行,獲得返回的vNode對(duì)象。

最后一步,vNode -> DOM。該過(guò)程中,存在vNode的對(duì)比以及DOM的添加修改操作。
在上一節(jié)中,有講到vm._update()方法中對(duì)DOM進(jìn)行更新。_update的主要代碼如下:

// src/core/instance/lifecycle.js
if (!prevVnode) {
  // Vue.prototype.__patch__ is injected in entry points
  // based on the rendering backend used.
  vm.$el = vm.__patch__(vm.$el, vnode, hydrating)  // 首次添加
} else {
  vm.$el = vm.__patch__(prevVnode, vnode)  // 數(shù)據(jù)變化后觸發(fā)的DOM更新
}

可以看出,無(wú)論是首次添加還是后期的update,都是通過(guò)__patch__來(lái)更新的。這里的__patch__核心步驟是在src/core/vdom/patch.js中的patch方法進(jìn)行實(shí)現(xiàn),源碼如下:

function patch (oldVnode, vnode, hydrating, removeOnly) {
    if (!oldVnode) {
      ...
    } else {
      ...
      if (!isRealElement && sameVnode(oldVnode, vnode)) {
        patchVnode(oldVnode, vnode, insertedVnodeQueue, removeOnly)  // diff并更新DOM。
      } else {
        elm = oldVnode.elm
        parent = nodeOps.parentNode(elm)
        ...
        if (parent !== null) {
          nodeOps.insertBefore(parent, vnode.elm, nodeOps.nextSibling(elm))  // 添加element到DOM。
          removeVnodes(parent, [oldVnode], 0, 0)
        }
        ...
      }
    }
    ...
  }

首次添加很簡(jiǎn)單,就是通過(guò)insertBefore將轉(zhuǎn)化好的element添加到DOM中。如果是update,則會(huì)調(diào)動(dòng)patchVnode()。最后來(lái)看下patchVnode的代碼:

function patchVnode (oldVnode, vnode, insertedVnodeQueue, removeOnly) {
  ...
  const elm = vnode.elm = oldVnode.elm
  const oldCh = oldVnode.children
  const ch = vnode.children
  ...
  if (isUndef(vnode.text)) {
    if (isDef(oldCh) && isDef(ch)) {  // 當(dāng)都存在時(shí),更新Children
      if (oldCh !== ch) updateChildren(elm, oldCh, ch, insertedVnodeQueue, removeOnly)
    } else if (isDef(ch)) {  // 只存在新節(jié)點(diǎn)時(shí),即添加節(jié)點(diǎn)
      if (isDef(oldVnode.text)) nodeOps.setTextContent(elm, "")
      addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue)
    } else if (isDef(oldCh)) {  // 只存在老節(jié)點(diǎn)時(shí),即刪除節(jié)點(diǎn)
      removeVnodes(elm, oldCh, 0, oldCh.length - 1)
    } else if (isDef(oldVnode.text)) {  // 刪除了textContent
      nodeOps.setTextContent(elm, "")
    }
  } else if (oldVnode.text !== vnode.text) { // 修改了textContent
    nodeOps.setTextContent(elm, vnode.text)
  }
}

其中有調(diào)用了updateChildren來(lái)更新子節(jié)點(diǎn),代碼如下:

function updateChildren (parentElm, oldCh, newCh, insertedVnodeQueue, removeOnly) {
  ...
  while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
    if (isUndef(oldStartVnode)) {
      oldStartVnode = oldCh[++oldStartIdx] // Vnode has been moved left
    } else if (isUndef(oldEndVnode)) {
      oldEndVnode = oldCh[--oldEndIdx]
    } else if (sameVnode(oldStartVnode, newStartVnode)) {
      patchVnode(oldStartVnode, newStartVnode, insertedVnodeQueue)
      oldStartVnode = oldCh[++oldStartIdx]
      newStartVnode = newCh[++newStartIdx]
    } else if (sameVnode(oldEndVnode, newEndVnode)) {
      patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue)
      oldEndVnode = oldCh[--oldEndIdx]
      newEndVnode = newCh[--newEndIdx]
    } else if (sameVnode(oldStartVnode, newEndVnode)) { // Vnode moved right
      patchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue)
      canMove && nodeOps.insertBefore(parentElm, oldStartVnode.elm, nodeOps.nextSibling(oldEndVnode.elm))
      oldStartVnode = oldCh[++oldStartIdx]
      newEndVnode = newCh[--newEndIdx]
    } else if (sameVnode(oldEndVnode, newStartVnode)) { // Vnode moved left
      patchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue)
      canMove && nodeOps.insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm)
      oldEndVnode = oldCh[--oldEndIdx]
      newStartVnode = newCh[++newStartIdx]
    } else {
      ...
    }
  }
  ...
}

可以看到updateChildren中,又通過(guò)patchVnode來(lái)更新當(dāng)前節(jié)點(diǎn)。梳理一下,patch通過(guò)patchVnode來(lái)更新根節(jié)點(diǎn),然后通過(guò)updateChildren來(lái)更新子節(jié)點(diǎn),具體子節(jié)點(diǎn),又通過(guò)patchVnode來(lái)更新,通過(guò)一個(gè)類似于遞歸的方式逐個(gè)節(jié)點(diǎn)的完成對(duì)比和更新。

Vue 2.0中對(duì)如何去實(shí)現(xiàn)VDOM的思路是否清晰,通過(guò)4層結(jié)構(gòu),很好的實(shí)現(xiàn)了可維護(hù)性,也為實(shí)現(xiàn)server render, weex等功能提供了可能。拿server render舉例,只需要將最后的vNode -> DOM 改成 vNode -> String 或者 vNode -> Stream, 就可以實(shí)現(xiàn)server render。剩下的compiler和Vue的核心邏輯都不需要改。

Watcher

我們都知道MVVM框架的特征就是當(dāng)數(shù)據(jù)發(fā)生變化后,會(huì)自動(dòng)更新對(duì)應(yīng)的DOM節(jié)點(diǎn)。使用MVVM之后,業(yè)務(wù)代碼中就可以完全不寫(xiě)DOM操作代碼,不僅可以將業(yè)務(wù)代碼聚焦在業(yè)務(wù)邏輯上,還可以提高業(yè)務(wù)代碼的可維護(hù)性和可測(cè)試性。那么Vue 2.0中是怎么實(shí)現(xiàn)對(duì)數(shù)據(jù)變化的監(jiān)聽(tīng)的呢?照例,先看序列圖:

可以看出,整個(gè)Watcher的過(guò)程可以分為三個(gè)過(guò)程。

對(duì)state設(shè)置setter/getter

對(duì)vm設(shè)置好Watcher,添加好state 觸發(fā) setter時(shí)的執(zhí)行方法

state變化觸發(fā)執(zhí)行

前面有說(shuō)過(guò),在生命周期函數(shù)beforeCreatecreated直接,會(huì)運(yùn)行方法initState()。在initState中,會(huì)對(duì)Props, Data, Computed等屬性添加Setter/Getter。拿Data舉例,設(shè)置setter/getter的代碼如下:

function initData (vm: Component) {
  let data = vm.$options.data
  ...
  // proxy data on instance
  const keys = Object.keys(data)
  let i = keys.length
  while (i--) {
    ...
    proxy(vm, keys[i])   // 設(shè)置vm._data為代理
  }
  // observe data
  observe(data)
}

通過(guò)調(diào)用observe方法,會(huì)對(duì)data添加好觀察者,核心代碼為:

Object.defineProperty(obj, key, {
  enumerable: true,
  configurable: true,
  get: function reactiveGetter () {
    const value = getter ? getter.call(obj) : val
    if (Dep.target) {
      dep.depend()  // 處理好依賴watcher
      ...
    }
    return value
  },
  set: function reactiveSetter (newVal) {
    ...
    childOb = observe(newVal)  // 對(duì)新數(shù)據(jù)重新observe
    dep.notify()  // 通知到dep進(jìn)行數(shù)據(jù)更新
  }
})

這個(gè)時(shí)候,對(duì)data的監(jiān)聽(tīng)已經(jīng)完成??梢钥吹剑?dāng)data發(fā)生變化的時(shí)候,會(huì)運(yùn)行dep.notify()。在notify方法中,會(huì)去運(yùn)行watcher的update方法,內(nèi)容如下:

update () {
  if (this.lazy) {
    this.dirty = true
  } else if (this.sync) {
    this.run()
  } else {
    queueWatcher(this)
  }
}
run () {
  if (this.active) {
    const value = this.get()
  }
  ...
}

update方法中,queueWatcher方法的目的是通過(guò)nextTicker來(lái)執(zhí)行run方法,屬于支線邏輯,就不分析了,這里直接看run的實(shí)現(xiàn)。run方法其實(shí)很簡(jiǎn)單,就是調(diào)用get方法,而get方法會(huì)通過(guò)執(zhí)行this.getter()來(lái)更新DOM。

那么this.getter是什么呢?本文最開(kāi)始分析new Vue過(guò)程時(shí),有講到運(yùn)行_mount方法時(shí),會(huì)運(yùn)行如下代碼:

vm._watcher = new Watcher(vm, () => {
  vm._update(vm._render(), hydrating)
}, noop)

那么this.getter就是這里Watcher方法的第二個(gè)參數(shù)。來(lái)看下new Watcher的代碼:

export default class Watcher {
  constructor (
    vm: Component,
    expOrFn: string | Function,
    cb: Function,
    options?: Object = {}
  ) {
    ...
    if (typeof expOrFn === "function") {
      this.getter = expOrFn
    } else {
      this.getter = parsePath(expOrFn)
    }
    ...
    this.value = this.lazy
      ? undefined
      : this.get()
  }
}

可以看出,在new Vue過(guò)程中,Watcher會(huì)在構(gòu)造完成后主動(dòng)調(diào)用this.get()來(lái)觸發(fā)this.getter()方法的運(yùn)行,以達(dá)到更新DOM節(jié)點(diǎn)。

總結(jié)一下這個(gè)過(guò)程:首先_init時(shí),會(huì)對(duì)Data設(shè)置好setter方法,setter方法中會(huì)調(diào)用dep.notify(),以便數(shù)據(jù)變化時(shí)通知DOM進(jìn)行更新。然后new Watcher時(shí),會(huì)將更新DOM的方法進(jìn)行設(shè)置,也就是Watcher.getter方法。最后,當(dāng)Data發(fā)生變化的時(shí)候,dep.notify()運(yùn)行,運(yùn)行到watcher.getter()時(shí),就會(huì)去運(yùn)行render和update邏輯,最終達(dá)到DOM更新的目的。

總結(jié)與收獲

剛開(kāi)始覺(jué)得看源碼,是因?yàn)橄M芰私庀耉ue 2.0的實(shí)現(xiàn),看看能不能得到一些從文檔中無(wú)法知道的細(xì)節(jié),用于提升運(yùn)行效率。把主要流程理清楚后,的確了解到一些,這里做個(gè)整理:

el屬性傳入的如果不是element,最后會(huì)通過(guò)document.querySelector來(lái)獲取的,這個(gè)接口性能較差,所以,el傳入一個(gè)element性能會(huì)更好。

$mount方法中對(duì)html,body標(biāo)簽做了過(guò)濾,這兩個(gè)不能用來(lái)作為渲染的根節(jié)點(diǎn)。

每一個(gè)組件都會(huì)從_init開(kāi)始重新運(yùn)行,所以,當(dāng)存在一個(gè)長(zhǎng)列表時(shí),將子節(jié)點(diǎn)作為一個(gè)組件,性能會(huì)較差。

*.vue文件會(huì)在構(gòu)建時(shí)轉(zhuǎn)化為render方法,而render方法的性能比指定template更好。所以,源碼使用*.vue的方式,性能更好。

如果需要自定義delimiters,每一個(gè)組件都需要多帶帶指定。

如果是*.vue文件,指定delimiters是失效的,因?yàn)?b>vue-loader對(duì)*.vue文件進(jìn)行解析時(shí),并沒(méi)有將delimiters傳遞到compiler.compile()中。(這一點(diǎn)不確定是bug還是故意這樣設(shè)計(jì)的)。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/80906.html

相關(guān)文章

  • vue@2.0源碼學(xué)習(xí)---目錄結(jié)構(gòu)分析與準(zhǔn)備工作

    摘要:源碼版本為原文地址和有必要了解這兩個(gè)概念的區(qū)別。點(diǎn)開(kāi)目錄下的,發(fā)現(xiàn)確實(shí)是導(dǎo)出了一個(gè)構(gòu)造函數(shù)。再回過(guò)頭看,它給構(gòu)造函數(shù)擴(kuò)展了一些方法具體的邏輯后文看。 前言 網(wǎng)上vue的源碼分析也蠻多的,不過(guò)很多都是1.0版本的并且大多都是在講數(shù)據(jù)的observe,索性自己看看源碼,雖然很難但是希望能學(xué)到點(diǎn)東西。 源碼版本為2.0.0 原文地址 runtime和runtime-with-compiler...

    tinysun1234 評(píng)論0 收藏0
  • vue@2.0源碼學(xué)習(xí)---組件究竟是什么

    摘要:定義一個(gè)組件如下打印如下再回過(guò)頭看,可以發(fā)現(xiàn)他做的工作就是擴(kuò)展一個(gè)構(gòu)造函數(shù),并將這個(gè)構(gòu)造函數(shù)添加到現(xiàn)在我們已經(jīng)可以回答最開(kāi)始的問(wèn)題的組件是什么的組件其實(shí)就是擴(kuò)展的構(gòu)造函數(shù),并且在適當(dāng)?shù)臅r(shí)候?qū)嵗癁閷?shí)例。 [email protected]源碼學(xué)習(xí)---組件究竟是什么 本篇文章從最簡(jiǎn)單的情況入手,不考慮prop和組件間通信。 Vue.component vue文檔告訴我們可以使用Vue.component(...

    PiscesYE 評(píng)論0 收藏0
  • Vue 2.0】核心源碼解讀 -- 不定期更新

    摘要:觀察員由模板解析指令創(chuàng)建的觀察員負(fù)責(zé)模板中的更新視圖操作。觀察員種類目前了解情況來(lái)看主要分三類視圖指令的計(jì)算屬性的用戶自定義的 介紹 關(guān)于 Vue.js 的原理一直以來(lái)都是一個(gè)話題。經(jīng)過(guò)幾天的源碼學(xué)習(xí)和資料介紹,我將一些個(gè)人理解的經(jīng)驗(yàn)給寫(xiě)下來(lái),希望能夠與大家共勉。 附上GITHUB源碼地址, 如果有任何不解 可以在 文章下面提出或者寫(xiě)下issue, 方便大家回答和學(xué)習(xí), 有興趣可以St...

    sunsmell 評(píng)論0 收藏0
  • Vue 筆記三:Vue2.0與1.0的區(qū)別

    摘要:升級(jí)的區(qū)別與的斷層式升級(jí)不同,延續(xù)了自己的風(fēng)格。在命名方式和上有一些區(qū)別,掌握它們是你升級(jí)整個(gè)項(xiàng)目的關(guān)鍵。以下內(nèi)容都是來(lái)源于個(gè)人項(xiàng)目的一些經(jīng)驗(yàn)之談,并非系統(tǒng)性的闡述??偰夸浨岸私?jīng)驗(yàn)收集器轉(zhuǎn)載自個(gè)人建了前端學(xué)習(xí)群,旨在一起學(xué)習(xí)前端。 升級(jí)的區(qū)別 與angular的斷層式升級(jí)不同,vue延續(xù)了自己的風(fēng)格。在命名方式和API上有一些區(qū)別,掌握它們是你升級(jí)整個(gè)項(xiàng)目的關(guān)鍵。以下內(nèi)容都是來(lái)源于個(gè)人...

    Big_fat_cat 評(píng)論0 收藏0
  • 前端窩 - 收藏集 - 掘金

    摘要:毫無(wú)疑問(wèn),設(shè)計(jì)模式于己于他人于系統(tǒng)都是多贏的設(shè)計(jì)模式使代碼編寫(xiě)真正工程化設(shè)計(jì)模小書(shū)前端掘金這是一本關(guān)于的小書(shū)。 JavaScript 常見(jiàn)設(shè)計(jì)模式解析 - 掘金設(shè)計(jì)模式(Design pattern)是一套被反復(fù)使用、多數(shù)人知曉的、經(jīng)過(guò)分類編目的、代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié)。使用設(shè)計(jì)模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。毫無(wú)疑問(wèn),設(shè)計(jì)模式于己于他人于系統(tǒng)都是多贏的;設(shè)計(jì)...

    李文鵬 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<