溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Vue.js的注意事項有哪些

發(fā)布時間:2021-11-06 15:55:49 來源:億速云 閱讀:192 作者:iii 欄目:web開發(fā)

這篇文章主要講解了“Vue.js的注意事項有哪些”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Vue.js的注意事項有哪些”吧!

1、為什么 Vue.js 不使用 ES Classes 的方式編寫組件

如果你使用過類似于 Angular 的框架或者某些后端 OOP 語言后,那么你的***個問題可能是:為什么不使用 Class 形式的組件?

Vue.js 的作者在 GitHub issues 中很好的回答了這個問題:

Use standard JS classes instead of custom syntax?

為什么不使用 Class 這里有三個很重要的原因:

ES Classes 不能夠滿足當(dāng)前 Vue.js 的需求,ES Classes 標(biāo)準(zhǔn)還沒有完全規(guī)范化,并且總是朝著錯誤的方向發(fā)展。如果 Classes  的私有屬性和裝飾器(當(dāng)前已進(jìn)入 Stage 3)穩(wěn)定后,可能會有一定幫助。

ES Classes 只適合于那些熟悉面向?qū)ο笳Z言的人,它對哪些不使用復(fù)雜構(gòu)建工具和編譯器的人不夠友好。

優(yōu)秀的 UI 組件層次結(jié)構(gòu)一般都是組件的橫向組合,它并不是基于繼承的層次結(jié)構(gòu)。而 Classes 形式顯然更擅長的是后者。

譯者注:But,Vue.js 3.0 將支持基于 Class 的組件寫法,真香。

2、如何構(gòu)建自己的抽象組件?

如果你想構(gòu)建自己的抽象組件(比如 transition、keep-alive),這是一個比構(gòu)建大型 web  應(yīng)用更加瘋狂地想法,這里有一些關(guān)于這個問題的討論,但是并沒有什么進(jìn)展。

Any plan for docs of abstract components?

譯者注:在 Vue.js 內(nèi)部組件(transition、keep-alive)中,使用了一個 abstract  屬性,用于聲明抽象組件,這個屬性作者并不打算開放給大家使用,所以文檔也沒有提及。但是如果你要使用也是可以的,那么你必須深入源碼探索該屬性有何作用。

但是不要害怕,如果你可以很好地理解 slots ,你就可以構(gòu)建自己的抽象組件了。這里有一篇很好的博客介紹了要如何做到這一點。

Writing Abstract Components with Vue.js

譯者注:下面是《在 Vue.js 中構(gòu)建抽象組件》的簡單翻譯

抽象組件與普通組件一樣,只是它不會在界面上顯示任何 DOM 元素。它們只是為現(xiàn)有組件添加額外的行為。

就像很多你已經(jīng)熟悉的 Vue.js 的內(nèi)置組件,比如:``、``、``。

現(xiàn)在展示一個案例,如何跟蹤一個 DOM 已經(jīng)進(jìn)入了可視區(qū)域 ,讓我們使用 IntersectionObserver API  來實現(xiàn)一個解決這個問題的抽象組件。

