vue-base-2

1. 条件渲染

1、v-if

  • 写法:
    • v-if
    • v-else-if
    • v-else
  • 适用于:频率较低的场景
  • 特点:创建或移除dom节点
  • 注意:以上写法可以连用,但不能被打断,同js语法一致

2、v-show

  • 写法:v-show="表达式"
  • 适用于:频率较高的场景
  • 特点:样式隐藏,display:none

3、v-if可能无法被获取到,v-show永远可以

<div v-if="n===1">1</div> <!-- 1如果成立,后面的就都不走了 -->
<div v-else-if="n===2">2</div>
<div v-else-if="n===3">3</div>
<div v-else>other</div> <!-- 前面的都不走,就走这个了 -->

4、<templata>模板 虚拟标签 不生成实际内容

<templata v-if="n===1">
    <div>1</div>
    <div>2</div>
    <div>3</div>
</templata>
<!-- 会生成三个连续<div>标签,template标签就消失了 -->

2. 列表渲染

1、基础

1、{{}}插值内容可能来源data属性、计算属性、methods或列表行参(item)
2、v-for

  • 1、展示列表数据
  • 2、语法:
    • v-for="(item,index) in list" :key="item.id"
    • {{item.name}}
  • 3、可遍历的数据:数组、对象、字符串、指定次数
  • 4、举例
<!-- 遍历数组 -->
<li v-for="(item,index) in list" :key="item.id">{{item.name}}</li>
<!-- list=[{id:1,name:1},{id:2,name:2}] -->

<!-- 遍历对象 -->
<li v-for="(value,key) in obj" :key="key">{{value}}</li>
<!-- obj={id:1,name:1,age:1} -->
<!-- 第1个行参是value,第2个行参是key -->

<!-- 遍历字符串 -->
<li v-for="(char,index) in str" :key="index">{{value}}</li>
<!-- str="abc" -->
<!-- 第1个行参是char,第2个行参是index -->

<!-- 遍历指定次数 -->
<li v-for="(num,index) in 5" :key="index">{{num}}</li>
<!-- 第1个行参是num,第2个行参是index -->

2、面试题:react、vue中的key有什么作用?(key的内部原理)

1. 虚拟DOM中key的作用:
  • key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,
    随后Vue对新旧虚拟DOM进行差异比较,其中key是重要的比较方式,比较规则如下:
2.对比规则:
  • 旧虚拟DOM与新虚拟DOM的key相同:

    • 若虚拟DOM中内容(文本和标签)没变, 直接使用之前的真实DOM;
    • 若虚拟DOM中内容变了, 文本变了替换文本,标签变了替换标签,生成新的真实DOM,替换掉页面中之前的真实DOM。
  • 旧虚拟DOM中未找到与新虚拟DOM相同的key

    • 创建新的真实DOM,随后渲染到到页面。
3. 用index作为key可能会引发的问题:
  • 若对数据进行:逆序添加、逆序删除等破坏顺序操作:
    会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低。

  • 如果结构中还包含输入类的DOM:
    会产生错误DOM更新 ==> 界面有问题。

4. 开发中如何选择key?:
  • 1.最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值。
  • 2.如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。

3、 列表过滤和排序

对数组进行数据操作,一般不对原数据直接操作,可以拷贝一份数据
对数组进行筛选然后返回,可以通过原数组过滤赋值到新数组

1.filter不改变原数组,返回新数组
2.watch的immediate是初始化回调函数,其中的newd是初始默认值
3.任何值的indexOf,检测""都能检测到,为0
4.数组sort方法改变原数组,传参两个,升序是前-后,降序是后-前

3.vue如何加工data变成响应式数据

1、简单叙述data数据是如何处理的

- 1.加工用户传入的data(data对象)
- 2.vm._data = data
控制台发现_data的数据都是`reactiveGetter`,是vue加工过的,将用户data数据劫持
- 3._data与vm做代理,使_data代理到vm中

2、js传参中的对象
对象作为函数传参时,传递的实际是对象的内存地址,
函数里面外面指向的是同一个内存地址,改变的自然也就是同一个对象;
但当传参被重新赋值替换整个对象时,传参被赋予一个新的内存地址,切断了与之前地址的联系。
但是却并没有删除或改变原本的外面的内存地址,所以外面的对象依旧指向的是原本的地址

