做者:Kevin Ball 譯者:前端小智 來源:vuejsdevelopers前端
點贊再看,養成習慣vue
本文
GitHub
github.com/qq449245884… 上已經收錄,更多往期高贊文章的分類,也整理了不少個人文檔,和教程資料。歡迎Star和完善,你們面試能夠參照考點複習,但願咱們一塊兒有點東西。git
不多有人最初編寫Vue組件時打算將其開源。咱們大多數人都是從本身編寫組件開始的——咱們有一個問題,而後決定經過構建一個組件來解決它。有時咱們發現本身想要在代碼庫的新位置解決相同的問題,所以咱們使用組件並對其進行重構,使其可重用。而後咱們想在一個不一樣的項目中使用它,因此咱們把它轉移到一個獨立的包中。而後咱們想「嘿,爲何不把這個分享給全世界呢?」因而咱們開源了這個組件。github
一方面,這意味着對於任何在Vue工做的人來講,均可以得到大量且不斷增加的開源組件,這很 piece。面試
另外一方面,由於這些組件中的大多數是從特定的狀況而來的,而且不是全部人都有跨多重環境重用組件的設計經驗,因此這些組件中的許多東西都不能很好地與Vue生態系統配合使用。編程
「很好」是什麼意思? 從高層次上講,這意味着行爲表現對於Vue開發人員來講很天然,而且易於擴展和集成到任何類型的應用程序中。瀏覽器
在探索了普遍的開源組件以後,下面幾點,我認爲下面是如何製做一個良好運行的Vue組件方式:微信
v-model
兼容性v-model
兼容性對於表單字段的組件使其成爲慣用的最重要方法之一就是要支持v-model
。 根據官方文檔介紹,v-model
本質上就是語法糖,即利用v-model
綁定數據後,其實就是既綁定了數據,又添加了一個input
事件監聽,以下:app
自定義事件也能夠用於建立支持 v-model
的自定義輸入組件。記住:函數
<input v-model="searchText">
複製代碼
等價於:
<input
v-bind:value="searchText"
v-on:input="searchText = $event.target.value"
>
複製代碼
當用在組件上時,v-model 則會這樣:
<custom-input
v-bind:value="searchText"
v-on:input="searchText = $event"
></custom-input>
複製代碼
爲了讓它正常工做,這個組件內的 <input>
必須:
將其 value
attribute 綁定到一個名叫 value
的 prop 上
在其 input
事件被觸發時,將新的值經過自定義的 input
事件拋出
寫成代碼以後是這樣的:
Vue.component('custom-input', {
props: ['value'],
template: `
<input
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
`
})
複製代碼
如今 v-model
就應該能夠在這個組件上完美地工做起來了:
<custom-input v-model="searchText"></custom-input>
複製代碼
爲了實現v-model
,組件須要實現input
事件。但其餘事件呢?好比點擊事件,鍵盤處理等等?雖然原生事件以 HTML 的形式冒泡,可是 Vue 的事件處理在默認狀況下並不冒泡。
例如,除非我作一些具體的事情,不然這是行不通的
<my-textarea-wrapper @focus="showFocus">
複製代碼
除非咱們在包裝組件中編寫發出focus
事件,不然將永遠不會調用showFocus
事件處理程序。不過,Vue 確實爲咱們提供了一種以編程方式訪問應用於組件的偵聽器的方法,所以咱們能夠將它們分配到正確的位置:$listener
對象。
再一想,緣由很明顯:這容許咱們將偵聽器傳遞到組件中的正確位置。例如,使用文本區域包裝器組件
<div class="my-textarea-wrapper">
<textarea v-on="$listeners" ></textarea>
</div>
複製代碼
如今發生在textarea
上的事件就是那些被傳遞的事件。
怎麼理解vue中$listeners
屬性?
假設有父組件Parent和子組件Child
// Parent
<template>
...
<child v-on:event-one="methodOne" v-on:event-two="methodTwo" />
...
</template>
複製代碼
那麼你在使用Child
時,傳入的全部v-on
事件均可以在$listeners
對象中找到。
// Child
created () {
console.log(this.$listeners) // { 'event-one': f(), 'event-two': f() }
}
複製代碼
如何處理textarea
的rows或在任何元素上添加簡單工具提示的title
標記等屬性呢
默認狀況下,Vue採用應用於組件的屬性,並將其放在該組件的根元素上。但這並不是老是咱們想要的。 若是咱們從上方再次查看textarea
包裝器,則在這種狀況下,將屬性應用於textarea
自己而不是div更有意義。
爲此,咱們告訴組件默認狀況下不要應用屬性,而是直接使用$attrs
對象應用它們,在 JS 代碼中:
export default {
inheritAttrs: false,
}
複製代碼
在模板中
<div class="my-textarea-wrapper">
<textarea v-bind="$attrs"></textarea>
</div>
複製代碼
官方文檔講解組件的屬性傳遞時,講到$attrs
和inheritAttrs
這兩個屬性,且兩個屬性結合會比較好用。乍一看沒看懂,結合代碼演示才搞清楚。
import Vue from 'vue';
Vue.component('base-input', {
inheritAttrs: false,
props: ['label', 'value'],
template: `
<label>
{{ label }}
<input
v-bind="$attrs"
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
</label>
`
})
new Vue({
el:'#root',
template:`
<base-input
v-model="username"
required
placeholder="Enter your username"
input="testInput"
></base-input>
`,
data:{
username:'',
}
})
複製代碼
先隱藏 inheritAttrs: false
和v-bind="$attrs"
,瀏覽器獲得的結果以下
此處有兩處異常:
placeholder
等屬性沒有傳到子組件;label
,而label
是不須要的$attrs
和inheritAttrs:false
即分別用來解決這兩個問題首先,inheritAttrs:false
解決子組件的根元素繼承父元素的屬性;其次,子組件中添加了v−bind="$attrs"
的元素會繼承父組件的屬性,即便props
中沒有定義該屬性
可訪問性和鍵盤導航是Web開發中最常被遺忘的部分之一,也是編寫要在生態系統中正常運行的組件時要正確處理的最重要的事情之一。
這意味着要確保組件符合瀏覽器規範:tab
鍵應該容許選擇表單字段。Enter
一般用於激活按鈕或連接。
有關常見組件的鍵盤導航建議的完整列表,能夠在W3C網站上找到。 遵循這些建議將使您的組件能夠在全部應用程序中使用,而不只僅是那些與可訪問性無關的組件。
當涉及到從組件到其父組件的數據通訊和用戶交互時,有兩個常見的選擇:props
中的回調函數和事件。 由於 Vue
的自定義事件不會像原生瀏覽器事件那樣冒泡,因此二者在功能上是等效的,可是對於可重用的組件,建議能使用事件就使用事件,其次在再是回調,爲何?
在Fullstack電臺的一期節目中,Vue 核心團隊成員Chris Fritz給出瞭如下理由:
使用事件使父組件能夠清楚地知道什麼。它明確區分了「咱們從父組件那裏獲得的東西」和「咱們發送給組件的東西」。
能夠在事件處理程序中直接使用表達式,從而爲簡單狀況提供極其緊湊的事件處理程序。
它更符合習慣——Vue示例和文檔傾向於使用事件來實現組件與其父組件之間的通訊。
幸運的是,若是當前使用的是props
回調,則很容易修改組件以發出事件。 使用回調的組件可相似以下:
// my-custom-component.vue
export default {
props: ['onActionHappened', ...]
methods() {
handleAction() {
... // your custom code
if (typeof this.onActionHappened === 'function') {
this.onActionHappened(data);
}
}
}
}
複製代碼
外面調用方式:
<my-custom-component :onActionHappened="actionHandler" />
複製代碼
更改成基於事件的方法以下所示:
// my-custom-component.vue
export default {
methods() {
handleAction() {
... // your custom code
this.$emit('action-happened', data);
}
}
}
複製代碼
外面調用方式:
<my-custom-component @action-happened="actionHandler" />
複製代碼
Vue的單文件組件結構使咱們能夠將樣式直接嵌入到組件中,尤爲是當與做用域結合使用時,這爲咱們提供了一種很好的方式來發布徹底打包的樣式化組件,而不會影響應用程序的其餘部分。
因爲該系統的強大功能,很容易將全部組件樣式放入組件中,並交付一個徹底樣式化的組件。問題是:沒有任何應用程序的樣式是相同的,而使組件在咱們的應用程序中看起來很完美的東西將使它在其餘人的應用程序中脫穎而出。因爲組件樣式一般比全局樣式表包含的時間晚,所以覆蓋它可能成爲一場專注性的噩夢。
防止這種狀況,建議任何CSS不是結構所必需的組件(顏色、邊框、陰影等)應該被排除在咱們的組件文件自己或可以被關閉。相反,考慮維護一個可定製的SCSS部分容許用戶定製他們的心的內容。
<template>
<div :class="isStyledClass">
<!-- my component -->
</div>
</template>
複製代碼
在 JS 中:
export default {
props: {
disableStyles: {
type: Boolean,
default: false
}
},
computed: {
isStyledClass() {
if (!this.disableStyles) {
return 'is-styled';
}
},
}
複製代碼
而後,咱們能夠
@import 'my-component-styles';
.is-styled {
@include my-component-styles();
}
複製代碼
這將容許咱們隨意使用現成的樣式,可是想要自定義的用戶再也不須要建立高度專注覆蓋,他們只需經過將disableStyles
屬性設置爲true
便可關閉樣式。
代碼部署後可能存在的BUG無法實時知道,過後爲了解決這些BUG,花了大量的時間進行log 調試,這邊順便給你們推薦一個好用的BUG監控工具 Fundebug。
原文:vuejsdevelopers.com/2018/06/18/…
文章每週持續更新,能夠微信搜索「 大遷世界 」第一時間閱讀和催更(比博客早一到兩篇喲),本文 GitHub github.com/qq449245884… 已經收錄,整理了不少個人文檔,歡迎Star和完善,你們面試能夠參照考點複習,另外關注公衆號,後臺回覆福利,便可看到福利,你懂的。