关于vue中$nextTick的一点使用心得
当下公司在做一个媒体门户网站,后台由另一家公司使用java开发并提供接口,本人负责开发后台页面,使用的是vue-element-admin开发
下面说一下问题场景,在开发过程中有一个后台管理员角色页面,其中包含一个表单dialog,在其中使用了el-tree组件,相关 代码结构如下:
<div class="filter-container">
<el-button class="filter-item" style="margin-left: 10px;" v-waves @click="handleCreate" type="primary" icon="el-icon-edit">新增角色
</el-button>
</div>
<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible" width="50%">
<el-form :rules="rules" ref="dataForm" :model="temp" label-position="top" label-width="90px"
style='width: 400px; margin-left:50px;'>
<el-form-item label="选择权限" prop="sysPermission">
<el-tree ref="tree" :data="sysPermission" :props="formProps" show-checkbox
@check-change="handleCheckChange" node-key="id"></el-tree>
</el-form-item>
</el-form>
</el-dialog>
相关的js如下:
export default {
name: 'sysRoleList',
data() {
return {
tableKey: 0,
list: null,
total: null,
listLoading: true,
formLoading: true,
listQuery: {
page: 1,
limit: 20,
importance: undefined,
title: undefined,
type: undefined,
sort: '+id'
},
dialogFormVisible: false,
dialogStatus: 'update',
textMap: {
update: '编辑角色',
create: '新增角色'
},
rules: {
sysRoleName: [{required: true, message: '必须填写角色名称', trigger: 'blur'}]
},
// 表单数据
temp: {
id: '',
sysPermissionList: [],
sysRoleName: ''
},
currentKeys: [],
// 表单权限字段映射
formProps: {
label: 'sysPermissionName'
},
sysPermission: {}
}
},
created() {
// 列表数据
// this.getList()
// 获取所有权限
// this.findAllSysPermission()
},
methods: {
/*
* todo:checkbox状态变更监听
* */
handleCheckChange(data, checked, indeterminate) {
const idObj = {id: data.id}
this.temp.sysPermissionList.push(idObj)
},
resetTemp() {
this.temp = {
id: '',
sysRoleName: '',
sysPermissionList: []
}
},
handleCreate() {
this.resetTemp()
this.dialogStatus = 'create'
this.currentKeys = []
this.dialogFormVisible = true
this.$nextTick(() => {
this.$refs['dataForm'].clearValidate()
this.$refs.tree.setCheckedKeys(this.currentKeys)
})
},
handleUpdate(row) {
this.resetTemp()
this.dialogStatus = 'update'
this.dialogFormVisible = true
this.temp = Object.assign({}, row) // copy obj
this.currentKeys = []
row.sysPermissionList.forEach((value, index) => {
this.currentKeys.push(value[0])
})
this.$nextTick(() => {
this.$refs['dataForm'].clearValidate()
this.$refs.tree.setCheckedKeys(this.currentKeys)
})
}
}
}
需求:
需要在每次编辑数据的时候触发<el-tree>的方法setCheckedKeys
问题:
之前没有把this.$refs.tree.setCheckedKeys()写在this.$nextTick的callback之中,因此会提示:
TypeError: Cannot read property 'setCheckedKeys' of undefined
解决方法:
把dialog组件内的其他需要执行方法的组件方法写到this.$nextTick的callback之中
原因如下(官方):
可能你还没有注意到,Vue 异步执行 DOM 更新。只要观察到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据改变。如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作上非常重要。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。Vue 在内部尝试对异步队列使用原生的 Promise.then 和 MessageChannel,如果执行环境不支持,会采用 setTimeout(fn, 0) 代替。
例如,当你设置 vm.someData = ‘new value’ ,该组件不会立即重新渲染。当刷新队列时,组件会在事件循环队列清空时的下一个“tick”更新。多数情况我们不需要关心这个过程,但是如果你想在 DOM 状态更新后做点什么,这就可能会有些棘手。虽然 Vue.js 通常鼓励开发人员沿着“数据驱动”的方式思考,避免直接接触 DOM,但是有时我们确实要这么做。为了在数据变化之后等待 Vue 完成更新 DOM ,可以在数据变化之后立即使用 Vue.nextTick(callback) 。这样回调函数在 DOM 更新完成后就会调用。
深入响应式原理
个人理解:
vue这么做是因为频繁的更新dom是特别耗费性能的,所以搞了一个批处理更新,把所有的update操作放到任务队列中,等主线程中执行栈的所有同步任务执行完毕,系统就会读取任务队列
一个比较典型的场景,created回调里是无法直接通过this.$refs获取到用ref命名的子组件的,只有通过$nextTick才能访问到。还有比如dialog里有一个步骤条组件,在每次打开对话框都想触发步骤1的动作。如果直接写step=0;step=1;是不会有变化的,因为整个函数执行完之前DOM都不会刷新。把step=1放到$nextTick里就可以了
- 海外服务器访问变慢如何解决?在线等,急…
- 19条运营线路,北京地铁如何进行智能化运维?
- 未来二十年,产业变革的核心是什么?
- 大数据助你购买航空延误险,飞机延误未必是坏事!
- 作为一个有追求的程序员,你应该掌握的七种武器
- 腾讯云直播答题方案解析
- C+虚函数实现多态性的思考
- Zzreal的大数据笔记-SparkDay04
- 180数字集团品牌升级 启用域名180.ai
- iDC预测全球物联网花费在2018年至7720亿美金
- 北京青年报:用数据说话应是网络强国标配
- 3字母域名谁不爱?游戏门户启用价值六位数的域名
- 中国版Space X首台“民营火箭”发动机试车成功;贾跃亭甘薇在美欢度圣诞,证监局喊破嗓子他也不回家;谷歌AI新技能
- 我的写作工具链
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Android build文件的删除的方法
- Android自定义Notification添加点击事件
- 深入理解Android Bitmap
- Android基于AlarmManager实现用户在线心跳功能示例
- 详解Android中获取软键盘状态和软键盘高度
- Android流式布局FlowLayout详解
- Linux 专题
- Go语言实现UDP通信
- Android多渠道打包的方法步骤
- Android编程实现压缩图片并加载显示的方法
- Android串口通信封装之OkUSB的示例代码
- Android 中Activity 之间传递参数
- Android开发简单实现摇动动画的方法
- Android 中menu同时显示图标和文字的实现
- android基于SwipeRefreshLayout实现类QQ的侧滑删除