本文版权归 “公众号 | 前端一万小时” 所有,欢迎转载!
转载请注明出处,未经同意,不可修改文章内容。
🔥🔥🔥本系列文章已在“公众号 | 前端一万小时”更新完毕,有需要的小伙伴可按需前往查看。
🔥🔥🔥“前端一万小时”两大明星专栏——“从零基础到轻松就业”、“前端面试刷题”,已于本月大改版,合二为一,干货满满,欢迎点击公众号菜单栏各模块了解。
涉及面试题:
1. Vue 父组件向子组件传递数据?
2. 子组件像父组件传递事件?
3. 跨组件双向数据绑定?
4. 什么是可接受的 prop 类型?
5. props 后面的数据流是什么?
6. 什么是非 prop 属性?
7. props 有哪些可用的验证?
[编号:vue_15]
1 父组件向子组件传值
💡父组件向子组件传值:通过“属性”传值!
<body>
<div id="root">
<counter :count="0"></counter> <!-- 3️⃣父组件通过“属性”绑定“数据” count,
将 count 传递出去; -->
<counter :count="1"></counter>
</div>
<script>
var counter = {
props: ["count"], // 4️⃣在子组件中,通过 props “接收”父组件传递过来的 count 值;
template: "<div>{{count}}</div>" // 1️⃣首先,我们在这里定义一个子组件,并添加一个“模板”;
// 5️⃣接着,子组件就可以使用这个“接收”到的“数据”。
}
var vm = new Vue({
el: "#root",
components: { // 2️⃣然后,将1️⃣中的子组件添加到 components 中;
counter: counter
}
})
</script>
</body>
❓需求:实现“点击”后计数器累加功能。
❌尝试: 子组件中直接实现计数器的累加数据的功能,页面虽然实现了,但后台会报错:
var counter = {
props: ["count"],
template: '<div @click="handleClick">{{count}}</div>',
methods: {
handleClick: function() {
this.count ++ // 实现累加的功能
}
}
}
❗️报错: 不要直接修改父组件传递过来的数据。
2 Vue 单向数据流
单向数据流:
- 父组件可以向子组件通过属性形式传递参数,传递的参数也可以随时随意修改;
- 但子组件不能修改父组件传递过来的参数,只能用父组件传递的数据!
💡以上代码报错的原因:
因为子组件接收父组件传递过来的数据,并不是一个基础类型的数据类型,而是类似于 Object 这种“引用”类型的数据类型。
如果修改了“引用”类型的数据,在使用子组件时,则会造成其他子组件接收数据的错误。
🚀如何解决上边代码的问题——如何解决单向数据流存在问题?
💡分析:
子组件接收到父组件的“数据”,将接收到的“数据”复制一份放在子组件 data
的 number
里(相当于这个“数据”的副本)。
那么就能让子组件使用自己 data
里的 number
,进而在子组件的 methods
里就使用 this.number ++
来实现累加数据的功能。
<script>
var counter = {
props: ["count"],
data: function() {
return {
number: this.count // 1️⃣子组件把接收到的“数据”放在自己 data 里的 number 中;
}
},
template: '<div @click="handleClick">{{number}}</div>',
methods: {
handleClick: function() {
this.number ++ // 2️⃣接着,我们就可以在方法里使用这个副本“数据”了。将不再报错!
}
}
}
var vm = new Vue({
el: "#root",
components: {
counter: counter
}
})
</script>
3 子组件向父组件传值
💡子组件向父组件传值:通过“触发监听”模式!
- “触发”指子组件
this.$emit("事件名", 步长 step)
- “监听”指父组件
@事件名="事件执行的方法名"
❓需求:每点击一次后,两组件的总数也会随之加 2 ?
(❗️本例中我们是先把“ 总数 total
”写死的,主要为了演示“子组件向父组件传值——步长 step”。通过后边的学习,我们还可以改良本例的代码)
<body>
<div id="root">
<counter :count="0" @inc="handleIncrease"></counter>
<!-- 2️⃣我们在父组件里通过 @inc 来“监听”这个来自子组件的事件,
并把一个“方法”赋值给这个“监听”到的事件; -->
<counter :count="1" @inc="handleIncrease"></counter>
<div>总计:{{total}}</div>
</div>
<script>
var counter = {
props: ["count"],
data: function() {
return {
number: this.count
}
},
template: '<div @click="handleClick">{{number}}</div>',
methods: {
handleClick: function() {
this.number = this.number + 2;
this.$emit("inc", 2) /*
1️⃣当我们点击子组件时,不仅会执行上边的方法,
还会“触发”一个 inc 事件;且这个事件的“步长” 2,
也会一并“触发”。(即,我会告诉父组件:我自己发生了改变,
改变了多少呢?新增了 2。
*/
}
}
}
var vm = new Vue({
el: "#root",
data: {
total: 1
},
components: {
counter: counter
},
methods: {
handleIncrease: function(step) { // 3️⃣紧接着,我们在根实例里定义这个“方法”;
// 4️⃣同时,这个方法可以接收到的“步长” step 这个参数;
this.total += step // 5️⃣运用“步长”,轻松实现需求。
}
}
})
</script>
</body>
祝好,qdywxs ♥ you!