this.$nextTick在数据回显的应用

369 阅读2分钟
让你明明白白学知识,有代码,有讲解,抄的走,学的会!

我们在开发数据回显的时候,有一些场景需要使用到 $nextTick 否则,数据回显不上,显示错误

场景描述: 我有一个文章编辑界面, 从接口获取到了数据,有一个日期,目前赋值不上

UI库: viewui 版本 "view-design": "^4.3.2"

这里和UI库的版本无关,只是说,我下面的语法是基于新的view ui 去写的, 如果和3.x 版本有差异,请切换为 3.x写法,版本不是这里的重点

上代码

<template>
  <div>
    <Form :model='formModel' ref='form'>
      <h3>假设这是文档的编辑界面,需要数据回显</h3>
      <FormItem label='文章标题'>
        <Input v-model='formModel.title' />
      </FormItem>
      <FormItem>
        <RadioGroup v-model='timeType'>
          <Radio :label='1'>长期</Radio>
          <Radio :label='2'>有效期</Radio>
        </RadioGroup>
        
        <DatePicker 
          v-show='timeType === 2'
          v-model='formModel.time' 
          @on-change='formModel.time = $event'
        >
        </DatePicker>
      </FormItem>
      <FormItem>
        <Button @click='submit'>提交</Button>
      </FormItem>
    </Form>
  </div>
</template>

<script>
export default {
  name: 'useNextTick',
  data () {
    return {
      formModel: {
        title: '',
        time: '2099-12-12'
      },
      timeType: 1
    }
  },
  watch: {
    timeType(val) {
      this.formModel.time = val === 1 ? 
      '2099-12-12': new Date().toJSON().substring(0,10)
    }
  },
  mounted () {
    this.init()
  },
  methods: {
    init () {
      // 这里从服务端获取数据, 实际项目中应该是 axios.get('/api/xxx').then({data} => { ....})
      
      let data = {
        title: '今天的瓜好香',
        time: '2020-09-12'
      }

      if(data.time === '2099-12-12') {
        this.timeType = 1
      } else {
        this.timeType = 2
      }

      this.formModel = data
    },
    submit() {
      console.log(this.formModel)
    }
  }
}
</script>

如果是新建文章, 日期默认是长期, 如果是编辑文章,数据回显,可能是其他日期

我这里做了 watch 监控了 timeType, 点击 radio 按钮,就会重置掉接口数据,产品经理也是要这个效果, 现在就是日期数据回显不上

目前是有问题的图.png, 今天的日期是 2020-12-23

出现这个问题,就是这个 watch 导致的,现在你又想用 watch 去做这个事情,因为你不想使用 RadioGroup 的 on-change 写方法, 好吧,我这里就是强制要你用 watch ,然后出现这个bug, 解决一下

因为我们在拿到接口数据的时候,更新了 timeType, 就会触发watch 的重置 formModel.time

watch 里面有对 formModel.time进行更新

this.formModel = data 也对time进行了更新

vue 内部会计算去掉重复更新操作

这个时候 nextTick 就上场了

init () {
      // 这里从服务端获取数据, 实际项目中应该是 axios.get('/api/xxx').then({data} => { ....})
      let data = {
        title: '今天的瓜好香',
        time: '2020-09-12'
      }

      // 这里必定会触发 watch 导致日期重置为当天
      if(data.time === '2099-12-12') {
        this.timeType = 1
      } else {
        this.timeType = 2
      }
      
      // 在下一次事件循环中再去更新数据,此时 timeType 已经是2,我们单纯的就更新了formModel.time的值
      this.$nextTick(() => {
        this.formModel = data
      })
      
      // 你使用setTimeout 也是ok的
      // setTimeout(() => {
      //	 this.formModel = data
      // }, 0)
    },

正确的效果.png

这个GIF说明只是单纯的说明,我们在刷新页面的时候,我们的日期如约按照接口中的数据进行了展示

我并不会说我这个 watch 用的又多么的精巧,只是在我们遇到问题时, 如果你能想到 备胎 $nextTick 那就能解决你的问题; 当前,其他的方式也可以解决, 比如我们在切换Radio的时候使用方法@on-change ='dosomething' 去操作,就完全没有这个问题

开发的方式多种多样,不局限,不死板

明天就是 1024 了, 过一个没有bug的周末,真好 🎉🎉🎉