• Vue基础5


    绑定样式

    1. class样式
      写法:class="xxx“ xxx可以是字符串、对象、数组
      字符串的写法适用于:类名不确定,要动态获取
      对象写法适用于:要绑定多个样式,个数不确定,名字也不确定
      数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用
    2. style样式
      :style="{fontSize:xxx}“其中xxx是动态
      :style=”[a,b]"其中a,b是样式对象

    绑定class样式

    DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>绑定样式title>
      <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
      <style>
        .basic{
          width: 400px;
          height: 100px;
          border: 1px solid black;
        }
        .happy{
          border: 5px solid red;
          background: linear-gradient(to top right,yellow 0%,orange 25%,pink 50%,yellow 75%,orange 100%);
        }
        .sad{
          background-color: #888;
          border: 5px greenyellow dashed;
        }
        .normal{
          background-color: skyblue;
        }
        .first{
          background-color: rgb(115, 231, 115);
        }
        .second{
          font-size: 30px;
          text-shadow: 2px 2px 5px pink;
        }
        .third{
          border-radius: 10px;
        }
      style>
    head>
    <body>
      <div id="root">
        
        <div class="basic" :class="mood" @click="changeMood">哈喽,你好{{name}}div>  <br>
    
        
        <div class="basic" :class="classArr">哈喽,你好{{name}}div>  
        <button @click="deleteClass">点击删除样式button>        
        <input type="text" v-model="added">
        <button @click="addClass">点击添加样式button>   <br><br>
        
        
        <div class="basic" :class="classObj">哈喽,你好{{name}}div>
        <button @click="chooseUse(0)">使用第一个样式,不使用第二个button>
        <button @click="chooseUse(1)">不使用第一个样式,使用第二个样式button>
        <button @click="chooseUse(2)">两个样式都使用button>
        <button @click="chooseUse(3)">两个样式都不使用button>
      div>
    body>
    <script>
      new Vue({
        el:"#root",
        data:{
          name:"张三",
          mood:"normal",
          classArr:["first","second","third"],
          classObj:{
            first:true,
            second:true
          },
          added:""
        },
        methods:{
          changeMood(){
            const arr=['normal','happy','sad']
            const r=Math.floor(Math.random()*3)     //随机数[0,n)的方法
            this.mood=arr[r]
          },
          deleteClass(){
            this.classArr.shift()
          },
          addClass(){
            this.classArr.push(this.added)
          },
          chooseUse(value){
            if(value==0){
              this.classObj.first=true
              this.classObj.second=false
            }else if(value==1){
              this.classObj.first=false
              this.classObj.second=true
            }else if(value==2){
              this.classObj.first=true
              this.classObj.second=true
            }else{
              this.classObj.first=false
              this.classObj.second=false
            }
          }
        }
      })
    script>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100

    请添加图片描述
    请添加图片描述
    请添加图片描述

    绑定style样式

    DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>绑定style样式title>
      <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
    head>
    <body>
      <div id="root">
        
        <div style="font-size: 40px;">你好啊div>
        <hr>
        
        
        <div :style="styleObj">你好,{{name}}div> <br>
        
        <div :style="styleArr">欢迎来到{{school.name}}div>
    
      div>
    body>
    <script>
      new Vue({
        el:"#root",
        data:{
          name:"张三",
          school:{
            name:"幸福中学"
          },
          styleObj:{
            fontSize: "40px",
            backgroundColor:"pink",
            color:"blue"
          },
          styleArr:[{
            fontSize: "50px",
            color:"red"
          },{
            backgroundColor:"skyblue",
            width:"500px",
            height:"150px"
          }]
        }
      })
    script>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    请添加图片描述

    条件渲染

    1. v-if 写法
      (1)v-if=“表达式”
      (2)v-else-if=“表达式”
      (3)v-else=“表达式”
      适用于:切换频率较低的场景
      特点:不展示的Dom元素直接被移除
      注意:v-if 可以和v-else-if,v-else一起使用,但要求结构不能被“打断”
    2. v-show
      写法:v-show=“表达式”
      适用于:切换频率较高的场景
      特点:不展示的dom元素未被移除,仅仅是使用样式隐藏掉
    3. 备注:使用v-if时,元素可能无法获取到,而使用v-show一定可以获取到,
      (v-if 为false时,页面上没有元素了,通过其他办法无法获取,v-show为false,页面上还有这个元素,所以可以通过其他办法获取到)
    DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>条件渲染title>
      <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
    head>
    <body>
      <div id="app">
        
        <button @click="isShow=!isShow">点击给你惊喜button>  <br>
        <h1 v-show="isShow">你好,{{name}}h1>
        
        <button @click="isIf=!isIf">点击就能展示button>   <br>
        <h1 v-if="isIf">欢迎来到{{school.name}}h1>
        <hr>
    
        
        <div>当前的n值是:{{n}}div>
        <button @click="n++">点我n+1button>
        <div v-show="n===1">Angulardiv>
        <div v-show="n===2">Reactdiv>
        <div v-show="n===3">Vuediv>
    
        
        <div>当前的d值是:{{d}}div>
        <button @click="d++">点我d+1button>
        <div v-if="d===1">Angulardiv>
        <div v-if="d===1">Reactdiv>
        <div v-if="d===2">Vuediv>
        <hr>
    
        
        <div>当前的a值是:{{a}}div>
        <button @click="a++">点我a+1button>
        <div v-if="a===1">JavaScriptdiv>
        
        <div v-else-if="a===1">Javadiv>
        <div v-else-if="a===2">Jquerydiv>
        <div v-else>哈哈哈div>
        <hr>
    
        
        <div>当前的b值是:{{b}}div>
        <button @click="b++">点我b+1button>
        <template v-if="b===1">
          <div>html,cssdiv>
          <div>JavaScriptdiv>
          <div>Dom,Bomdiv>
        template>
      div>
    body>
    <script>
      new Vue({
        el:"#app",
        data:{
          name:"张三",
          isShow:false,
          isIf:false,
          school:{
            name:"幸福中学"
          },
          n:0,
          d:0,
          a:0,
          b:0
        },
    
      })
    script>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73

    请添加图片描述
    请添加图片描述
    请添加图片描述

    列表渲染

    v-for指令

    v-for指令:

    1. 用于展示列表数据
    2. 语法:v-for=“(item,index) in xxx” :key=“yyy”
    3. 可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)
    DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>列表渲染title>
      <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
    head>
    <body>
      <div id="app">
        
        <h2>人员列表(遍历数组)h2>
        <ul>
          <li v-for="(p,index) in people" :key="p.id">
            {{index}}-{{p.name}}-{{p.age}}
          li>
        ul>
    
        
        <h2>王老师信息(遍历对象)h2>
        <ul>
          <li v-for="(value,k) of wang" :key="k">
            {{k}}-{{value}}
          li>
        ul>
        
        
        <h2>hello遍历(少用)h2>
        <ul>
          <li v-for="(s,index) of str" :key="index">
            {{index}}-{{s}}
          li>
        ul>
    
        
        <h2>数次数(少用)h2>
        <ul>
          <li v-for="(number,index) of 6" :key="index">
            索引:{{index}}-数值:{{number}}
          li>
        ul>
      div>
    body>
    <script>
      new Vue({
        el:"#app",
        data:{
          people:[
            {id:"001", name:"张三", age:"18"},
            {id:"002", name:"李四", age:"19"},
            {id:"003", name:"王五", age:"20"}
          ],
          wang:{
            name:"王立春",
            merried:"已婚",
            sex:"女"
          },
          str:"hello"
        }
      })
    script>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    请添加图片描述

    key的原理

    index作为key的时候

    DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>key的原理title>
      <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
    head>
    <body>
      <div id="app">
        <ul>
          <li v-for="(p,index) in people" :key="index">
            {{p.name}}-{{p.age}} <input type="text">
          li>
        ul>
        <button @click="add">在列表最前面添加一个老刘button>
      div>
    body>
    <script>
      new Vue({
        el:"#app",
        data:{
          people:[
            {id:"001",name:"张三",age:18},
            {id:"002",name:"李四",age:19},
            {id:"003",name:"王五",age:20}
          ]
        },
        methods:{
          add(){
            var obj={id:"004",name:"老刘",age:30}
            this.people.unshift(obj)
          }
        }
      })
    script>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    若在列表中同时存在输入框时会出现以下问题:
    请添加图片描述
    出现问题的原因是Vue在生成虚拟dom时候使用对比(diff)算法,下面是运行过程图:
    请添加图片描述

    id作为key的时候

    DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>key的原理title>
      <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
    head>
    <body>
      <div id="app">
        <ul>
          <li v-for="(p,index) in people" :key="p.id">
            {{p.name}}-{{p.age}} <input type="text">
          li>
        ul>
        <button @click="add">在列表最前面添加一个老刘button>
      div>
    body>
    <script>
      new Vue({
        el:"#app",
        data:{
          people:[
            {id:"001",name:"张三",age:18},
            {id:"002",name:"李四",age:19},
            {id:"003",name:"王五",age:20}
          ]
        },
        methods:{
          add(){
            var obj={id:"004",name:"老刘",age:30}
            this.people.unshift(obj)
          }
        }
      })
    script>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    请添加图片描述
    就能得到正确结果,其运行过程如下所示:
    请添加图片描述

    总结

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

    1. 虚拟DOM中key的作用:
      key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:
    2. 对比规则:
      (1)旧虚拟DOM中找到了与新虚拟DOM中相同的key:
      ①若虚拟DOM中内容没变,直接使用之前的真实的DOM
      ②若虚拟DOM中的内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM
      (2)旧虚拟DOM中未找到与新虚拟DOM中相同的key
      创建新的真实DOM,随后渲染到页面
    3. 用index作为key可能会引发的问题:
      (1)若对数据进行:逆序添加、逆序删除等破坏顺序操作:
      会产生没有必要的真实DOM更新 =》页面效果没问题,但效率低
      (2)如果结构中还包含输入类的DOM:
      会产生错误DOM更新==》页面有问题
    4. 开发中如何选择key?
      ①最好使用每条数据唯一标识作为key,比如id,手机号、身份证号、学号等唯一值。
      ②如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的

    列表过滤

    知识点补充:
    对列表进行过滤时候可以使用filter过滤:
    用法:
    过滤出来的数组=数组.filter(()=>{
    过滤条件
    })

    indexOf用法:
    str.indexOf(“条件值”)

    • 若符合存在条件值的值,返回条件值在数组中的位置
    • 若不符合存在条件值的值,则返回-1
    • 若为空串,返回0

    请添加图片描述

    用监视属性实现

    当immediate为true时,会在初始时候刷新一遍,则handler的val为"",对象的name值都符合条件,因此能在最初时都渲染在页面上

    DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>列表过滤title>
      <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
    head>
    <body>
      <div id="root">
        <h1>人员列表h1>
        <input type="text" v-model="keyword"> <br>
        <ul>
          <li v-for="(p,index) in filPeo" :key="p.id">
            {{p.name}}-{{p.age}}-{{p.sex}}
          li>
        ul>
      div>
    body>
    <script>
      new Vue({
        el:"#root",
        data:{
          keyword:"",
          people:[
            {id:"001",name:"马冬梅",age:19,sex:"女"},
            {id:"002",name:"周冬雨",age:20,sex:"女"},
            {id:"003",name:"周杰伦",age:21,sex:"男"},
            {id:"004",name:"温兆伦",age:22,sex:"男"}
          ],
          filPeo:[]
        },
        watch:{
          keyword:{
            immediate:true,
            handler(val){
              this.filPeo=this.people.filter((p) => {
                return p.name.indexOf(val)!=-1
              });
            }
          }
        }
      })
    script>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    请添加图片描述
    请添加图片描述

    用计算属性实现(比监视属性简单)

    不用再用另外一个数组装过滤后的东西了,直接用计算属性返回即可。
    计算属性通过keyword计算出来结果

    DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>列表过滤-计算属性title>
      <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
    head>
    <body>
      <div id="root">
        <h1>人员列表h1>
        <input type="text" v-model="keyword">
        <ul>
          <li v-for="(p,index) in filPeo" :key="p.id">
            {{p.name}}-{{p.age}}-{{p.sex}}
          li>
        ul>
      div>
    body>
    <script>
      new Vue({
        el:"#root",
        data:{
          keyword:"",
          people:[
            {id:"001",name:"马冬梅",age:19,sex:"女"},
            {id:"002",name:"周冬雨",age:20,sex:"女"},
            {id:"003",name:"周杰伦",age:21,sex:"男"},
            {id:"004",name:"温兆伦",age:22,sex:"男"}
          ]
        },
        computed:{
          filPeo(){
            return this.people.filter((p) => {
              return p.name.indexOf(this.keyword)!=-1
            })
          }
        }
      })
    script>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    请添加图片描述

    列表排序

    知识点补充:
    数组.sort((a,b)=>{
    return a-b;
    })
    升序:return a-b;
    降序:return b-a;

    DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>exampletitle>
      <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
    head>
    <body>
      <script>
        const arr=[15,30,10,8,45]
        //升序排序
        arr.sort((a,b) => {
          return a-b
        })
        console.log("arr经过升序排序之后得",arr);
        
        //降序排序
        const arr1=[15,30,10,8,45]
        arr1.sort((a,b) => {
          return b-a
        })
        console.log("arr经过降序排序之后得:",arr1);
      script>
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    请添加图片描述
    正式代码:

    DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>列表排序title>
      <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
    head>
    <body>
      <div id="root">
        <h1>人员列表h1>
        <input type="text" placeholder="输入姓名" v-model="keyword"> 
        <button @click="sortType=2">年龄升序button>
        <button @click="sortType=1">年龄降序button>
        <button @click="sortType=0">原顺序button>
        <ul>
          <li v-for="(p,index) in filPeo">
            {{p.name}}-{{p.age}}-{{p.sex}}
          li>
        ul>
      div>
    body>
    <script>
      new Vue({
        el:"#root",
        data:{
          people:[
            {id:"001",name:"马冬梅",age:35,sex:"女"},
            {id:"002",name:"周冬雨",age:20,sex:"女"},
            {id:"003",name:"周杰伦",age:25,sex:"男"},
            {id:"004",name:"温兆伦",age:15,sex:"男"}
          ],
          keyword:"",
          sortType:0
        },
        computed:{
          filPeo(){
            const arr= this.people.filter((p) => {
              return p.name.indexOf(this.keyword)!=-1
            })
            //判断一下是否需要排序
            if(this.sortType){
              //sort改变原数组
              arr.sort((a,b) => {
                return this.sortType!=1?a.age-b.age:b.age-a.age
              })
            }
            return arr 
          }
        }
      })
    script>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    请添加图片描述

    Vue检测数据改变的原理

    更新时的一个小问题

    DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>更新时的一个问题title>
      <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
    head>
    <body>
      <div id="root">
        <h1>人员列表h1>
        <button @click="updateMa">更新马冬梅的信息button>
        <button @click="updateYu">更新周冬雨的信息button>
        <ul>
          <li v-for="(p,index) in people" :key="p.id">
            {{p.name}}-{{p.age}}-{{p.sex}}
          li>
        ul>
      div>
    body>
    <script>
      const vm=new Vue({
        el:"#root",
        data:{
          people:[
            {id:"001",name:"马冬梅",age:19,sex:"女"},
            {id:"002",name:"周冬雨",age:20,sex:"女"},
            {id:"003",name:"周杰伦",age:21,sex:"男"},
            {id:"004",name:"温兆伦",age:22,sex:"男"}
          ]
        },
        methods:{
          updateMa(){
            //此种方法修改有效
            this.people[0].name="马老师"
            this.people[0].age=50
            this.people[0].sex="男"
          },
          updateYu(){
            //此种方法修改无效
            this.people[1]={id:"002",name:"周老师",age:30,sex:"男"}
          }
        }
      })
    script>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    请添加图片描述
    可以发现,第一种写法,马冬梅的信息修改后能够有效,Vue能够检测到修改,但是第二种写法,从控制台输出可以发现,内存中周冬雨的那条数据已经修改了,但是Vue没有检测到修改,所以在页面上没有反应
    请添加图片描述
    加工data 就是 数据劫持

    Vue检测对象数据原理

    DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Vue检测原理title>
      <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
    head>
    <body>
    body>
    <script>
      var data={
        name:"幸福中学",
        address:"上海"
      }
    
      //创建一个监视的实例对象,用于监视data中属性的变化
      var obs=new Observer(data)
      
      //写一个Observer的构造函数
      function Observer(obj){
        //汇总对象中所有的属性形成一个数组
        var keys=Object.keys(obj)
        console.log(keys);
        //遍历
        keys.forEach((k) => {
          //this指的是当前的实例对象
          Object.defineProperty(this,k,{
            get(){
              return obj[k]
            },
            set(val){
              console.log("${k}的值被修改了,我要去解析模板了");
              obj[k]=val
            }
          })
        })
      }
    
      //准备一个vm实例对象
      const vm={}
      vm._data=data=obs
    
    script>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    请添加图片描述

    Vue.set()方法

    Vue中的小bug:
    1. 如果是data中已有属性的属性值undefined不会显示,也不会出现bug
    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
        <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
    head>
    <body>
        <div id="app">
            <h1>学生信息h1>
            <h2>姓名:{{student.name}}h2>
            <h2>年龄:真实{{student.age.rAge}},对外{{student.age.sAge}}h2>
            
            <h2>性别:{{student.sex}}h2>
            <h2>朋友们h2>
            <ul>
                <li v-for="(f,index) in student.friends" :key="index">
                    {{f.name}}-{{f.age}}
                li>
            ul>
        div>
    body>
    <script>
        Vue.config.productionTip=false;
    
        const vm=new Vue({
            el:"#app",
            data:{
                school:{
                    name:"幸福中学",
                    address:"幸福路"
                },
                student:{
                    name:"张三",
                    age:{
                        rAge:40,
                        sAge:30
                    },
                    // sex:"男",
                    friends:[
                        {name:"李四",age:20},
                        {name:"王五",age:25},
                    ]
                }
            }
        })
    script>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    在这里插入图片描述

    1. 如果是data的属性不存在就会出现问题
    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
        <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
    head>
    <body>
    <div id="app">
        <h1>学生信息h1>
        <h2>姓名:{{student.name}}h2>
        <h2>年龄:真实{{student.age.rAge}},对外{{student.age.sAge}}h2>
        <h2>性别:{{sex}}h2>
        <h2>朋友们h2>
        <ul>
            <li v-for="(f,index) in student.friends" :key="index">
                {{f.name}}-{{f.age}}
            li>
        ul>
    div>
    body>
    <script>
        Vue.config.productionTip=false;
    
        const vm=new Vue({
            el:"#app",
            data:{
                school:{
                    name:"幸福中学",
                    address:"幸福路"
                },
                // sex:"男",
                student:{
                    name:"张三",
                    age:{
                        rAge:40,
                        sAge:30
                    },
                    friends:[
                        {name:"李四",age:20},
                        {name:"王五",age:25},
                    ]
                },
            }
        })
    script>
    html>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    在这里插入图片描述

    简单的给学生添加性别

    额外的给对象设置属性

    给vm._data.student添加是达不到响应式的,也不会有getter和setter方法

    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
        <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
    head>
    <body>
        <div id="app">
            <h1>学生信息h1>
            <h2>姓名:{{student.name}}h2>
            <h2>年龄:真实{{student.age.rAge}},对外{{student.age.sAge}}h2>
            
            <h2>性别:{{student.sex}}h2>
            <h2>朋友们h2>
            <ul>
                <li v-for="(f,index) in student.friends" :key="index">
                    {{f.name}}-{{f.age}}
                li>
            ul>
        div>
    body>
    <script>
        Vue.config.productionTip=false;
    
        const vm=new Vue({
            el:"#app",
            data:{
                school:{
                    name:"幸福中学",
                    address:"幸福路"
                },
                student:{
                    name:"张三",
                    age:{
                        rAge:40,
                        sAge:30
                    },
                    // sex:"男",
                    friends:[
                        {name:"李四",age:20},
                        {name:"王五",age:25},
                    ]
                }
            }
        })
    script>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    在这里插入图片描述
    用vm.student.sex设置也是得到的同样的结果,在数据代理上并不会有所改变
    在这里插入图片描述
    用Vue.set()添加,就可以做响应式了,有getter和setter方法了。但是不能用在vm或者vm._data上面,不能对data直接 添加属性
    在这里插入图片描述
    用vm.$set()也可以做响应式效果
    在这里插入图片描述
    用方法添加性别

    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
        <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
    head>
    <body>
        <div id="app">
            <h1>学生信息h1>
            <h2>姓名:{{student.name}}h2>
            <h2>年龄:真实{{student.age.rAge}},对外{{student.age.sAge}}h2>
            
            <button @click="addSex">添加一个性别属性,默认值是男button>
            <button @click="addGSex">添加一个性别属性,默认值是女button>
            <h2 v-if="student.sex">性别:{{student.sex}}h2>
            <h2>朋友们h2>
            <ul>
                <li v-for="(f,index) in student.friends" :key="index">
                    {{f.name}}-{{f.age}}
                li>
            ul>
        div>
    body>
    <script>
        Vue.config.productionTip=false;
    
        const vm=new Vue({
            el:"#app",
            data:{
                school:{
                    name:"幸福中学",
                    address:"幸福路"
                },
                student:{
                    name:"张三",
                    age:{
                        rAge:40,
                        sAge:30
                    },
                    // sex:"男",
                    friends:[
                        {name:"李四",age:20},
                        {name:"王五",age:25},
                    ]
                }
            },
            methods:{
                addSex(){
                    Vue.set(this.student,'sex','男')
                },
                addGSex(){
                    this.$set(this.student,'sex','女')
                }
            }
        })
    script>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    请添加图片描述
    注意: 对象不能是Vue实例,或者Vue实例的根数据对象

    Vue检测数组数据原理

    数组不像对象,数组中元素没有getter和setter方法

    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
        <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
    head>
    <body>
        <div id="app">
            <h1>学生信息h1>
            <h2>姓名:{{name}}h2>
            <h2>年龄:{{age}}h2>
            <h2>爱好h2>
            <ul>
                <li v-for="(h,index) in hobby" :key="index">
                    {{h}}
                li>
            ul>
            <hr>
            <h2>朋友h2>
            <ul>
                <li v-for="(f,index) in friends" :key="index">
                    {{f}}
                li>
            ul>
        div>
    body>
    <script>
        Vue.config.productionTip=false;
    
        const vm=new Vue({
            el:"#app",
            data:{
                name:"张三",
                age:20,
                hobby:['读书','看电影','画画'],
                friends:{
                    f1:"王五",
                    f2:"李四",
                    f3:"赵六"
                }
            }
        })
    script>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    在这里插入图片描述
    使用直接修改方法不奏效
    在这里插入图片描述
    修改数组使用pop(),shift(),splice()这些
    请添加图片描述
    使用Vue.set()也可以对数组进行修改
    请添加图片描述

    总结Vue监视属性

    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
        <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
    head>
    <body>
        <div id="app">
            <h1>学生信息h1>
            <button @click="student.age++">年龄+1岁button>   <br>
            <button @click="addSex">添加性别属性,默认值:男button>     <br>
            <button @click="student.sex='未知'">修改性别button>
            <button @click="addFriend">在列表首位添加一个朋友button>  <br>
            <button @click="updateFirstFriendName">修改第一个朋友名字:tombutton>  <br>
            <button @click="addHobby">添加一个爱好button>    <br>
            <button @click="correctHobby">修改第一个爱好为:开车button>
            <h2>姓名:{{student.name}}h2>
            <h2>年龄:{{student.age}}h2>
            <h2 v-if="student.sex">性别:{{student.sex}}h2>
            <h2>爱好:h2>
            <ul>
                <li v-for="(h,index) in student.hobby" :key="index">
                    {{h}}
                li>
            ul>
            <h2>朋友们:h2>
            <ul>
                <li v-for="(f,index) in student.friends" :key="index">
                    {{f.name}}--{{f.age}}
                li>
            ul>
        div>
    
    body>
    <script>
        Vue.config.productionTip=false;
        const vm=new Vue({
            el:"#app",
            data:{
                student:{
                    name:"张三",
                    age:20,
                    hobby:["看书","打游戏","画画"],
                    friends:[
                        {name:"李四",age:30},
                        {name:"王五",age:35},
                    ]
                }
            },
            methods:{
                addSex(){
                    // Vue.set(this.student,"sex","男")
                    this.$set(this.student,"sex","男")
                },
                addFriend(){
                    this.student.friends.unshift({name:"jack",age:25})
                },
                updateFirstFriendName(){
                    // this.student.friends.splice(0,1,{name:"tom",age:28})
                    this.student.friends[0].name="tom"
                    this.student.friends[0].age=15
                },
                addHobby(){
                    this.student.hobby.push("唱歌")
                },
                correctHobby(){
                    // this.student.hobby.splice(0,1,"开车")
                    Vue.set(this.student.hobby,0,"开车")
                    this.$set(this.student.hobby,0,"开车")
                }
    
            }
        })
    script>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76

    请添加图片描述

    Vue监视数据的原理:

    1. Vue会监视data中所有层次的数据
    2. 如何检测对象中的数据?
      通过setter实现监视,且要在new View时就传入要检测的数据
      (1)对象中后追加的属性,Vue默认不做响应式处理
      (2)如需给后添加的属性做响应式,请使用如下API:
      Vue.set(tartget,propertyName/index,value) 或 vm.$set(target,propertyName/index,value)
    3. 如何检测数组中的数据?
      通过包裹数组更新元素的方法实现,本质就是做了两件事:
      (1)调用原生对应的方法对数组进行更新
      (2)重新解析模板,进而更新页面
    4. 在Vue修改数组中的某个元素一定要用如下方法:
      (1)使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
      (2)Vue.set()或vm.$set()

    特别注意:Vue.set()和vm.$set()不能给 vm 或 vm的根数据对象 添加属性

    对filter(),concat()和slice()这些非变更方法,不会改变原始数组,而总是返回一个新数组,当使用这些方法时候,可以用新数组替换旧数组

    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
        <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
    head>
    <body>
        <div id="app">
            <h1>学生信息h1>
            <button @click="removeRead">过滤掉读书的爱好button>
            <h2>爱好h2>
            <ul>
                <li v-for="(h,index) in student.hobby" :key="index">
                    {{h}}
                li>
            ul>
        div>
    body>
    <script>
        Vue.config.productionTip=false;
        const vm=new Vue({
            el:"#app",
            data:{
                student:{
                    hobby:["读书","看报","唱歌"]
                }
            },
            methods:{
                removeRead(){
                    this.student.hobby=this.student.hobby.filter((h)=>{
                        return h!=="读书"
                    })
                }
            }
        })
    script>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    为 Serverless Devs 插上 Terraform 的翅膀,实现企业级多环境部署(上)
    【路径规划】基于梯度下降算法求解自定义起点终点障碍路径规划问题附matlab代码
    时间序列-AR MA ARIMA
    一个注解搞定SpringBoot接口定制属性加解密
    Linux(二)LED驱动程序框架(总线设备驱动)
    wpf添加Halcon的窗口控件报错:下列控件已成功添加到工具箱中,但未在活动设计器中启用
    “Life Long Learning”(终身学习)和“灾难性遗忘”(catastrophic forgetting)
    (二十三)数据结构-交换排序
    深入浅出学习透析Nginx服务器的基本原理和配置指南「Keepalive性能分析实战篇」
    DNS抓包
  • 原文地址:https://blog.csdn.net/qq_34306228/article/details/127930219