Vue 基礎組件間的資料傳遞
props
- 從外部接收指定資料
<body>
<div id="app">
<my-component :from-parent="text" />
</div>
<script type="text/x-template" id="my-component">
<div>
<div> From parent text:{{ fromParent }} </div>
<div> From self text:{{ text }} </div>
</div>
</script>
<script>
Vue.component('my-component', {
props: ['fromParent'],
template: '#my-component',
data: () => ({
text: '來自自己',
}),
});
new Vue({
el: '#app',
data: {
text: '來自父組件',
},
});
</script>
</body>
- 檢查型別
<body>
<div id="app">
<my-component :prop-a="text" />
</div>
<script type="text/x-template" id="my-component">
<h1>{{ propA }}</h1>
</script>
<script>
Vue.component('my-component', {
template: '#my-component',
props: {
parentMsg: null, // null 代表不檢查型別
propA: Number, // 限定數字
propB: [String, Number], // 多種條件可用 [ ] 隔開
propC: {
// 必要欄位,且限定字串型別
type: String,
// required: true,
},
propD: {
// 數字型別,且有預設值
type: Number,
default: 100,
},
propE: {
// Object 型別,代表可接受的是個物件或陣列的型別
type: Object,
default: function () {
return {
message: 'hello',
};
},
},
propF: {
// 自訂的條件驗證
validator: function (value) {
return value > 10;
},
},
},
});
new Vue({
el: '#app',
data: {
text: 123,
},
});
</script>
</body>
- props 的值如果是物件
會發生 pass by reference
<body>
<div id="app">
<div>來自父組件:{{ counts }}</div>
<br />
<my-component :count="counts"></my-component>
<my-component :count="counts"></my-component>
<my-component :count="counts"></my-component>
</div>
<script>
Vue.component('my-component', {
props: ['count'],
template: `
<div class="component">
<span>{{ count.num }}</span>
<button @click="plus">add</button>
</div>
`,
methods: {
plus() {
this.count.num++;
},
},
});
new Vue({
el: '#app',
data: () => ({
counts: {
num: 0,
},
}),
});
</script>
</body>
這時可以用 function
的形式回傳一個新的值,那麼每個元件內的變數就是獨立的了
<body>
<div id="app">
<div>來自父組件:{{ counts }}</div>
<br />
<my-component :count="counts"></my-component>
<my-component :count="counts"></my-component>
<my-component :count="counts"></my-component>
</div>
<script>
Vue.component('my-component', {
props: ['count'],
template: `
<div class="component">
<span>{{ independent }}</span>
<button @click="plus">add</button>
</div>
`,
data() {
return {
independent: this.count.num,
};
},
methods: {
plus() {
this.independent++;
},
},
});
new Vue({
el: '#app',
data: () => ({
counts: {
num: 0,
},
}),
});
</script>
</body>
單向資料流
父元件可以影響子元件但子元件無法影響父元件
外部資料透過 props 傳進來,若要更新父元件必須透過發生 event 的方式告知父元件必須被更新,但是由父元件自己更新
<body>
<div id="app">
<p>父元件:{{ text }}<input v-model="text" /></p>
<p>元件:<my-component :from-parent="text"></my-component></p>
</div>
<script>
Vue.component('my-component', {
template: '<span>{{ fromParent }}<input v-model="message"></span>',
props: {
fromParent: String,
},
data() {
return {
message: this.fromParent,
};
},
});
new Vue({
el: '#app',
data: {
text: 'hello',
},
});
</script>
</body>
透過 $emit 更新父元件
<body>
<div id="app">
<p>父元件:{{ text }}<input v-model="text" /></p>
<hr />
<p>元件:<my-component :from-parent="text"></my-component></p>
</div>
<script>
Vue.component('my-component', {
template: `
<span>
{{ fromParent }}
<input v-model="message">
<button @click="updateText">Update</button>
</span>
`,
props: {
fromParent: String,
},
data() {
return {
message: this.fromParent,
};
},
methods: {
updateText() {
this.$parent.$emit('update', this.message);
},
},
});
new Vue({
el: '#app',
data: {
text: 'hello',
},
methods: {
selfUpdate(val) {
this.text = val;
},
},
mounted() {
this.$on('update', this.selfUpdate);
},
});
</script>
</body>
event bus
我們都知道 Vuex 可以幫助我們統一管理狀態,但如果專案沒有那麼龐大或複雜的話使用 Vuex 就有些殺雞焉用牛刀的感覺,那麼我們就可以使用 event bus 來作為組件溝通的另一項選擇
<body>
<div id="app">
<my-component1></my-component1>
<hr />
<my-component2></my-component2>
</div>
<script>
// event bus
var bus = new Vue();
Vue.component('my-component1', {
template: `
<div class="my-component1">
<input v-model="text">
<button @click="submit">Submit</button>
</div>
`,
data() {
return {
text: '123',
};
},
methods: {
submit() {
bus.$emit('receive', this.text);
},
},
});
Vue.component('my-component2', {
template: `
<div class="my-component2">{{ text }}</div>
`,
data() {
return {
text: '456',
};
},
created() {
bus.$on('receive', (newText) => {
this.text = newText;
});
},
});
var app = new Vue({
el: '#app',
});
</script>
</body>