真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

vue組件間怎么實現(xiàn)事件傳遞

vue組件間怎么實現(xiàn)事件傳遞,針對這個問題,這篇文章詳細(xì)介紹了相對應(yīng)的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

十年的達(dá)州網(wǎng)站建設(shè)經(jīng)驗,針對設(shè)計、前端、開發(fā)、售后、文案、推廣等六對一服務(wù),響應(yīng)快,48小時及時工作處理。成都全網(wǎng)營銷的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動調(diào)整達(dá)州建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計,從而大程度地提升瀏覽體驗。成都創(chuàng)新互聯(lián)從事“達(dá)州網(wǎng)站設(shè)計”,“達(dá)州網(wǎng)站推廣”以來,每個客戶項目都認(rèn)真落實執(zhí)行。

由于新工作需要用vue,所以最近接觸最多的也是vue,因為之前一直在用react,所以對于vue上手還是很快的。

我也盡量找一些他們兩個的異同點,除了多了一些輔助用的方法以外,最大的不同應(yīng)該是對于組件間的通信,不僅有props,還有一種事件監(jiān)聽,也是可以通過組件間傳遞的。

但是,在vue2.+中,vue引入了diff算法和虛擬dom來提升效率。我們知道這些事為了處理頻繁更新dom元素所提出的一種優(yōu)化方案,可頻繁變動更新以及事件監(jiān)聽的初始化之間是否會有矛盾,當(dāng)組件需要變動時,有沒有對注冊過的事件進(jìn)行解綁? 我們來寫一些簡單的代碼印證一下。

我們寫兩個div做的按鈕,一個是寫的html代碼,一個是通過組件的形式插入,兩個按鈕完全一樣,但我們加一個disabled的屬性在外層,并通過if-else來判斷disabled從而顯示不同的按鈕(當(dāng)然正常場景下我們不會這么去寫代碼,這里只是通過這種方式模擬一種特殊場景,我們自行考慮在我們的業(yè)務(wù)中是否存在這種場景)。




我們加一點樣式,讓他盡量好看一點,看著很簡單,兩個按鈕,可點擊時為他綁定一個點擊事件,不可點擊時不為他綁定。不同點是一個是直接寫的html代碼,一個是組件。組件的代碼如下:


然后在mounted周期里加一個1秒的settimeout將disabled變?yōu)閒alse,然后我們測試一下

vue組件間怎么實現(xiàn)事件傳遞

vue組件間怎么實現(xiàn)事件傳遞

當(dāng)disabled還是true得時候,兩個按鈕點擊都會彈出可點擊的alert。但當(dāng)disebled變?yōu)閒alse的時候,上面用html寫的不會再彈框,可下面用組件寫的就還是會彈窗。

vue組件間怎么實現(xiàn)事件傳遞

這種問題出現(xiàn)時是非常不好定位的,因為代碼上很顯然不會去調(diào)取這個clicktest事件,而在頁面上,我們也能確定按鈕已經(jīng)變?yōu)椴豢牲c擊的那一個了。那為什么這個事件還是會被調(diào)取呢?

這先要從diff算法說起,傳統(tǒng)的diff tree算法的算法復(fù)雜度是O(n^3),而react在引入diff算法時,拋除了跨級移動的情況,即只比對同一級的節(jié)點異同,讓算法復(fù)雜度降低到了O(n),讓我們可以肆無忌憚(當(dāng)然也要適可而止)的頻繁刷新整個頁面。

(呵呵,沒圖)

diff有一條策略是擁有相同類的兩個組件將會生成相似的樹形結(jié)構(gòu),擁有不同類的兩個組件將會生成不同的樹形結(jié)構(gòu)。所以它的比對順序就是

1)tree diff

2)component diff

3)element diff

回到我們的代碼上,我們在進(jìn)行component diff時,認(rèn)為他們是相同的組件,然后進(jìn)行element diff,即進(jìn)行新增 刪除和移動所以問題就是發(fā)生在了這里,在實例化組件的時候我們初始化了事件監(jiān)聽,但在替換相同組件里的dom時,vue并沒有對已添加到組件上的事件監(jiān)聽做刪除。

