vue面试题十一:关于Vue.$set()、Vue中data选项中的值做为参数传递、Vue.nextTick()、v-if与v-show的总结

关于Vue.$set 、Vue中data选项中的值做为参数传递、Vue.$nextTick、v-if与v-show的总结

一 Vue.$nextTick() 的背景及用法

JS 运行机制(事件循环)

JS执行是单线程的,它是基于事件循环的。
1.所有同步任务都在主线程上执行,形成一个执行栈。
2.主线程之外,会存在一个任务队列,只要异步任务有了结果,就在任务队列中放置一个事件。
3.当执行栈中的所有同步任务执行完后,就会读取任务队列中的任务。任务队列中对应的异步任务,会结束等待状态,进入执行栈。
主线程不断重复第三步。(每执行完第三步渲染一次页面,然后接着执行第三步)

主线程从 " 任务队列 " 中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为 E v e n t L o o p (事件循环)。 主线程从"任务队列"中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。 主线程从"任务队列"中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为EventLoop(事件循环)。

也就是说,某些操作(点击按钮,ajax请求)执行后,会使他们相应的操作(代码)进入任务队列中,当主线程执行完毕,会获取任务队列中执行完的结果,渲染页面,然后再获取结果吗,再渲染页面(循环)。
在这里插入图片描述

Vue.nextTick 官网介绍
在下次DOM更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的DOM。

Vue DOM更新是异步执行的(每从任务队列中取一次数据,才渲染一次页面),即在任务队列的代码中修改,获取Dom数据时是获取不到的,因为视图不会立即更新。所以设置了 Vue.nextTick(),目的就是等同一数据循环中的所有数据变化完成之后,再统一进行视图更新。

demo

 //如果有一个 隐藏的input 框 :v-show=‘false’,你把他显示出来并且让他获取焦点
 // 反例
 show(){
  this.show = true     //修改 v-show
  document.getElementById("input").focus()  //在第一个 tick 里,获取不到输入框,自然也获取不到焦点
} 
 
 // 正例
 show(){
  this.show = true     //修改 v-show
  this.$nextTick( ()=>  document.getElementById("input").focus()) // Vue会在dom变化完执行这个操作,所以可以
}
 // 获取元素宽度
 <div id="app">
    <div ref="myW" v-if="show">{{ message }}</div>
    <button @click="getMyW">获取div元素宽度</button>
</div>
getMyW() {
    this.show = true;
    //this.message = this.$refs.myW.offsetWidth;
    //报错 TypeError: this.$refs.myW is undefined
    this.$nextTick(()=>{
        //dom元素更新后执行,此时能拿到p元素的属性
        this.message = this.$refs.myW.offsetWidth;
  })
}

二 Vue.$set的背景及用法

vue 双向绑定的原理:
Vue 会在初始化实例时对属性执行 getter/setter 转化过程,所以属性必须在 data 对象上存在才能让 Vue 转换它,这样才能让它是响应的。

在这里插入图片描述

受现代 JavaScript 的限制 (而且 Object.observe 也已经被废弃),Vue 不能检测到对象属性的添加或删除。 这个时候可以用this.$set(),给新添加的对象属性,或数组元素添加getter,setter方法

简单说即是:当你发现你给对象加了一个属性,在控制台能打印出来,但是却没有更新到视图上时,也许这个时候就需要用到this.$set()这个方法了

demo

<template>
  <div class="home">
    <div>{{student}}</div>
    <div v-for="(item,index) in items" :key="index">{{item}}</div>
	<button @click="btn()">修改</button>
  </div>
</template>

<script>
import Vue from 'vue' // 别忘了引入
export default {
  name: 'Home',
  data(){
    return{
      student:{
        name:'张三',
      },
	  items:[1, 2, 3],
    }
  },
  methods:{
	btn(){
      Vue.set(this.student, 'age', 18);
      Vue.set(this.items, 1, 'two');
	  console.log(this.student,this.items);
	}
  }
}
</script>

在这里插入图片描述

三 Vue中data选项中的值做为参数传递

把data中的某个对象赋值给一个变量,修改这个变量,把data中的对象也会被一同修改。即这个赋值是引用了地址。

demo

<script>
    export default {
        data () {
            return {
                userLists: [
                    {
                        id: 1,
                        name: '张三'
                    }
                ]
            }
        },
        methods: {
            test () {
                // 这里直接赋值给对象
                let tmpArr = this.userLists
                // 因为是地址引用,所以这个时候data中userLists的id也会变
                tmpArr.id = 2
                
                
                // 正确的赋值方式
                 let tmpArr = JSON.parse(JSON.stringify(this.userLists))
                 // 对象深拷贝,这个时候,二者不会相互影响
                  tmpArr.id = 2
            }
        }
        
    }
</script>

四 v-if与v-show

相同点:v-if与v-show都可以动态控制dom元素显示隐藏
不同点:v-if显示隐藏是将dom元素整个添加或删除,而v-show隐藏则是为该元素添加css–display:none,dom元素还在。

v-if与v-show使用对比:
1.手段:v-if是动态的向DOM树内添加或者删除DOM元素;v-show是通过设置DOM元素的display样式属性控制显隐;
2.编译过程:v-if切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件;v-show只是简单的基于css切换;
3.编译条件:v-if是惰性的,如果初始条件为假,则什么也不做;只有在条件第一次变为真时才开始局部编译(编译被缓存?编译被缓存后,然后再切换的时候进行局部卸载); v-show是在任何条件下(首次条件是否为真)都被编译,然后被缓存,而且DOM元素保留;
4.性能消耗:v-if有更高的切换消耗;v-show有更高的初始渲染消耗;
5.使用场景:v-if适合运营条件不大可能改变;v-show适合频繁切换。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值