uniapp - props、 ref、$emit、$parent、$child、$on、$set


舉個例子來解釋一下何為父組件,何為子組件?

index.vue導入sunui-cell組件的時候,我們就稱index.vue為父組件依次類推,在vue中只要能獲取到組件的實例,那么就可以調用組件的屬性或是方法進行操作

 

 

一、props(一般用來單向傳值)

1. 何為單向傳值?

即父組件傳值給子組件(首次)但不能動態(再次)改變子組件現有的值,但我非要改呢? 通過watch監聽或者通過$ref標識獲取實例后修改以及使用v-modal,使用v-modal會存在不同步情況->使用.sync

 

2.props靜態傳值

子組件通過props選項來聲明一個自定義的屬性,然后父組件就可以在嵌套標簽的時候,通過這個屬性往子組件傳遞數據 - 引用腳本之家

 

 

 

 

 

 

3. props動態傳值

通過v-bind綁定props的自定義的屬性,傳遞去過的就不是靜態的字符串了,它可以是一個表達式、布爾值、對象等等任何類型的值 - 引用腳本之家

 

 

 

 

 

 

 

4. props最適合傳遞數據,它並不能調用子組件里的屬性和方法

 

二、$ref

1.不大適合傳遞數據

主要用來調用子組件里的屬性和方法

 

 

 

 

2. 通常是初始化頁面(也就是視圖層渲染完以后)才能調用

如果是初始化的話建議在mounted生命周期或者使用this.$nextTick()將回調延遲到下次 DOM 更新循環之后執行(但我們首先得標識ref,相同組件ref的值如果重復會被后面的組件覆蓋),如果不是初始化的話必須要等待它加載完以后才能夠調用(this.nextTick)

 

 

 

 

三、$emit

1. $emit 綁定一個自定義事件event,當這個這個語句被執行到的時候,就會將參數arg傳遞給父組件,父組件通過@event監聽並接收參數

 

 

 

四、$on(非父組件之間傳值)

 

1.父組件需要導入A和B組件

<template>
	<view class="content">
		<view style="padding: 12px 15px;">
			點擊hover效果
		</view>
		<onA></onA>
		<onB></onB>
	</view>
</template>

<script>
	import onA from '@/components/onA.vue';
	import onB from '@/components/onB.vue';
	export default {
		data() {
			return {
				title: 'Hello'
			}
		},
		components: {
			onA,
			onB
		},
		onLoad() {
		},
		mounted() {
		},
		methods: {

		}
	}
</script>

<style>
	.content {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
	}

	.logo {
		height: 200rpx;
		width: 200rpx;
		margin-top: 200rpx;
		margin-left: auto;
		margin-right: auto;
		margin-bottom: 50rpx;
	}

	.text-area {
		display: flex;
		justify-content: center;
	}

	.title {
		font-size: 36rpx;
		color: #8f8f94;
	}
</style>

 

2. onA組件

<template>
	<view>
		<button type="primary" @click="onSend">傳值給onB組件</button>
	</view>
</template>

<script>
	import bridge from '@/utils/bridge.js';
	export default {
		data() {
			return {
				msg: 'hello,onB'
			};
		},
		methods: {
			onSend() {
				bridge.$emit('receiveA', this.msg);
			}
		},
		mounted() {
			bridge.$on('receiveB', (val) => {
				console.log('我是onA組件,接收來自onB的值:', val);
			});
		}
	}
</script>

<style>

</style>

 

3.onB組件

<template>
	<view>
		<button type="primary" @click="onSend">傳值給onA組件</button>
	</view>
</template>

<script>
	import bridge from '@/utils/bridge.js';
	export default {
		data() {
			return {
				msg: 'hello,onA'
			};
		},
		methods: {
			onSend() {
				bridge.$emit('receiveB', this.msg);
			}
		},
		mounted() {
			bridge.$on('receiveA', (val) => {
				console.log('我是onB組件,接收來自onA的值:', val);
			});
		}
	}
</script>

<style>

</style>

 

4.bridge.js

import Vue from 'vue'
export default new Vue()

 

 

五、$parent(用於子組件獲取父組件實例) - 當前組件樹的根 Vue 實例。如果當前實例沒有父實例,此實例將會是其自己

 

 

 

 

 

六、$child - 當前實例的直接子組件。需要注意 $children 並不保證順序,也不是響應式的。如果你發現自己正在嘗試使用 $children 來進行數據綁定,考慮使用一個數組配合 v-for 來生成子組件,並且使用 Array 作為真正的來源

 

<template>
	<view class="content">
		<view style="padding: 12px 15px;">
			點擊hover效果
		</view>
		<onA></onA>
		<onB></onB>
	</view>
</template>

<script>
	import onA from '@/components/onA.vue';
	import onB from '@/components/onB.vue';
	export default {
		data() {
			return {
				title: 'Hello'
			}
		},
		components: {
			onA,
			onB
		},
		onLoad() {
		},
		mounted() {
			console.log(this.$root.$children[0].$children[0]._data);
			console.log(this.$root.$children[0].$children[1]._data.msg);
			console.log(this.$root.$children[0].$children[2]._data.msg);
		},
		methods: {

		}
	}
</script>

<style>
	.content {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
	}

	.logo {
		height: 200rpx;
		width: 200rpx;
		margin-top: 200rpx;
		margin-left: auto;
		margin-right: auto;
		margin-bottom: 50rpx;
	}

	.text-area {
		display: flex;
		justify-content: center;
	}

	.title {
		font-size: 36rpx;
		color: #8f8f94;
	}
</style>

  

七、$set - 在開發過程中,我們時常會遇到這樣一種情況:當vue的data里邊聲明或者已經賦值過的對象或者數組(數組里邊的值是對象)時,向對象中添加新的屬性,如果更新此屬性的值,是不會更新視圖的

 

1.運行這個示例時,我們發現對象新增的屬性(e)是不會更新

<template>
	<view>
		<view @click="addd(obj)">點擊增加1:{{obj.d}}</view>
		<view @click="adde(obj)">點擊增加2:{{obj.e}}</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				obj: {}
			}
		},
		mounted() {
			// 原有的
			this.obj = {
				d: 0
			};
			// 新增的對象.e
			this.obj.e = 0;
			console.log('after--', this.obj);
		},
		methods: {
			addd(item) {
				item.d = item.d + 1;
				console.log('item--1', item);
			},
			adde(item) {
				item.e = item.e + 1;
				// this.$forceUpdate();
				console.log('item--2', item);
			}
		}
	}
</script>

  

2. 我們有兩種解決方案,一種是利用this.$set或者this.$foreUpdate();讓它渲染到視圖層 - 代碼引用簡書:https://www.jianshu.com/p/71b1807b1815

 

 

<template>
	<view>
		<view @click="addd(obj)">點擊增加1:{{obj.d}}</view>
		<view @click="adde(obj)">點擊增加2:{{obj.e}}</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				obj: {}
			}
		},
		mounted() {
			// 原有的
			this.obj = {
				d: 0
			};
			// 新增的對象.e
			// this.obj.e = 0;
			this.$set(this.obj, 'e', 0);
			console.log('after--', this.obj);
		},
		methods: {
			addd(item) {
				item.d = item.d + 1;
				console.log('item--1', item);
			},
			adde(item) {
				item.e = item.e + 1;
				// this.$forceUpdate();
				console.log('item--2', item);
			}
		}
	}
</script>

  

理清一下已經使用過的vue實例,可能會再次更新(-.-)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM