- props參數
- slot定製插槽
- event自定義事件
在使用 vue-cli 建立的項目中,組件的建立很是方便,只須要新建一個 .vue 文件,而後在 template 中寫好 HTML 代碼,一個簡單的組件就完成了 一個完整的組件,除了 template 之外,還有 script和 stylecss
<template>
<div class="headComponent">
子組件{{{myData}}
</div>
</template>
<script>
export default {
props:['data','type'],
inheritAttrs: false,
data(){
return{
myData:'',
}
},
mounted(){
},
methods:{
}
}
</script>
<style scoped>
</style>
複製代碼
而後在其餘文件的 js 裏面引入並註冊,就能直接使用這個組件了html
import list from '../components/headComponent.vue'
複製代碼
父對子傳參,就須要用到 props,一般的 props 是這樣的:vue
props:['data','type']
複製代碼
可是通用組件的的應用場景比較複雜,對 props 傳遞的參數應該添加一些驗證規則,經常使用格式以下:ajax
props: {
// 基礎類型檢測 (`null` 意思是任何類型均可以)
propA: Number,
// 多種類型
propB: [String, Number],
// 必傳且是字符串
propC: {
type: String,
required: true
},
// 數字,有默認值
propD: {
type: Number,
default: 100
},
// 數組/對象的默認值應當由一個工廠函數返回
propE: {
type: Object,
default: function () {
return { message: 'hello' }
}
},
// 自定義驗證函數
propF: {
validator: function (value) {
return value > 10
}
}
}
複製代碼
對於經過 props 傳入的參數,不建議對其進行操做,由於會同時修改父組件裏面的數據 // vue2.5已經針對 props 作出優化,這個問題已經不存在了 若是必定須要有這樣的操做,能夠這麼寫:vue-router
let copyData = JSON.parse(JSON.stringify(this.data))
複製代碼
爲何不直接寫 let myData = this.data 呢? 由於直接賦值,對於對象和數組而言只是淺拷貝,指向的是同一個內存地址,其中一個改變另外一個也會改變。而經過 JSON顛倒轉換以後,實現了深拷貝,則能夠互不影響。vue-cli
在通用組件中,一般會須要有各類事件,好比複選框的 change 事件,或者組件中某個按鈕的 click 事件,有時子組件須要觸發一個事件,並傳遞給父組件數組
// 子組件方法:觸發父組件方法,並傳遞參數data到父組件
handleSubmit(data){
this.$emit('submitToParent', data)
}
複製代碼
// 父組件調用子組件
<child-component @submitToParent="parentSubmit"></child-component>
... ...
// 父組件中被觸發的方法,接受到子組件傳來的參數
parentSubmit(data){
// 父組件的邏輯處理
}
複製代碼
父組件中的邏輯要放在父組件處理,子組件基於父組件的數據作的邏輯放在子組件中處理; 這樣既下降了耦合性,也保證了各自的數據不被污染。bash
一個通用組件,每每不可以完美的適應全部應用場景 因此在封裝組件的時候,只須要完成組件 80% 的功能,剩下的 20% 讓父組件經過 solt 解決session
上面是一個通用組件,在某些場景中,右側的按鈕是 「處理」 和 「委託」。在另外的場景中,按鈕須要換成 「查看」 或者 「刪除」 在封裝組件的時候,就不用寫按鈕,只須要在合適的位置留一個 slot,將按鈕的位置留出來,而後在父組件寫入按鈕函數
子組件
<div class="child-btn">
<!-- 具名插槽 -->
<slot name="button"></slot>
<!-- 匿名插槽(每一個組件只能有一個) -->
<slot><slot>
</div>
父組件
<child>
<!-- 對應子組件中button的插槽 -->
<button slot="button">slot按鈕</button>
</child>
複製代碼
開發通用組件的時候,只要不是獨立性很高的組件,建議都留一個 slot,即便還沒想好用來幹什麼。
開發過程當中,經常須要在子組件內添加新的內容,這時候能夠在子組件內部留一個或者多個插口
而後在調用這個子組件的時候加入內容
添加的內容就會分發到對應的 slot 中
slot 中還能夠做爲一個做用域,在子組件中定義變量,而後在父組件中自定義渲染的方式 子組件:
這個示例中,首先在子組件中添加 slot,並在子組件中定義了數組變量 navs 而後在父組件中以做用域 template 添加內容,其中 scope 是固有屬性,它的值對應一個臨時變量 props 而 props 將接收從父組件傳遞給子組件的參數 navs
關於slot的用法還可查看:juejin.im/post/5cc856…
Vue 沒有直接子對子傳參的方法,建議將須要傳遞數據的子組件,都合併爲一個組件。若是必定須要子對子傳參,能夠先從傳到父組件,再傳到子組件。 父子組件之間是經過 props 和 自定義事件來傳參,非父子組件一般會採用 Vuex 傳參 Vuex設計初衷是用來管理組件狀態,也能夠用於複雜組件的參數傳遞
可是 Vuex 的雖然能夠用來傳參,但並不推薦;由於 Vuex 相似於一個全局變量,會一直佔用內存 在寫入數據龐大的 state 的時候,就會產生內存泄露(人是活的,不能由於事物有弊端就不使用,合理利用便可)。 Tips: 當頁面刷新的時候,Vuex 會初始化,同時也會丟失編輯過的數據 若是刷新頁面時須要保留數據,能夠經過 url 或者 sessionstorage 保存 id,而後 ajax 請求數據
在編寫組件的時候,能夠在 style 標籤中添加 scoped,讓標籤中的樣式只對當前組件生效 可是一味的使用 scoped,確定會產生大量的重複代碼 因此在開發的時候,應該避免在組件中寫樣式 當全局樣式寫好以後,再針對每一個組件,經過 scoped 屬性添加組件樣式
Vue 還能夠將多個子組件,都掛載在同一個位置,經過變量來切換組件,實現 tab 菜單這樣的效果
當組件擁有 name 屬性的時候,就能夠在它的模板內遞歸的調用本身,這在開發樹形組件的時候十分有效
最終渲染結果:
在vue2.0以後的版本中,不容許子組件直接改變父組件的數據,在1.0的版本中能夠這樣操做的,可是每每項目需求須要改變父組件的數據,那咱們如何變通呢? 當咱們把父元素的數據給子組件時,要傳一個非基礎類型,即傳遞對象or數組,子組件經過訪問對象中的屬性操做數據,由於對象和數組是傳引用,因此在子組件中修改的時候,父組件也會同步改變,以下:
// 父組件要props傳遞給子組件的數據
myData:{
info:'父組件信息'
}
// 子組件
<template id="tpl">
<div>
<button @click="change">change</button>
<p>{{data.info}}</p>
</div>
</template>
... 省略部分無關代碼 ...
props:['data'],
methods:{
change(){
this.data.info = 'change info'
}
}
複製代碼
當子組件點擊change按鈕改變數據的時候,父組件也會同步改變
若是不想影響父組件的值,咱們也能夠用文章開頭講的JSON顛倒轉換的方式,在mounted方法中進行深拷貝,在data中初始化數據時用另外一個變量做爲承載,這樣才承載變量改變,就不會影響父組件該變量的值了。
參考博客: www.cnblogs.com/wisewrong/p… www.cnblogs.com/yesyes/p/66…