父组件向子组件传值
-
流程:父组件向子组件传递数据,首先要在父组件中使用
v-bind
命令将要传递的数据绑定到子组件上,在子组件中的props属性接收父组件传递过来的数据 -
测试选题
- 测试传基本类型
- 测试传对象类型
- 测试传数组类型
-
目的:测试父组件传递不同类型数据给子组件,观察子组件是否可以动态渲染
测试一 传基本类型
- 由父组件由字符串改数值加字符串,观察能否动态渲染
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>Document</title>
<style>
#father {
display: flex;
justify-items: center;
flex-direction: column;
}
.button {
width: 100px;
}
</style>
</head>
<body>
<div id="father">
<son-component :message="fatherMessage"></son-component>
<button class="button" @click="handleButtonClick"> 字符串数值类型混合传值 </button>
</div>
<script>
Vue.component("son-component", {
template: `<div id="son" ><p>{{this.message}}</p></div>`,
props: ["message"]
})
new Vue({
el: '#father',
data() {
return {
fatherMessage: 'Hello son!'
}
},
methods: {
handleButtonClick() {
this.fatherMessage = "字符串数值混合传值" + 1820299979 + "@qq.com"
}
}
})
</script>
</body>
</html>
测试二 传对象类型
-
父组件新增加一个key **结论:**子组件可以成功动态渲染
-
父组件修改一个key的value **结论:**子组件可以成功动态渲染
-
父组件修改变对象的引用 **结论:**子组件可以成功动态渲染
-
父组件key:null改成有值 **结论:**子组件可以成功动态渲染
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>Document</title>
<style>
#father {
display: flex;
justify-items: center;
flex-direction: column;
}
.button {
width: 200px;
}
</style>
</head>
<body>
<div id="father">
<son-component :message="fatherMessage"></son-component>
<button class="button" @click="handleButtonAddClick"> 新增一个对象</button>
<button class="button" @click="handleButtonChangeClick"> 改变对象value值</button>
<button class="button" @click="handleButtonChangeYinYongClick"> 改变对象的引用</button>
<button class="button" @click="handleButtonChangeEmptyClick"> 由空对象变成有值</button>
</div>
<script>
Vue.component("son-component", {
template: `<div id="son" ><p>{{this.message}}</p></div>`,
props: {
message: {
}
}
})
new Vue({
el: '#father',
data() {
return {
fatherMessage: {
city: "杭州",
test: null
}
}
},
methods: {
handleButtonAddClick() {
this.fatherMessage.block = "西湖区"
},
handleButtonChangeClick() {
this.fatherMessage.city = "哈尔滨"
},
handleButtonChangeYinYongClick() {
this.fatherMessage = {
movie: "流浪地球",
}
},
handleButtonChangeEmptyClick() {
this.fatherMessage.test = "征服未知,勇做先躯"
}
}
})
</script>
</body>
</html>
测试三 传数组类型
-
父组件新增加一个元素 **结论:**子组件可以成功动态渲染
-
父组件修改一个元素 **结论:**子组件可以成功动态渲染
-
父组件用splice方法删除数值 **结论:**子组件可以成功动态渲染
-
父组件由slice方法切割数值 结论:子组件不能完成动态渲染
-
父组件改变数组的引用 **结论:**子组件可以成功动态渲染
-
说明
Slice方法并不会修改数组,而是返回一个子数组。
解决方案:把返回的子数组赋值给数组
this.fatherMessage = this.fatherMessage.slice(4, 8)
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>Document</title>
<style>
#father {
display: flex;
justify-items: center;
flex-direction: column;
}
.button {
width: 200px;
}
</style>
</head>
<body>
<div id="father">
<son-component :message="fatherMessage"></son-component>
<button class="button" @click="handleButtonAddClick"> 新增一个数值</button>
<button class="button" @click="handleButtonChangeClick"> 改变一个数值</button>
<button class="button" @click="handleButtonSpliceClick"> 用splice方法切数值</button>
<button class="button" @click="handleButtonSliceClick"> 用slice方法切数值</button>
<button class="button" @click="handleButtonChangeEmptyClick"> 改变数组的引用</button>
</div>
<script>
Vue.component("son-component", {
template: `<div id="son" ><p>{{this.message}}</p></div>`,
props: {
message: {
}
}
})
new Vue({
el: '#father',
data() {
return {
fatherMessage: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
}
},
methods: {
handleButtonAddClick() {
this.fatherMessage.push(2333)
},
handleButtonChangeClick() {
this.fatherMessage[2] = 333
},
handleButtonSpliceClick() {
this.fatherMessage.splice(5, 1)
},
handleButtonSliceClick() {
this.fatherMessage.slice(6, 8)
},
handleButtonChangeEmptyClick() {
this.fatherMessage = [9, 8, 7, 6, 5, 4, 3, 2, 1]
}
}
})
</script>
</body>
</html>
二.子向父传值
-
测试选题
- 子组件通过$emit()向父组件传值
- 子组件通过父组件传来的prop(基本类型)传值
- 子组件通过父组件向子组件传递函数,子组件修改参数传值
- 通过总线方式传值
- 通过父组件prop传来的对象,子组件修改对象value传值
-
**目的:验证 子向父传值共有几种方式 **
测试一 通过$emit()传值
- 结论:子可以将值传给父组件,并且可以完成动态渲染
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>Document</title>
<style>
#father {
display: flex;
justify-items: center;
flex-direction: column;
}
.button {
width: 200px;
}
</style>
</head>
<body>
<div id="father">
{{this.fatherMessage}}
<son-component @thorwfather="thorwfather">
</son-component>
</div>
<script>
Vue.component("son-component", {
template: `<button class="button" @click="handleClick"> 子组件传值(1)</button>`,
props: {
message: {
}
},
data() {
return {
sonMessage: "子组件传来的值"
}
},
methods: {
handleClick() {
this.$emit("thorwfather", this.sonMessage)
}
}
})
new Vue({
el: '#father',
data() {
return {
fatherMessage: "父组件的初值"
}
},
methods: {
thorwfather(data) {
this.fatherMessage = data
}
}
})
</script>
</body>
</html>
测试二 修改父组件传来的prop
-
结论:无法传值并且无法动态渲染
-
原因:所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。
-
报错信息:Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop’s value. Prop being mutated: "message"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>Document</title>
<style>
#father {
display: flex;
justify-items: center;
flex-direction: column;
}
.button {
width: 200px;
}
</style>
</head>
<body>
<div id="father">
<son-component :message="fatherMessage"></son-component>
{{fatherMessage}}
</div>
<script>
Vue.component("son-component", {
template: `<div id="son" ><button class="button" @click="handleButtonChangeClick"> 修改父组件传来的props值</button> </div>`,
props: {
message: {
}
},
methods: {
handleButtonChangeClick() {
this.message = "子组件改变的值"
}
}
})
new Vue({
el: '#father',
data() {
return {
fatherMessage: "父组件传来的值"
}
},
methods: {}
})
</script>
</body>
</html>
测试三 通过父组件传来函数并传参完成传值
-
结论:父组件可以接收到值并且可以动态渲染
-
备注:prop不止可以传递data里面的数据,mathods里面的方法也可以传递
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>Document</title>
<style>
#father {
display: flex;
justify-items: center;
flex-direction: column;
}
.button {
width: 200px;
}
</style>
</head>
<body>
<div id="father">
{{reversedMessage}}
<son-component :message="fatherFunction"></son-component>
</div>
<script>
Vue.component("son-component", {
template: `<div id="son" ><button class="button" @click="handleButtonChangeClick"> 修改父组件传来的props值</button> </div>`,
props: {
message: {
type: Function,
}
},
data() {
return {
son: "子组件传来的值"
}
},
methods: {
handleButtonChangeClick() {
this.message(this.son)
}
}
})
new Vue({
el: '#father',
data() {
return {
fatherMessage: "父组件的值",
}
},
computed: {
reversedMessage() {
return this.fatherMessage
}
},
methods: {
fatherFunction(data) {
this.fatherMessage = data
}
}
})
</script>
</body>
</html>
测试四 总线的方式传值
- 结论:可以完成传值并动态渲染
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>Document</title>
<style>
#father {
display: flex;
justify-items: center;
flex-direction: column;
}
.button {
width: 200px;
}
</style>
</head>
<body>
<div id="father">
{{fatherMessage}}
<son-component></son-component>
</div>
<script>
var eventBus = new Vue()
Vue.component("son-component", {
template: `<div id="son" ><button class="button" @click="handleButtonChangeClick"> 修改父组件传来的props值</button> </div>`,
data() {
return {
son: "子组件传来的值"
}
},
methods: {
handleButtonChangeClick() {
eventBus.$emit("zongxian", this.son)
}
}
})
new Vue({
el: '#father',
data() {
return {
fatherMessage: "父组件的值",
}
},
created() {
eventBus.$on("zongxian", (data) => {
this.fatherMessage = data
})
}
})
</script>
</body>
</html>
测试五 通过父组件传来的对象进行传值
- 结论:可以传值并动态渲染
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>Document</title>
<style>
#father {
display: flex;
justify-items: center;
flex-direction: column;
}
.button {
width: 200px;
}
</style>
</head>
<body>
<div id="father">
<son-component :message="fatherMessage"></son-component>
{{fatherMessage}}
</div>
<script>
Vue.component("son-component", {
template: `<div id="son" ><button class="button" @click="handleButtonChangeClick"> 修改父组件传来的props值</button> </div>`,
props: {
message: {}
},
methods: {
handleButtonChangeClick() {
this.message.city = "北京"
}
}
})
new Vue({
el: '#father',
data() {
return {
fatherMessage: {
city: "杭州"
}
}
},
methods: {}
})
</script>
</body>
</html>