我們看一下vue的代碼,

Vue.prototype.$emit = function (event: string): Component {
 const vm: Component = this
 if (process.env.NODE_ENV !== 'production') {
  const lowerCaseEvent = event.toLowerCase()
  if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) {
  tip(
   `Event "${lowerCaseEvent}" is emitted in component ` +
   `${formatComponentName(vm)} but the handler is registered for "${event}". ` +
   `Note that HTML attributes are case-insensitive and you cannot use ` +
   `v-on to listen to camelCase events when using in-DOM templates. ` +
   `You should probably use "${hyphenate(event)}" instead of "${event}".`
  )
  }
 }
 let cbs = vm._events[event]
 if (cbs) {
  cbs = cbs.length > 1 ? toArray(cbs) : cbs
  const args = toArray(arguments, 1)
  for (let i = 0, l = cbs.length; i < l; i++) {
  try {
   cbs[i].apply(vm, args)
  } catch (e) {
   handleError(e, vm, `event handler for "${event}"`)
  }
  }
 }
 return vm
 }

vue是通過vdom里的_events屬性下確定是否有綁定事件的。我們看一下不可點擊的按鈕的_events

:
clickTest
:
Array(1)
0
:
? invoker()
length
:

發(fā)現(xiàn)clicktest還在。這就是問題所在了。

那么我們該如何去回避這樣的問題呢,還是應(yīng)從diff的比對方式來解決問題,還是看代碼。

function sameVnode (a, b) {
 return (
 a.key === b.key && (
  (
  a.tag === b.tag &&
  a.isComment === b.isComment &&
  isDef(a.data) === isDef(b.data) &&
  sameInputType(a, b)
  ) || (
  isTrue(a.isAsyncPlaceholder) &&
  a.asyncFactory === b.asyncFactory &&
  isUndef(b.asyncFactory.error)
  )
 )
 )
}

也就是對diff來說,所謂相同的第一判定原則是key。

key也是react引入diff時添加的一個屬性,用來判斷前后vdom樹上是否為統(tǒng)一元素(注意是同級關(guān)系上),所以我們只需要在代碼上加key,就可以避免這個問題

可點擊
不可點擊

這樣,我們在點擊按鈕時,就不會再出彈框了。

key的作用很廣泛,當(dāng)我們在遍歷數(shù)組生成dom時,添加一個可確定的唯一id(注意不應(yīng)該用數(shù)組索引),會優(yōu)化我們的比對效率以及更少的操作dom。我們也會在某個div上添加key以確保他不會因為兄弟元素的變動而被重新渲染(這類div一般會被綁定react或vue以外的事件或動作,如在這個div中生成了一個canvas等)。

那么除了在組件上加這種不必要key值以外,還有別的方法解決嗎?

有的,這里有一種很反vue但是類react的方式,就是把回調(diào)事件通過props的方式傳遞,向下面著這樣,

可點擊
不可點擊
  props: {
   'clickTest': {
    type: Function
   }
  },
  methods: {
   handleClick() {
    //this.$emit('clickTest')
    this.clickTest && this.clickTest()
   }
  }

雖然vue給了我們更方便的事件傳遞的方式,但props里是允許我們?nèi)鬟f任何類型的,我的期望是在真實的dom上或者在公共組件的入口處以外的地方,都是通過props的方式來傳遞結(jié)果的。雖然這種方式很不vue,而且也享受不到v-on給我們帶來的遍歷,但是這樣確實可以減少不必要的麻煩。

當(dāng)然既然用了vue,更好的利用vue給我們帶來的便利也很重要,所以對于這種很少會出現(xiàn)的麻煩,我們有一個預(yù)期,并可以快速定位并修復(fù)問題,就可以了。

關(guān)于vue組件間怎么實現(xiàn)事件傳遞問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識。


網(wǎng)站欄目:vue組件間怎么實現(xiàn)事件傳遞
網(wǎng)頁地址:http://weahome.cn/article/iesoeh.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部