本文版权归 “公众号 | 前端一万小时” 所有,欢迎转载!
转载请注明出处,未经同意,不可修改文章内容。
🔥🔥🔥本系列文章已在“公众号 | 前端一万小时”更新完毕,有需要的小伙伴可按需前往查看。
🔥🔥🔥“前端一万小时”两大明星专栏——“从零基础到轻松就业”、“前端面试刷题”,已于本月大改版,合二为一,干货满满,欢迎点击公众号菜单栏各模块了解。
涉及面试题:
props 是什么?
[编号:vue_05]
1 父组件向子组件传值
上一篇我们封装列表组件时,让 input 框的输入内容显示在列表组件上就已经用到了“父组件向子组件传值”。
<div id="app">
<input type="text" v-model="inputValue">
<button v-on:click="handleBtnClick">添加</button>
<ul>
<todo-item v-bind:content="item"
v-for="item in list"> <!-- 2️⃣-①:使用子组件;
2️⃣-②:父组件通过 v-bind 动态绑定
content 的形式传递内容给子组件; -->
</todo-item>
</ul>
</div>
<script>
var TodoItem = {
props: ['content'], // 3️⃣子组件中以 props 接收 content;
template: '<li>{{content}}</li>' // 4️⃣在模板中使用接收到的数据。
}
var app = new Vue({ // 1️⃣父组件是 app 实例这个根组件,即整个 #app 这个 div 的内容;
el: '#app',
components: { // 2️⃣子组件是注册在根组件的 TodoItem,它在根组件里的名字也叫 TodoItem;
TodoItem: TodoItem
},
data: {
list: [],
inputValue: ''
},
methods: {
handleBtnClick() {
this.list.push(this.inputValue)
this.inputValue = ''
}
}
})
</script>
简而言之:父组件通过“属性”向子组件传值,子组件通过 props
接收属性来调用其内容。
2 子组件向父组件传值
🚀需求:当点击列表项时,删除所点击的对应内容。
也就是说,当点击子组件中的某个列表项时,父组件收到对应信息来删除对应列表项。那么完成这个需求,就涉及到“子组件向父组件传值”。
❗️注意:为了代码简洁,接下来大家已经比较熟悉的 v-bind 和 v-on 指令都将用简写!
v-on 简写为 @
,用来绑定事件监听器;v-bind 简写为 :
,用来动态绑定属性。
<div id="app">
<input type="text" v-model="inputValue">
<button @click="handleBtnClick">添加</button>
<ul>
<todo-item :content="item"
v-for="item in list"
@delete="handleItemDelete"
> <!-- 3️⃣-①:父组件在创建子组件时,通过 v-on 指令监听 delete 事件;
3️⃣-②:一旦 delete 事件被触发,父组件就执行 handleItemDelete 方法; -->
</todo-item>
</ul>
</div>
<script>
var TodoItem = {
props: ['content'],
// 1️⃣子组件的 li 标签监听 click 事件,当触发时执行 handleItemClick 方法;
template: '<li @click="handleItemClick">{{content}}</li>',
methods: { // 2️⃣-①:子组件的方法定义在子组件的 methods 中;
handleItemClick() {
this.$emit('delete') // 2️⃣-②:子组件中,通过 $emit 向外触发 delete 事件;
}
}
}
var app = new Vue({
el: '#app',
components: {
TodoItem: TodoItem
},
data: {
list: [],
inputValue: ''
},
methods: {
handleBtnClick() {
this.list.push(this.inputValue)
this.inputValue = ''
},
handleItemDelete() { // 4️⃣-①:在父组件的 methods 中定义 handleItemDelete 方法;
this.list = [] // 4️⃣-②:让 list 为空数组 []。
}
}
})
</script>
保存返回页面,刷新查看效果:我们完成了子组件向父组件传值,成功删除了列表项。但,当点击列表项时,清空了“整个”列表!
这是因为当 delete 事件触发后,父组件执行的 handleItemDelete
方法中我们让 list 为空数组。
handleItemDelete() { // 4️⃣-①:在父组件的 methods 中定义 handleItemDelete 方法;
this.list = [] // 4️⃣-②:让 list 为空数组 []。
}
而当 list 为空数组,即改变了 list 的数据,让它已有的列表项被全部清空。所以当点击某一个列表项时,我们就看到整个列表被清空。
❓如何正确删除所点击的某一项列表?
答:可以通过获取列表项的下标来完成此功能。
<div id="app">
<input type="text" v-model="inputValue">
<button @click="handleBtnClick">添加</button>
<ul>
<todo-item :content="item"
:index="index"
v-for="(item, index) in list"
@delete="handleItemDelete"
> <!-- 1️⃣当循环 list 数组时,第一项获取内容 item,
第二项获取数组的下标 index;
2️⃣动态绑定一个名为 index 的属性,当父组件向子组件传值时,
除了 content 对应的内容 item,同时再传入 index 对应的列表项下标; -->
</todo-item>
</ul>
</div>
<script>
var TodoItem = {
props: ['content', 'index'], // 3️⃣子组件要使用列表项下标,必须在 props 中接收 index 属性;
template: '<li @click="handleItemClick">{{content}}</li>',
methods: {
handleItemClick() {
this.$emit('delete', this.index) /*
4️⃣当子组件被点击时,不但触发 delete 事件,
同时把被点击列表项的下标作为参数传给父组件;
*/
}
}
}
var app = new Vue({
el: '#app',
components: {
TodoItem: TodoItem
},
data: {
list: [],
inputValue: ''
},
methods: {
handleBtnClick() {
this.list.push(this.inputValue)
this.inputValue = ''
},
handleItemDelete(index) { /*
5️⃣-①:父组件接收子组件传来的下标,
当监听到 delete 事件被触发时执行 handleItemDelete 方法;
*/
this.list.splice(index, 1) // 5️⃣-②:从传来的下标开始,删除一项。
}
}
})
</script>
现在我们完成了“当点击列表项时,删除所点击的对应内容”的需求,同时还学到了子组件向父组件传值的方式。
再简述一次此实现流程:
- 父组件通过 v-bind 指令传递下标 index 值;
- 父组件传递的值,子组件一定要在自己的
props
接收; - 子组件通过
$emit
触发delete
事件,同时传递被点击列表项的下标; - 父组件通过 v-on 监听
delete
事件,获取到子组件传递的下标并执行handleItemDelete
方法; - 最终实现当点击某项列表时,删除此项。
祝好,qdywxs ♥ you!