(完整代碼在這里:[vue-intersect](https://github.com/heavyy/vue-intersect))

// IntersectionObserver.vue export default {   // 在 Vue 中啟用抽象組件   // 此屬性不在官方文檔中, 可能隨時發(fā)生更改,但是我們的組件必須使用它   abstract: true,   // 重新實現(xiàn)一個 render 函數(shù)   render() {     // 我們不需要任何包裹的元素,只需要返回子組件即可     try {       return this.$slots.default[0];     } catch (e) {       throw new Error('IntersectionObserver.vue can only render one, and exactly one child component.');     }      return null;   },   mounted () {     // 創(chuàng)建一個 IntersectionObserver 實例     this.observer = new IntersectionObserver((entries) => {       this.$emit(entries[0].isIntersecting ? 'intersect-enter' : 'intersect-leave', [entries[0]]);     });      // 需要等待下一個事件隊列,保證子元素已經(jīng)渲染     this.$nextTick(() => {       this.observer.observe(this.$slots.default[0].elm);     });   },   destroyed() {     // 確保組件移除時,IntersectionObserver 實例也會停止監(jiān)聽     this.observer.disconnect();   } }

讓我們看看如何使用它?

<intersection-observer @intersect-enter="handleEnter" @intersect-leave="handleLeave">   <my-honest-to-goodness-component></my-honest-to-goodness-component> </intersection-observer>

但是在這樣做之前,請你三思。我們一般依賴 mixins 和一些純函數(shù)來解決一些特殊場景的問題,你可以將 mixins 直接看做一個抽象組件。

How do I extend another VueJS component in a single-file component? (ES6  vue-loader)

3、我不太喜歡 Vue.js 的單文件組件,我更希望 HTML、CSS 和 JavaScript 分離。

沒有人阻止你這樣做,如果你是個注重分離的哲學(xué)家,喜歡把不同的東西放在不同文件,或者討厭編輯器對 .vue  文件的不穩(wěn)定行為,那么你這么做也是可以的。你要做的很簡單:

<!--https://vuejs.org/v2/guide/single-file-components.html --> <!-- my-component.vue --> <template src="./my-component.html"></template> <script src="./my-component.js"></script> <style src="./my-component.css"></style>

這么做,就會出現(xiàn)下一個問題:我的組件總是需要 4 個文件(vue + html + css + js)嗎?我能不能擺脫 .vue 文件?  答案是肯定的,你可以使用 vue-template-loader。

我的同事還為此寫了一篇很棒的教程:

Using vue-template-loader with Vue.js to Compile HTML Templates

4、 函數(shù)式組件

感謝 React.js 讓函數(shù)式組件很流行,這是因為他們無狀態(tài)、易于測試。然而它們也存在一些問題。

譯者注:不了解 Vue.js 函數(shù)式組件的可以先在官方文檔查看:官方文檔

4.1 為什么我不能對功能組件使用基于 Class 的 @Component 裝飾器?

再次回到 Classes,它只是一種用于保存本地狀態(tài)的數(shù)據(jù)結(jié)構(gòu)。如果函數(shù)式組件是無狀態(tài)的,那么使用 @Component 裝飾器就是無意義的。

這里有關(guān)于這個的討論:

How to create functional component in @Component?

4.2 外部類和樣式不應(yīng)用于函數(shù)式組件

函數(shù)式組件不能像普通組件那樣,綁定具體的類和樣式,必須在 render 函數(shù)中手動應(yīng)用這些綁定。

DOM class attribute not rendered properly with functional components

class attribute ignored on functional components

4.3 函數(shù)式組件總是會重復(fù)渲染?

TLDR:在函數(shù)式組件中使用有狀態(tài)組件時務(wù)必要小心

Functional components are re-rendered when props are unchanged.

函數(shù)式組件相當(dāng)于直接調(diào)用組件的 Render 函數(shù),這意味著你應(yīng)該:

避免在 render 函數(shù)中直接使用有狀態(tài)組件,因為這會在每次調(diào)用 render 函數(shù)時創(chuàng)建不同的組件實例。

如果函數(shù)式組件是葉子組件,會更好地利用它們。 需要注意的是,同樣的行為也適用于 React.js。

4.4 如何在Vue.js 函數(shù)式組件中觸發(fā)一個事件?

在從函數(shù)式組件中觸發(fā)一個事件并不簡單。不幸的是,文檔中也沒有提到這一點。函數(shù)式組件中不可用 $emit 方法。stack overflow  上有人討論過這個問題:

How to emit an event from Vue.js Functional component?

5、Vue.js 的透明包裹組件

組件包裹一些DOM元素,并且公開了這些DOM元素的事件,而不是根DOM的節(jié)點實例。

例如:

<!-- Wrapper component for input --> <template>     <div class="wrapper-comp">         <label>My Label</label>         <input @focus="$emit('focus')" type="text"/>     </div> </template>

這里我們真正感興趣的是 input 節(jié)點,而不是 div 根節(jié)點,因為它主要是為了樣式和修飾而添加的。用戶可能對這個組件的幾個輸入事件感興趣,比如  blur、focus、click、hover等等。這意味著我們必須重新綁定每個事件。我們的組件如下所示。

<!-- Wrapper component for input --> <template>     <div class="wrapper-comp">         <label>My Label</label>         <input type="text"             @focus="$emit('focus')"             @click="$emit('click')"             @blur="$emit('blur')"             @hover="$emit('hover')"         />     </div> </template>

實際上這是完全沒必要的。簡單的解決方案是使用 Vue 實例上的屬性 vm.$listeners 將事件重新綁定到所需DOM 元素上:

<!-- Notice the use of $listeners --> <template>     <div class="wrapper-comp">         <label>My Label</label>         <input v-on="$listeners" type="text"/>     </div> </template> <!-- Uses: @focus event will bind to internal input element --> <custom-input @focus="onFocus"></custom-input>

6、為什么你不能在 slot 上綁定和觸發(fā)事件

我經(jīng)??吹接行╅_發(fā)人員,在 slot 上進(jìn)行事件的監(jiān)聽和分發(fā),這是不可能的。

組件的 slot  由調(diào)用它的父組件提供,這意味著所有事件都應(yīng)該與父組件相關(guān)聯(lián)。嘗試去傾聽這些變化意味著你的父子組件是緊密耦合的,不過有另一種方法可以做到這一點,Evan  You解釋得很好:

Is it possible to emit event from component inside slot #4332

Suggestion: v-on on slots

7、slot 中的 slot(訪問孫輩slot)

在某些時候,可能會遇到這種情況。假設(shè)有一個組件,比如 A ,它接受一些 slot 。遵循組合的原則,使用組件 A 構(gòu)建另一個組件 B 。然后你把 B 用在  C 中。

那么現(xiàn)在問題來了: 如何將 slot 從 C 組件傳遞到 A 組件?

要回答這個問題,首先取決你使用何種方式構(gòu)建組件? 如果你是用 render 函數(shù),那就很簡單。你只需要在組件 B 的 render  函數(shù)中進(jìn)行如下操作:

// Render function for component B function render(h) {     return h('component-a', {         // Passing slots as they are to component A         scopedSlot: this.$scopedSlots     } }

但是,如果你使用的是基于模板的方式,那么就有些糟糕了。幸運的是,在這個問題上有了進(jìn)展:

feat(core): support passing down scopedSlots with v-bind

感謝各位的閱讀,以上就是“Vue.js的注意事項有哪些”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對Vue.js的注意事項有哪些這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI