vue源碼分析(二十二)Vue之指令(v-text桐筏、v-html)

我們先來看看代碼 “src/platforms/web/compiler/directives”目錄下面包含html.jstext.js,代碼分別如下:

html.js

/* @flow */

import { addProp } from 'compiler/helpers'

export default function html (el: ASTElement, dir: ASTDirective) {
  if (dir.value) {
    addProp(el, 'innerHTML', `_s(${dir.value})`, dir)
  }
}

text.js

/* @flow */

import { addProp } from 'compiler/helpers'

export default function text (el: ASTElement, dir: ASTDirective) {
  if (dir.value) {
    addProp(el, 'textContent', `_s(${dir.value})`, dir)
  }
}

可以看到上面就是定義了兩個函數(shù)心包,分別傳入了3各參數(shù):
1身辨、 el 類型是ASTElement
2、_s函數(shù)还惠,就是一個將值轉(zhuǎn)換為string類型的方法饲握,
3、dir類型是ASTDirective

可以看到上面的函數(shù)都調(diào)用了一個addProp方法蚕键,addProp函數(shù)的作用就是向el.props推入(push)dir對象救欧。
模板編譯的時候,就是我們之前的vue源碼分析(十六)核心函數(shù)之Compiler這一步的時候會把props添加到domProps對象上面锣光。

v-html 和 v-text 的更新是通過updateDOMProps函數(shù)來進行更新的笆怠,updateDOMProps又是通過render來觸發(fā)的。

下面是 updateDOMProps的代碼:

function updateDOMProps (oldVnode: VNodeWithData, vnode: VNodeWithData) {
 // 如果都不存在domProps對象的話誊爹,就不往下走了
  if (isUndef(oldVnode.data.domProps) && isUndef(vnode.data.domProps)) {
    return
  }
  let key, cur
  const elm: any = vnode.elm
  const oldProps = oldVnode.data.domProps || {}
  let props = vnode.data.domProps || {}
  // clone observed objects, as the user probably wants to mutate it
  // 如果是props是被觀察的一個對象蹬刷,就進行一個拷貝
  if (isDef(props.__ob__)) {
    props = vnode.data.domProps = extend({}, props)
  }
 // 如果新對象props上面不存在,那就置為空
  for (key in oldProps) {
    if (!(key in props)) {
      elm[key] = ''
    }
  }

  for (key in props) {
    cur = props[key]
    //如果節(jié)點具有textContent或innerHTML替废,則忽略子級箍铭,這就是
    if (key === 'textContent' || key === 'innerHTML') {
      if (vnode.children) vnode.children.length = 0
      if (cur === oldProps[key]) continue
      if (elm.childNodes.length === 1) {
        elm.removeChild(elm.childNodes[0])
      }
    }

    if (key === 'value' && elm.tagName !== 'PROGRESS') {
      // store value as _value as well since
      // non-string values will be stringified
      elm._value = cur
      // avoid resetting cursor position when value is the same
      const strCur = isUndef(cur) ? '' : String(cur)
      if (shouldUpdateValue(elm, strCur)) {
        elm.value = strCur
      }
    } else if (key === 'innerHTML' && isSVG(elm.tagName) && isUndef(elm.innerHTML)) {
      // IE doesn't support innerHTML for SVG elements
      svgContainer = svgContainer || document.createElement('div')
      svgContainer.innerHTML = `<svg>${cur}</svg>`
      const svg = svgContainer.firstChild
      while (elm.firstChild) {
        elm.removeChild(elm.firstChild)
      }
      while (svg.firstChild) {
        elm.appendChild(svg.firstChild)
      }
    } else if (
      // skip the update if old and new VDOM state is the same.
      // `value` is handled separately because the DOM value may be temporarily
      // out of sync with VDOM state due to focus, composition and modifiers.
      // This  #4521 by skipping the unnecesarry `checked` update.
      cur !== oldProps[key]
    ) {
      // some property updates can throw
      // e.g. `value` on <progress> w/ non-finite value
      try {
        elm[key] = cur
      } catch (e) {}
    }
  }
}

一般的代碼分析,我就直接在代碼里面的注釋寫了椎镣,為了節(jié)省篇幅诈火,下面我們就挑一些重點的。

if (key === 'textContent' || key === 'innerHTML') {
      if (vnode.children) vnode.children.length = 0
      if (cur === oldProps[key]) continue
      if (elm.childNodes.length === 1) {
        elm.removeChild(elm.childNodes[0])
      }
    }

從上面的代碼可以看到如果是textContent(v-text)或者innerHTML(v-html)
1状答、清空里面的虛擬子級
2冷守、如果值沒有改變,就跳過
3惊科、清空里面的真實子級

 if (key === 'value' && elm.tagName !== 'PROGRESS') {
      // store value as _value as well since
      // non-string values will be stringified
      elm._value = cur
      // avoid resetting cursor position when value is the same
      const strCur = isUndef(cur) ? '' : String(cur)
      if (shouldUpdateValue(elm, strCur)) {
        elm.value = strCur
      }
    }

key等于value的情況拍摇,一般是表單類的標簽,但是PROGRESS進度條標簽頁存在value屬性馆截,所有需要過濾充活,因為PROGRESS的值用戶是不能改變的,那就沒有必調(diào)用shouldUpdateValue來更新蜡娶。

elm[key] = cur

最后給elm真實的DOM節(jié)點設(shè)置混卵,textContent或者innerHTML屬性的值。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末窖张,一起剝皮案震驚了整個濱河市幕随,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌宿接,老刑警劉巖赘淮,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件辕录,死亡現(xiàn)場離奇詭異,居然都是意外死亡梢卸,警方通過查閱死者的電腦和手機走诞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來低剔,“玉大人速梗,你說我怎么就攤上這事〗蟪荩” “怎么了姻锁?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長猜欺。 經(jīng)常有香客問我位隶,道長,這世上最難降的妖魔是什么开皿? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任涧黄,我火速辦了婚禮,結(jié)果婚禮上赋荆,老公的妹妹穿的比我還像新娘笋妥。我一直安慰自己,他們只是感情好窄潭,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布春宣。 她就那樣靜靜地躺著,像睡著了一般嫉你。 火紅的嫁衣襯著肌膚如雪月帝。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天幽污,我揣著相機與錄音嚷辅,去河邊找鬼。 笑死距误,一個胖子當著我的面吹牛簸搞,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播准潭,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼攘乒,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了惋鹅?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤殉簸,失蹤者是張志新(化名)和其女友劉穎闰集,沒想到半個月后沽讹,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡武鲁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年爽雄,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沐鼠。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡挚瘟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出饲梭,到底是詐尸還是另有隱情乘盖,我是刑警寧澤,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布憔涉,位于F島的核電站订框,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏兜叨。R本人自食惡果不足惜穿扳,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望国旷。 院中可真熱鬧矛物,春花似錦、人聲如沸跪但。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽特漩。三九已至吧雹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間涂身,已是汗流浹背雄卷。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蛤售,地道東北人丁鹉。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像悴能,于是被迫代替她去往敵國和親揣钦。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內(nèi)容