在我们使用vue进行开发的过程中,可能会遇到一种情况:当生成vue实例后,当再次给数据赋值时,有时候并不会自动更新到视图上去; 当我们去看vue文档的时候,会发现有这么一句话:如果在实例创建之后添加新的属性到实例上,它不会触发视图更新。
在使用el-progress组件实现实时进度条时遇到了这个问题。基本环境是,在el-table中有很多col列,其中有一列表示各行元素的进度条。实际上就是tableData存储了所有被表格展示的信息。通过改变该tableData数组来更新表格显示信息,问题在于更新的方式,如果直接使用下标tableData[i].progress = value来更新数据的值,确实能够修改值本身,但是Vue.js并不能感知到数据的变化,以至于其渲染的进度条不会发生动态改变,值得一提的是,如果修改的是vue渲染之外的普通列数据,比如一个文本,那么是可以看到实时变化的,同时,如果修改了表格的其他值成功了,那么vue会因为更新了表格,而去检查tableData进度条有关参数的改变,进而有了使用下标也能更新渲染进度条的效果,本质其实就是:
受 ES5 的限制,Vue.js 不能检测到对象属性的添加或删除。因为 Vue.js 在初始化实例时将属性转为 getter/setter,所以属性必须在 data 对象上才能让 Vue.js 转换它,才能让它是响应的。
正确写法:this.$set(this.data,”key”,value’)
data () {
return {
student: {
name: '',
sex: ''
}
}
}
mounted () { // ——钩子函数,实例挂载之后
this.student.age = 24
}
必须用以下写法才能使vue感知到数据的变化。
mounted () {
this.$set(this.student,"age", 24)
}
Vue 不允许动态添加根级响应式属性。
const app = new Vue({
data: {
a: 1
}
// render: h => h(Suduko)
}).$mount('#app1')
Vue.set(app.data, 'b', 2)
只可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式属性,例如
var vm=new Vue({
el:'#test',
data:{
//data中已经存在info根属性
info:{
name:'小明';
}
}
});
//给info添加一个性别属性
Vue.set(vm.info,'sex','男');
参考原文链接https://juejin.im/post/6844903901175496711
至于element使用的进度条组件,我随机选了一个将进度文本值嵌入进度条的样式:
<el-progress :text-inside="true" :stroke-width="26" :percentage="70">el-progress>
<el-progress :text-inside="true" :stroke-width="24" :percentage="100" status="success">el-progress>
<el-progress :text-inside="true" :stroke-width="22" :percentage="80" status="warning">el-progress>
<el-progress :text-inside="true" :stroke-width="20" :percentage="50" status="exception">el-progress>
可以在代码中以及文档里看到各个参数的意义:
https://element.eleme.cn/#/zh-CN/component/progress
我们需要实时修改的可能就是color,根据进度程度改变进度条颜色,或是status,实际上这两个参数基本效果一致,只不过color更自由,可以选择更多颜色,而status则是懒人选择的直接根据状态修改颜色。
最重要的百分比参数是需要实时修改的,也是容器渲染需要感受更新的参数。
我们将百分比以及其他要显示的数据装入tableData,可以写一个函数向后端发出请求,获取当前时间点实时的进度比率或是其他可以表示进度的数值,比如一个函数updateProgress,然后调用setInterval(this.updateProgress, 1500)函数每隔一段时间进行一次请求,实现实时更新。该函数周期执行,第一个参数是被周期执行的函数,也就是我们的请求进度函数,第二个参数是周期实现,单位是毫秒,也就是说样例的意思是每1.5秒执行一次更新进度的请求函数。同时更新进度条百分比,注意这里的更新进度条百分比就是上面所说的更新方式,一定要用vue能感知到的方式进行更新,updateProgress函数大概长这样:
updateProgress: function() {
axios.post('/v1/progress', this.getRunningTask(this.tableData)).then( (res) => {
for(let i = 0; i < this.pageSize; i++){
if(this.tableData[i].state === 'running'){
let data = this.tableData[i]
data.progress = res.data[this.tableData[i].task_id]
if(data.progress >= 25 && data.progress < 50){
data.pro_status = "#E6A23C"
}
else if(data.progress >= 50 && data.progress < 75){
data.pro_status = "#409EFF"
}
else if(data.progress >= 75 && data.progress < 100){
data.pro_status = "#3AC2B0"
}
else if(this.tableData[i].progress === null){
data.progress = 100
data.state = "complete"
}
this.$set(this.tableData, i, data)
console.log(data.progress, res.data[this.tableData[i].task_id], data.pro_status)
}
}
})
},
该函数应该放在vue 的methods里,而周期更新的函数应该放在mounted里,在vue生命周期中表示在这段周期中开始不断请求
注意要在最后销毁清空掉该周期执行函数
beforeMount: function(){
this.initiateProgress();
},
mounted: function() {
console.log('this', this)
this.timer = setInterval(this.updateProgress, 1500)
},
beforeDestroy: function () {
clearInterval(this.timer);
},
最后放上vue官方文档作为重点,没注意时这才是最大的坑