3、对象属性的监听和动态添加对象的属性

    //示例1
    let data = {
        name:'xx',
        age:'xx',
    }
    Object.defineProperty(data,name,{
        get(){
            return data.name
        },
        set(val){
            data.name=val
        }
    })
    //注意这样写会造成内存溢出,当读取data属性时,会调get方法,而get方法返回data.name,此时相当于又读取了data.name,又读取了get,周而复始,死循环了
    //所以原则上一般不对原数据进行直接修改,先深拷贝再处理。
    //示例2
    //用户传入的data数据   
    let data = {
        name:'xx',
        address:'xx',
    }

    //创建一个监视的实例对象,用于监视data中属性的变化
    const obs = new Observer(data)      
    console.log(obs)    

    //准备一个vm实例对象
    let vm = {}
    vm._data = data = obs 
    //将实例对象赋给data和_data,使三个变量都引用同一内存地址
    //data换了新的内存地址,而Observer中的传参却没有更新内存地址,所以访问的是原来的内存地址,强制只有通过构造函数实例才能修改最初的data传参
    //而构造函数中修改传参,实际是保留了函数创建时的变量环境,即闭包,这样读取属性不会产生死循环

    function Observer(obj){
        //汇总对象中所有的属性形成一个数组
        const keys = Object.keys(obj)
        //遍历
        keys.forEach((k)=>{
            //拷贝一份data的属性到实例对象obs上,使obs属性被读取或修改时,实际操作的都是data对象
            Object.defineProperty(this,k,{
                get(){
                    return obj[k]
                },
                set(val){
                    console.log(`${k}被改了,我要去解析模板,生成虚拟DOM.....我要开始忙了`)
                    obj[k] = val
                }
            })
        })
    }
//此处是一层遍历赋值,vue做到了无论多深的层级的对象属性,都能被监听到,做了递归遍历,修改监听所有属性
//get和set只对已经存在的data对象的属性有效,那么在后续使用中需要增加新的属性怎么实现响应式?
// 一级属性可以通过提前添加变量在this上
// 对象中的属性可以通过Vue.set(this.obj,'key',value)添加对象的响应式属性,且即时更新页面

// data=>_data=>vm
// 从data到_data的过程叫做数据劫持,从_data到vm的过程叫做数据代理。虽然底层都用到了Object.defineProperty方法。
// 在数据劫持里,vue处理数据的get和set使其变成响应式数据,set数据更新引起模板重新解析,生成虚拟dom,对比新旧虚拟dom,该更新更新该复用复用。
// 数组的更新看key,key存在,对比内容节点,一样的复用,不一样的更新;新生成的key在旧的里面不存在,直接生成新的
// 从_data到vm的过程,只是为了在页面使用时更加简洁方便。
    //添加响应式的对象属性:
    //vue对对象中新增的属性默认是不做监听的,需要调用api
    //注意obj只能是this下面的对象,不可以直接在this中添加属性。
    //以下三者等价
    Vue.set(this.student,'sex','男')
    vm.$set(this.student,'sex','男')
    this.$set(this.student,'sex','男')
    //新增对象属性经过以上方法加工后,就变成了与_data中一样的get和set,reactive函数,数据变化会引起模板重新解析
    
    //注意:get和set方法只供于对象属性使用。

4、数组监听和修改

读取一个对象不存在的属性,返回undefined
读取一个不存在的对象/变量,直接报错

// 操作数组下标,不会触发响应式
let arr=["王","李","孙"]
arr[0]="刘" //页面没有反应

// 操作数组下标的属性,不会触发响应式
let arr=[{
        age:11
    },{
        age:10
    },{
        age:15
    }]
arr[0].age=20 //页面被更新了
//arr数组都每项都是对象,而对象的属性都是被vue维护的。可以被监听到
//若操作arr[1]={age:222},不生效,因为是对数组直接操作下标

// _data里的一级属性,对象或数组被重新赋值都可以被监听到

vue如何监听数组的变化呢?
1、vue通过7个数组方法监听数组改变

  • push:添加元素至数组最后,改变数组长度
  • pop:删除数组最后一个元素,改变数组长度
  • shift:删除数组第一个元素,改变数组长度
  • unshift:添加元素至数组第一位,改变数组长度
  • splice:从起始位置删除n个、替换成..(index,n,"")
  • sort:数组排序
  • reverse:反转数组元素的顺序

以上7个方法都会改变原数组,并且引起模板重新解析
因为vue包装了以上方法,主要两个方面:
1.是沿用Array.push/pop...
2.增加了模板解析?

2、数组重新赋值:filter方法修改数组不会更新数组内容,所以不会被监听到,可以把新返回的内容重新替换给原数组
3、如用数组下标方式修改:vm.$set(this.arr, index, content)
注意:数组中的对象属性,可以被监听到,任意层级的对象属性都能被监听到

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容