props
能夠是數組或對象,用於接收來自父組件的數據。javascript
// 父組件 List.vue
<template>
<div>
<List-item :str="str" :obj="obj" :arr="arr"></List-item>
</div>
</template>
<script>
import ListItem from "./ListItem";
export default {
data() {
return {
str: "給子組件傳值",
obj: {msg: "給子組件傳值"},
arr: [1, 2, 3]
}
},
components: {
ListItem
}
}
</script>
// 子組件 ListItem.vue
<template>
<div>
<div>{{msg}}</div>
<div>{{obj}}</div>
<div>{{arr}}</div>
</div>
</template>
<script>
export default {
props: {
msg: String, // props是字符串
obj: Object, // props是對象
arr: Array // props是數組
}
}
</script>
複製代碼
.sync
修飾符 .sync 是 2.3.0+
新增,它對 props
起到了一種修飾的做用,使用 .sync
進行修飾的 props
意味子組件有修改它的意圖,這種狀況下它只起到一個標註性做用,有它沒它都不會影響邏輯(後文會介紹使用 .sync 的其餘做用)。html
使用 .sync
修改上邊的代碼:vue
// 父組件 List.vue
<template>
<!-- 這裏不寫 .sync 也不會影響結果 --> <List-item :title.sync="title" @update:title="updataTitle"></List-item> </template> <script> import ListItem from "./ListItem"; export default { data() { return { title: "我是title", } }, components: { ListItem }, methods: { updataTitle(res) { this.title = res; } } } </script> // 子組件 ListItem.vue <template> <div> <button @click="handleClick">Click me</button> <div>{{title}}</div> </div> </template> <script> export default { props: { title: String, }, methods: { handleClick() { // 子組件向父組件傳值 this.$emit('update:title', '我要父組件更新 title'); } } } </script> 複製代碼
使用.sync
向子組件傳遞 多個props:java
當咱們用一個對象同時設置多個 prop
的時候,也能夠將這個 .sync
修飾符和 v-bind
配合使用:web
<text-document v-bind.sync="doc"></text-document> 複製代碼
這樣會把 doc
對象中的每個屬性 (如 title) 都做爲一個獨立的 prop
傳進去,而後各自添加用於更新的 `v-on 監聽器。vuex
更多介紹,.sync 。api
這種方式,從嚴格意思上講不是值的傳遞,而是一種"取"(不推薦直接經過實例進行值的獲取)。數組
能夠經過 Vue 的實例屬性 $parent
得到父組件的實例,藉助實例能夠調用父實例中的方法,或者獲取父實例上的屬性,從而達到取值的目的。微信
// 父組件 List.vue
...
<script>
export default {
data() {
return {
message: "hello children",
msg: "hello"
}
},
methods: {
sendMessage() {
return this.message;
}
}
}
</script>
// 子組件 ListItem.vue
<template>
<div>
<div>{{data}}</div>
<div>{{msg}}</div>
</div>
</template>
<script>
export default {
data() {
return {
data: "",
msg: ""
}
},
mounted() {
this.data = this.$parent.sendMessage(); // 調用父實例中的方法
this.msg = this.$parent.msg; // 獲取父實例中的屬性
}
}
</script>
複製代碼
拓展網絡
子組件調用父組件中的方法:
經過 $parent
獲取父實例 this.$parent.event
。
經過 props
傳遞方法。
經過 $emit
監聽父組件中的方法 this.$emit("envnt")
。
$emit
發送一個自定義事件,事件名稱是一個字符串。v-on
綁定子組件發送的自定義事件。// 父組件 List.vue
<template>
<div>
<!-- 監聽自定義事件 -->
<List-item v-on:welcome="getWelcome"></List-item>
</div>
</template>
<script>
import ListItem from "./List-item";
export default {
components: {
ListItem
},
methods: {
getWelcome(data) {
alert(data)
}
}
}
</script>
// 子組件 ListItem.vue
<template>
<button @click="handleClick">Click me</button>
</template>
<script>
export default {
methods: {
handleClick() {
// 使用 $emit 發送自定義事件 welcome
this.$emit('welcome', 'hello');
}
}
}
</script>
複製代碼
此方式同 $parent
,這裏就不進行介紹了。
儘管存在 prop
和事件,有的時候你仍可能須要在 JavaScript 裏直接訪問一個子組件。爲了達到這個目的,能夠經過 ref
特性爲這個子組件賦予一個 ID 引用。
<template>
<div>
<List-item ref="item" :title="title"></List-item>
<div>{{data}}</div>
</div>
</template>
<script>
import ListItem from "./List-item";
export default {
data() {
return {
title: "我是title",
data: ""
}
},
components: {
ListItem
},
mounted() {
this.data = this.$refs.item.message;
}
}
</script>
複製代碼
非父子組件傳值,能夠使用一個空的 Vue 實例做爲中央事件總線,結合實例方法 $on
和 $emit
完成傳值操做。
Bus 的定義方式有如下三種:
Bus
抽離出來,組件有須要時進行引入。// Bus.js
import Vue from 'vue'
const Bus = new Vue()
export default Bus
複製代碼
Bus
掛載到 Vue 根實例的原型上。import Vue from 'vue'
Vue.prototype.$bus = new Vue();
複製代碼
Bus
注入到 Vue 根對象上。import Vue from 'vue'
const Bus = new Vue()
new Vue({
el:'#app',
data: {
Bus
}  
})
複製代碼
下面案例中的 Bus
掛載在 Vue 原型上:
// 組件1 使用 $emit 向外部發布自定義事件
<template>
<button @click="handleClick"> Send Message</button>
</template>
<script>
export default {
data() {
return {
message: "給兄弟組件傳值",
}
},
methods: {
handleClick() {
this.$Bus.$emit("sendMessage", this.message)
}
}
}
</script>
// 組件2 使用 $on 訂閱外部發布的事件
<template>
<div>
{{data}}
</div>
</template>
<script>
export default {
data() {
return {
data: "",
}
},
mounted() {
this.$Bus.$on("sendMessage", data => {
this.data = data;
})
}
}
</script>
複製代碼
注意:註冊的 Bus
要在組件銷燬時卸載,不然會屢次掛載,形成觸發一次但多個響應的狀況。
beforeDestroy () {
this.$Bus.$off('sendMessage', this.message);
}
複製代碼
Vuex 是一個專爲 Vue.js 應用程序開發的狀態管理模式。它採用集中式存儲管理應用的全部組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。
圖片引用自網絡:
Vuex 的具體使用。
不是方法的方法:
子組件 A
經過事件 $emit
傳值傳給父組件。
父組件經過屬性 props
傳值給子組件 B
。
provide
選項容許咱們指定咱們想要提供給後代組件的數據/方法。
provide: function () {
return {
getMap: this.getMap
}
}
複製代碼
而後在任何後代組件裏,咱們均可以使用 inject
選項來接收指定的咱們想要添加在這個實例上的屬性:
inject: ['getMap']
複製代碼
provide
和 inject
主要爲高階插件/組件庫提供用例。並不推薦直接用於應用程序代碼中。
// 父級組件提供 'foo'
var Provider = {
provide: {
foo: 'bar'
},
// ...
}
// 子組件注入 'foo'
var Child = {
inject: ['foo'],
created () {
console.log(this.foo) // => "bar"
}
// ...
}
複製代碼
然而,依賴注入仍是有負面影響的。它將你應用程序中的組件與它們當前的組織方式耦合起來,使重構變得更加困難。同時所提供的屬性是非響應式的。這是出於設計的考慮,由於使用它們來建立一箇中心化規模化的數據跟使用 $root 作這件事都是不夠好的。若是你想要共享的這個屬性是你的應用特有的,而不是通用化的,或者若是你想在祖先組件中更新所提供的數據,那麼這意味着你可能須要換用一個像 Vuex 這樣真正的狀態管理方案了。
這個兩個屬性是 2.4
新增的特性。
$attrs:
官網介紹的很累贅,暫且理解爲非 props
屬性集合。更多介紹。
當一個組件中沒有聲明任何 prop 時,this.$attrs
能夠獲取到全部父做用域的屬性綁定 (class 和 style 除外),而且能夠經過 v-bind="$attrs"
傳給其內部組件 —— 在建立高級別的組件時很是有用。
inheritAttrs:
控制元素屬性是否顯示在 dom 上,默認值爲 true
。
默認狀況下父做用域的不被認做 props 的特性綁定 (attribute bindings) 將會「回退」且做爲普通的 HTML 特性應用在子組件的根元素上。當撰寫包裹一個目標元素或另外一個組件的組件時,這可能不會老是符合預期行爲。經過設置 inheritAttrs 到 false,這些默認行爲將會被去掉。而經過 (一樣是 2.4 新增的) 實例屬性 $attrs 可讓這些特性生效,且能夠經過 v-bind 顯性的綁定到非根元素上。
祖先組件:
<template>
<div>
<List-item :title="title" :message="message"></List-item>
</div>
</template>
<script> import ListItem from "./List-item"; export default { data() { return { title: "我是title", message: "傳給後代" } }, components: { ListItem } } </script>
複製代碼
父組件:
<template>
<div>
<h1>{{title}}</h1>
<h2>{{$attrs.message}}</h2>
<!-- 經過 v-bind="$attrs" 傳入後代組件-->
<ListItem2 v-bind='$attrs'></ListItem2>
</div>
</template>
<script> import ListItem2 from './List-item2' export default { props: { title: String }, components: { ListItem2 }, // 默認爲 true,若是傳入的屬性子組件沒有 prop 接受,就會以字符串的形式做爲標籤的屬性存在 <div message="傳給後代"></div> // 設爲 false,在 dom 中就看不到這些屬性 <div>...</div> inheritAttrs: false } </script>
複製代碼
後代組件:
<template>
<div>
{{$attrs.message}}
</div>
</template>
<script> export default { mounted() { console.log(this.$attrs) // {message: "傳給後代"} } } </script>
複製代碼
渲染出來的結果爲:
在實際項目中確實有遇到插槽 後備內容
動態顯示的狀況,因此這裏要補充一下插槽 後備內容
是如何與子組件進行通訊的。
插槽後備內容是指:寫在父組件中,包含在子組件標籤裏的,與子組件中的 slot
對應。
<template>
<child-component>
我是插槽的後備內容
</child-component>
</template>
複製代碼
好比這裏有一個含有 slot
的 current-user
組件,它的模版結構是這樣的:
<!-- 子組件 current-user.vue -->
<template>
<div>
<div>current-user組件</div>
<slot>插槽裏默認顯示:{{user.firstName}}</slot>
</div>
</template>
<script> export default { data() { return { user: { firstName: "zhao", lastName: "xinglei" } } } } </script>
複製代碼
它的父組件是這樣的:
<!-- 父組件 Users.vue -->
<template>
<div>
<div>我是Users組件</div>
<current-user>
我是插槽裏的後備內容: {{user.lastName}}(我想顯示爲子組件中 user.lastName )
</current-user>
</div>
</template>
<script> import CurrentUser from './Current-User.vue' export default { components: { CurrentUser } } </script>
複製代碼
咱們看到,在父組件 Users
中,爲子組件 current-user
提供的後備內容中,想要顯示子組件定義的 user.firstName
是不能作到的。
官網中提供一個指令 v-slot,它與 props
結合使用從而達到插槽後備內容與子組件通訊的目的。
咱們首先須要在子組件的 slot
中傳遞一個 props
(這個props
叫作插槽props),這裏咱們起名叫 user
:
<!-- 子組件 current-user.vue -->
<template>
<div>
<div>current-user組件</div>
<slot :user="user">
插槽裏默認顯示:{{user.firstName}}
</slot>
</div>
</template>
複製代碼
在父組件中,包含插槽後備內容的子組件標籤上咱們綁定一個 v-slot
指令,像這樣:
<template>
<div>
<div>我是Users組件</div>
<!-- slotProps裏的內容就是子組件傳遞過來的 props -->
<!-- "user": { "firstName": "zhao", "lastName": "xinglei" } -->
<current-user v-slot="slotProps">
{{slotProps}}
</current-user>
</div>
</template>
複製代碼
最後渲染出來的結果爲:
官網給這種插槽起名叫作做用域插槽
,更多瞭解。
1. 組件之間傳值無非就是經過屬性、事件和操做 Vue 實例進行的。
2. 操做實例進行組件件通訊,實例屬性 $root、$parent、$children 分別對應了根實例、父實例、子實例。
3 ref 子組件引用,在操做表單元素時會應用的到。
4. Vuex 是一個專爲 Vue.js 應用程序開發的狀態管理模式,簡單的應用不要使用 Vuex。
5. Vue.observable() 讓一個對象可響應,能夠做爲最小化的跨組件狀態存儲器(本文未提到)。
複製代碼
我的博客同步更新:https: www.webinfoq.cn
微信公衆號:webinfoq