上节回顾
上一节学习了父组件与子组件之间的简单通讯,回想一下大致如下:
- 父传子 ->
props
- 子传父 ->
$emit
但是也存在一些遗留问题,比如:我想在父组件中点击行事件修改弹出框的显示隐藏
其实上一节已经实现了效果,只是同时也得到了一大串的大红字~满山红真的让人很脸红的说啊...
本节目标
今天不上班,有一整天的自由时间,时间真的是一个很珍贵的东西呀,所以但凡是与时间有关的产物都会很有价值!
回到正题吧,今天可以慢慢的想一下如何来完成上一次没有完成的功能。
子组件修改父组件
Step 1. 直接修改props
SeaConch:先说好啊,这样做不对
旁白:不对你为什么还要写呢!?
SeaConch:因为我就是这样过来的啊...
既然父组件可以通过子组件定义的props
属性传递对象
,那为什么不直接修改它来实现修改父组件呢?
SeaConch:好像很有道理的样子!来试试~
不皮啦,好好记录!
父组件代码稍多,最后在贴完整的吧。
student-list (父
)组件关键代码:
html:
<student-list-info
...
:visible="this.display"
>
</student-list-info>
javascript:
data () {
return {
...
display: false
}
},
student-list-info (子
)组件完整代码:
<template>
<div>
<el-button icon="el-icon-more" @click="changeDisplay(true)" circle></el-button>
<el-dialog title="查询" :visible.sync="this.visible">
<el-form :model="student">
<el-form-item label="姓名">
<el-input v-model="student.name"></el-input>
</el-form-item>
<el-form-item label="性别">
<el-input v-model="student.sex"></el-input>
</el-form-item>
<el-form-item label="年龄">
<el-input v-model.number="student.age" type="number"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="changeDisplay(false)">取 消</el-button>
<el-button type="primary" @click="doConfirm(student)">确 定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
name: 'student-list-info',
props: [
'student',
'visible'/* 新增 */
],
methods: {
// 确认按钮
doConfirm (student) {
this.$emit('confirm', student)
this.changeDisplay(false)
},
// 修改显示状态
changeDisplay (value) {
this.visible = value
}
}
}
</script>
<style scoped>
</style>
npm run dev
诶~居然可以用~
控制台:我笑了
打开控制台才发现,原来一切都是假的!看到那广阔的红色疆土了吗?那是朕为你打下的江山!
其实错误是在说vue
并不推荐
这样修改prop
的值,并且我们应该避免这样做
,以免在父组件发生改变时获得一个惊喜
好吧好吧,你说的有理,并且成功的说服了我,我改。
Step 2. 通过$emit间接修改
既然不能再子组件中修改,那就转移到父组件中修改吧。
关键字当然是$emit
啦。
1.修改子组件
子组件只修改一个地方就可以啦
// 修改显示状态
changeDisplay (value) {
// this.visible = value
this.$emit('switch', value)
}
2.修改父组件
父组件需要给子组件@
一个switch
事件供其触发
html:
<student-list-info
...
:visible="this.display"
@switch="onSwitch"
>
</student-list-info>
javascript:
// 切换显示状态
onSwitch (value) {
this.display = value
}
好啦,run
再次查看效果,这次没有错误了
不过这样看来的话,关于组件之间的值传递有些麻烦...
经查阅,vuex
好像可以很好的解决这个问题,但渐进式的vue
允许我们暂时不用他,你会知道什么时候该使用vuex的
,逼格满满~
不过似乎Step 2.
也是可以优化的,再来个Step 3.
吧
Step 3. 使用.sync触发式更新prop
.sync
实际是一种简单化的方法,我们来应用一下吧。
1.父组件不再需要Step 2.
中新增的switch
事件了:
<student-list-info
style="float: left"
@confirm="onConfirm"
:student="this.student"
:visible.sync="display"
>
</student-list-info>
注意::visible.sync="display"
这里display
没有带this.
并且也不可以带this.
带上会报错,错误看不太明白,不过既然带上this.
会出错,那可能和更新事件的作用域有关系吧。
2.子组件中只需要修改一下changeDisplay函数
:
// 修改显示状态
changeDisplay (value) {
// this.visible = value
// this.$emit('switch', value)
this.$emit('update:visible', value)
}
run
一下
结果是成功的。
点击弹出框的X
好像报错,我去看一下。
改好了,把他原本的关闭事件屏蔽掉啦。
父组件完整代码:
<template>
<div>
<el-row>
<student-list-info
style="float: left"
@confirm="onConfirm"
:student="this.student"
:visible.sync="display"
>
</student-list-info>
</el-row>
<hr>
<h3>学员列表</h3>
<el-table
:data="tableData"
@row-click="onRowClick"
border
stripe
style="width: 100%">
<el-table-column
prop="name"
label="姓名"
width="180">
</el-table-column>
<el-table-column
prop="sex"
label="性别"
width="180">
</el-table-column>
<el-table-column
prop="age"
label="年龄">
</el-table-column>
</el-table>
</div>
</template>
<script>
import studentListInfo from './student-list-info'
export default {
name: 'student-list',
// 组件
components: {
studentListInfo
},
data () {
return {
tableData: [{
name: '张楚岚',
sex: '男',
age: '23'
},
{
name: '冯宝宝',
sex: '女',
age: '99'
},
{
name: '赵方旭',
sex: '男',
age: '59'
},
{
name: '肖自在',
sex: '男',
age: '36'
}
],
student: {
name: '',
sex: '',
age: 0
},
display: false /* 新增 */
}
},
// 方法集
methods: {
// 确认事件
onConfirm (item) {
this.tableData.push(item)
},
// 点击行事件
onRowClick (row) {
this.display = true
this.student = {
name: row.name,
sex: row.sex,
age: row.age
}
}
}
}
</script>
<style scoped>
</style>
子组件完整代码:
<template>
<div>
<el-button icon="el-icon-more" @click="changeDisplay(true)" circle></el-button>
<el-dialog title="查询" :visible="visible" @close='onClosed'>
<el-form :model="student">
<el-form-item label="姓名">
<el-input v-model="student.name"></el-input>
</el-form-item>
<el-form-item label="性别">
<el-input v-model="student.sex"></el-input>
</el-form-item>
<el-form-item label="年龄">
<el-input v-model.number="student.age" type="number"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="changeDisplay(false)">取 消</el-button>
<el-button type="primary" @click="doConfirm(student)">确 定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
name: 'student-list-info',
props: [
'student',
'visible'/* 新增 */
],
methods: {
// 确认按钮
doConfirm (student) {
this.$emit('confirm', student)
this.changeDisplay(false)
},
// 修改显示状态
changeDisplay (value) {
this.$emit('update:visible', value)
},
// 对话框关闭事件
onClosed () {
this.$emit('update:visible', false)
}
}
}
</script>
<style scoped>
</style>
效果图
现在可以点击行,弹出对话框查看啦~
小节
本节主要是记录了我想要从子组件修改父组件的属性的一个过程,这里也首次出现了vuex
,闲下来的时候去看一下怎么使用吧,下回见~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。