应用场景
在vue中父子组件是通过props传递数据的。通常有以下几种场景:
- 子组件展示父组件传递过来的props,一般是字符串
- 子组件接受父组件传递过来的props,作为本地数据使用
- 子组件接受父组件的传递过来的props,进行转换后展示(计算得到某个值)
- 子组件修改父组件传递过来的props
子组件展示父组件传递过来的props
【1】传递的prop是基础类型的值,父组件改变data,子组件随之改变
parent.vue
<template>
<div>
<p>这是父元素的内容</p>
<div>{{city}}</div>
<button v-on:click='changeCity'>点我改变city</button>
<child v-bind:city='city'></child>
</div>
</template>
<script>
import Child from './passPropChild'
export default {
name: 'parent',
data: function () {
return {
city: '北京'
}
},
components: {
child: Child
},
methods: {
changeCity: function () {
this.city = this.city + Math.random().toFixed(2)
}
}
}
</script>
<style scoped>
</style>
child.vue
<template>
<div>
<p>这是子元素的内容</p>
<div>{{ city}}</div>
</div>
</template>
<script>
export default {
name: 'child',
// eslint-disable-next-line vue/no-dupe-keys
props: ['city'],
data: function () {
return {
}
},
methods: {
}
}
</script>
<style scoped>
</style>
【2】传递的数据类型是引用类型,父组件改变data,子组件随之改变
parent.vue
<template>
<div>
<p>这是父元素的内容</p>
<ul>
<li v-for='item in cityList' :key="item.id">
{{item.name}}
</li>
</ul>
<button v-on:click='changeCity'>点我改变city</button>
<child v-bind:cityList='cityList'></child>
</div>
</template>
<script>
import Child from './passPropChild'
export default {
name: 'parent',
data: function () {
return {
cityList: [
{
id: 1,
name: '北京'
},
{
id: 2,
name: '上海'
},
{
id: 3,
name: '广州'
}
]
}
},
components: {
child: Child
},
methods: {
changeCity: function () {
this.cityList.push({
id: 4,
name: '我是乱入的'
})
}
}
}
</script>
<style scoped>
</style>
child.vue
<template>
<div>
<p>这是子元素的内容</p>
<ul>
<li v-for='item in cityList' :key="item.id">
{{item.name}}
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'child',
// eslint-disable-next-line vue/no-dupe-keys
props: ['cityList'],
data: function () {
return {
}
},
methods: {
}
}
</script>
<style scoped>
</style>
子组件接受父组件的props作为本地数据使用
定义一个本地的data属性,将这个prop作为初始值
【1】传递的prop是基础类型的值,父组件改变data,子组件不改变
parent.vue
<template>
<div>
<p>这是父元素的内容</p>>
<div>{{city}}</div>
<button v-on:click='changeCity'>点我改变city</button>
<child v-bind:city='city'></child>
</div>
</template>
<script>
import Child from './passPropChild'
export default {
name: 'parent',
data: function () {
return {
city: '北京'
}
},
components: {
child: Child
},
methods: {
changeCity: function () {
this.city = this.city + Math.random().toFixed(2)
}
}
}
</script>
<style scoped>
</style>
child.vue
<template>
<div>
<p>这是子元素的内容</p>
<p>{{cityC}}</p>
</div>
</template>
<script>
export default {
name: 'child',
// eslint-disable-next-line vue/no-dupe-keys
props: ['city'],
data: function () {
return {
cityC: this.city
}
},
methods: {
}
}
</script>
<style scoped>
</style>
【2】传递的数据类型是引用类型,父组件改变data,子组件随之改变
parent.vue
<template>
<div>
<p>这是父元素的内容</p>
<ul>
<li v-for='item in cityList' :key="item.id">
{{item.name}}
</li>
</ul>
<button v-on:click='changeCity'>点我改变city</button>
<child v-bind:cityList='cityList'></child>
</div>
</template>
<script>
import Child from './passPropChild'
export default {
name: 'parent',
data: function () {
return {
cityList: [
{
id: 1,
name: '北京'
},
{
id: 2,
name: '上海'
},
{
id: 3,
name: '广州'
}
]
}
},
components: {
child: Child
},
methods: {
changeCity: function () {
this.cityList.push({
id: 4,
name: '我是乱入的'
})
}
}
}
</script>
<style scoped>
</style>
child.vue
<template>
<div>
<p>这是子元素的内容</p>
<ul>
<li v-for='item in cityListC' :key="item.id">
{{item.name}}
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'child',
// eslint-disable-next-line vue/no-dupe-keys
props: ['cityList'],
data: function () {
return {
cityListC: this.cityList
}
},
methods: {
}
}
</script>
<style scoped>
</style>
子组件接受父组件的props进行转换后展示
用这个prop的值定义一个计算属性
【1】传递的prop是基础类型的值,父组件改变data,子组件随之改变
parent.vue
<template>
<div>
<p>这是父元素的内容</p>
<div>{{city}}</div>
<button v-on:click='changeCity'>点我改变city</button>
<child v-bind:city='city'></child>
</div>
</template>
<script>
import Child from './passPropChild'
export default {
name: 'parent',
data: function () {
return {
city: '北京'
}
},
components: {
child: Child
},
methods: {
changeCity: function () {
this.city = this.city + Math.random().toFixed(2)
}
}
}
</script>
<style scoped>
</style>
child.vue
<template>
<div>
<p>这是子元素的内容</p>
<p>{{cityChange}}</p>
</div>
</template>
<script>
export default {
name: 'child',
// eslint-disable-next-line vue/no-dupe-keys
props: ['city'],
data: function () {
return {
cityC: this.city
}
},
methods: {
},
computed: {
cityChange: function () {
return this.city + '1'
}
}
}
</script>
<style scoped>
</style>
【2】传递的数据类型是引用类型,父组件改变data,子组件随之改变
parent.vue
<template>
<div>
<p>这是父元素的内容</p>
<ul>
<li v-for='item in cityList' :key="item.id">
{{item.name}}
</li>
</ul>
<button v-on:click='changeCity'>点我改变city</button>
<child v-bind:cityList='cityList'></child>
</div>
</template>
<script>
import Child from './passPropChild'
export default {
name: 'parent',
data: function () {
return {
cityList: [
{
id: 1,
name: '北京'
},
{
id: 2,
name: '上海'
},
{
id: 3,
name: '广州'
}
]
}
},
components: {
child: Child
},
methods: {
changeCity: function () {
this.cityList.push({
id: 4,
name: '我是乱入的'
})
}
}
}
</script>
<style scoped>
</style>
child.vue
<template>
<div>
<p>这是子元素的内容</p>
<ul>
<li v-for='item in cityListC' :key="item.id">
{{item.name}}
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'child',
// eslint-disable-next-line vue/no-dupe-keys
props: ['cityList'],
data: function () {
return {
}
},
methods: {
},
computed: {
cityListC: function () {
var newCityList = []
for (let i = 0; i < this.cityList.length; i++) {
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
this.cityList[i].name = this.cityList[i].name + 1
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
newCityList.push(this.cityList[i])
}
return newCityList
}
}
}
</script>
<style scoped>
</style>
子组件修改父组件传递过来的props
【1】传递的数据类型是基础类型,子组件修改父组件传递过来的props
,报错。
【2】传递的数据类型是引用类型,子组件将父组件传递过来的props
作为本地数据,子组件修改父组件传递过来的props
,父组件也会随之改变。
总结:
【1】子组件接受父组件传递过来的props
仅作为展示时:无论什么数据类型,父组件改变,子组件随之改变。
对于这个场景,子组件只是展示,子组件随父组件变化是符合场景需求的
【2】子组件接受父组件传递过来的props作为本地数据时:prop
为基础类型的值,父组件改变,子组件不变;prop
为引用类型的值,父组件改变,子组件随之改变。
对于这个场景,子组件是在父组件的数据基础上进行加工,父组件数据改变,子组件是希望同步响应的,解决的方法:使用watch
来监听prop
。产生这个问题的原因是,因为生命周期的关系,组件的data
属性,在reated
,只在初始化的时候赋值了一次。
【3】子组件接受父组件传递过来的props作为计算属性时:无论什么数据类型,父组件改变,子组件随之改变。
【4】子组件修改父组件,基础类型的值报错;引用类型的值父组件也改变
参考链接: