zoukankan      html  css  js  c++  java
  • 422 vue day03

    异步 DOM 更新

    1、Vue 中采用了 异步DOM更新 的机制

    2、如何更新页面

    • 数据发生改变后, vue 没有立即将数据的改变更新到视图中, 而是等到数据不再变化的时候 一次性的 将 数据的改变更新到视图中

       // 1. 验证了
       for (let i = 0; i < 1000; i++) {
           this.count++
       }
      

    3、为什么是异步 DOM 更新

    • 性能的考虑
    • 因为对于前端来说, 修改数据进行 DOM 操作是常有的事情, 如果频繁操作 DOM, 会严重影响页面的加载性能
    • DOM 操作这是前端的性能的瓶颈
    • 比如 : for (let i = 1; i < 10000; i++>) ,如果同步, 就要重新渲染 1000 次

    4、验证 异步 DOM 更新

    // 2. 直接获取data 中的值, 会立马获取成功
    console.log(this.count)
    this.count++
    console.log(this.count)
    
    // 但是 通过dom来获取count的值,因为DOM更新这个count值是异步的,是需要一点时间的
    console.log(document.querySelector('h1').innerText) // 0
    this.count = 100
    console.log(document.querySelector('h1').innerText) // 0
    

    5、需求 : 在数据更新后,立即获取到更新后的内容

    DOM 更新后,会执行 this.$nextTick() 的回调函数,所以能拿到值

    // setTimeout(() => {
    //      console.log(document.querySelector('h1').innerText)
    //   }, 1000)
    this.$nextTick(() => {
      console.log(document.querySelector('h1').innerText) // 100
    })
    

    01-DOM异步更新.html
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
    </head>
    
    <body>
        <!-- 
           DOM更新是异步的 
           - 性能的考虑
           - 证明 
           - $nextTick:解决异步DOM更新获取数据的问题 【$nextTick 是 实例对象的方法。】
         -->
    
        <div id="app">
            <h1>{{ num }}</h1>
            <button @click="fn">按钮</button>
        </div>
    
        <script src="./vue.js"></script>
        <script>
            const vm = new Vue({
                el: '#app',
                data: {
                    num: 100
                },
                methods: {
                    fn() {
                        // 没问题的 【同步】
                        // console.log(this.num)
                        // this.num += 1
                        // console.log(this.num)
    
                        // 操作DOM ,获取DOM里的内容数据
                        console.log(document.querySelector('h1').innerText) // 100
                        this.num += 1 // +1 【数据变化,去更新DOM时,是异步的】
                        console.log(document.querySelector('h1').innerText) // 100
    
                        // 问题来了?
                        // 解决办法1 : 等你3秒 【不推荐】
                        // setTimeout(() => {
                        //   console.log(document.querySelector('h1').innerText) // 100
                        // }, 1000)
    
                        // 解决办法2 : 希望数据改变了, 视图更新完毕后, 通知我, 我再去获取h1里的值
                        // 更新视图完毕后, 自动会触发这个回调
                        // 面试 : 数据 、DOM(视图 更新)
                        this.$nextTick(() => {
                            console.log(document.querySelector('h1').innerText)
                        })
    
                        // console.log(1)
                        // 异步给我们的感觉有点延迟
                        // setTimeout(() => {
                        //   console.log('hha ')
                        // }, 0)
                        // console.log(2)
                    }
                }
            })
        </script>
    </body>
    
    </html>
    

    02-数据变化更新问题.html

    数据发生变化 ,不是一改变就立马更新的, 而是当数据不再发生变化的时候,一次性统一更新的。

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
    </head>
    
    <body>
        <!-- 
            数据发生变化 ,不是一改变就立马更新的, 而是当数据不再发生变化的时候,一次性统一更新的
          -->
        <div id="app">
            <h1>{{ num }}</h1>
            <button @click="fn">按钮</button>
        </div>
        <script src="./vue.js"></script>
        <script>
            const vm = new Vue({
                el: '#app',
                data: {
                    num: 1
                },
                methods: {
                    fn() {
                        for (var i = 1; i <= 100; i++) {
                            this.num++
                        }
                    }
                }
            })
        </script>
    </body>
    
    </html>
    

    数据响应式问题:$set()

    1. 数据 : obj > name > 有值(zs) ,  绑定: v-modle='obj.name' ==> ok
    2. 在某个事件中, 直接添加属性,是不行的,  this.$set() 处理
    
    总结 : 
    1. 以后尽量先在data里声明好, 给一个初始值, 以后就可以正常使用了
    2. 在一些第三方框架里, 我们就必须动态的添加额外的数据, 使用this.$set()
    
    03-数据响应式问题.html
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
    </head>
    
    <body>
        <!-- 
           1. 数据 : obj > name > 有值(zs)   ,  绑定: v-modle='obj.name' ==> ok
           2. 在某个事件中, 直接添加属性, 是不行的,  用this.$set() 处理
    
           总结 : 
           1. 以后尽量先在data里声明好, 给一个初始值, 以后就可以正常使用了
           2. 在一些第三方框架里, 我们就必须动态的添加额外的数据,  用this.$set()
         -->
    
        <div id="app">
            <input type="text" v-model="obj.name" />
            <button @click="fn">按钮</button>
        </div>
    
        <script src="./vue.js"></script>
        <script>
            const vm = new Vue({
                el: '#app',
                data: {
                    obj: {
                        // name :'zs'
                    }
                },
                methods: {
                    fn() {
                        console.log('123');
                        // 下面 这样直接添加是不行的, 是无法实现正常的数据劫持, 无法正常的进行数据响应式
                        // this.obj.name = 'zs';
                        
                        // 解决方案:官方推荐使用 this.$set,三个参数:对象、属性、属性值
                        this.$set(this.obj, 'name', 'zs');
                    }
                }
            })
        </script>
    </body>
    
    </html>
    

    监听 watch

    1、数据持久化 (本地存储)

    1. 可以在数组的`增删改`, 都要保存一下, 比较繁琐
    2. 监听数组的变化, 数组一旦发生变化, 在监听里面 保存一下(代码写一遍就可以了)
    
    vue 提供了一个监听器.
    

    TodoMVC 数据持久化

    需求 : 将todoMVC中的数据, 保存到 本地存储中 (本地持久化)

    1. 何时存储数据?

      因为功能中的 CRUD 都会修改 list 数据,所以,只要 list 数据发生改变, 就要保存到本地存储中;
      方法一 : 在 CRUD 中 分别调用保存数据的方法,(不推荐 太繁琐)
      方法二 : 想办法监听 list 数据的改变,只要 list 数据变了, 就调用保存数据的方法

    可以使用 vue 的 watch 监听 list 的数据改变

    1. 存储值

      监听数组和监听对象一样 需要深度监听
      保存值, 记得把对象转化为字符串(存的快 省空间)

       // 监听
       watch: {
          // 监听list
          todoList: {
             deep: true,
             handler(newVal) {
                // console.log('发生变化了', newVal)
                // 保存起来
                localStorage.setItem('todoList', JSON.stringify(newVal))
             }
          }
       },
    
    
    1. 取值 , 在 data 中可以初始值

      记得给一个默认值 空数组 []

    	const todoList =  JSON.parse(localStorage.getItem('todoList')) || [],
    
    

    2、说明

    Vue 中可以通过 watch 配置项, 来监听 vue 实例中数据的变化


    3、基本使用

    watch: {
        // 监听name属性的数据变化
        // 作用 : 只要name的值发生变化,这个方法就会被调用
        // 第一个参数 : 新值
        // 第二个参数 : 旧值,之前的前
        name(newVal,oldVal){
                console.log('新 :',newVal);
                console.log('旧 :',oldVal);
        }
    }
    
    

    4、基本使用案例

    需求 : 监听用户名文本框字符个数(3-6),并显示格式验证

    <input type="text" v-model="name" />
    <span v-show="isShow">用户名的字符 在 6-12之间</span> if
    (/^[0-9a-zA-Z]{3,6}$/.test(newVal)) { 验证 }
    
    

    5、监听对象 (数组也属于对象)

    // data :
     data: {
       obj: {
       name: 'zs'
       }
    },
    // 组件
    <input type="text" v-model="obj.name" />
    // 监听
    
    

    6、开始监听对象的属性

    // 从对象的角度来监听的
     因为对象和数组都是引用类型,引用类型变量存的是地址,地址没有变,所以不会触发watch
    obj:{
        // 深度监听 属性的变化
        deep:true,
        // 立即处理 进入页面就触发
        immediate: true,  
        // 数据发生变化就会调用这个函数  
        handler( newVal ) {
          console.log( newVal.name );
         }
      },
     // 从属性的角度来监听
     'obj.name' ( newVal ) {
          console.log('监听对象的属性',newVal);
     }
    
    

    7、计算属性和watch的区别

    computed 和 watch的区别
    computed :  计算属性
        - 1.根据已知值 ,得到一个新值 
            - 2. 新值随着已知值(相关的数据)变化而变化 
            1. 计算属性 ==> (得到的是)新值
            2. 计算属性(num)  ==> 是别人影响了我
    
    watch : 监听器
    1. 监听 ==> (监听)已知值
    2. 监听数据 (num2) => 是我影响到了别人
    
    

    8、命名规则 : 数字 字母 _ $

    let xxx = 'sex'
    
    let obj = {
      'mg-name': 'zs',
      age: 20,
      // sex : '男'
      [xxx] : '男'
    }
    
    

    05-监听器的基本使用-我的.html
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            [v-cloak] {
                display: none;
            }
        </style>
    </head>
    
    <body>
        <div id="app">
            <h1>{{ num }}</h1>
            <button @click="fn">按钮</button>
        </div>
    
        <script src="./vue.js"></script>
        <script>
            const vm = new Vue({
                el: '#app',
                data: {
                    num: 100,
                    msg: {}
                },
                methods: {
                    fn() {
                        for (let i = 0; i < 5; i++) {
                            this.num++
                        }
                    }
                },
                watch: {
                    num(newVal, oldVal) {
                        console.log(`新值是:${newVal},旧值是:${oldVal}`); // 新值是:105,旧值是:100
                    }
                }
            })
        </script>
    
    </body>
    
    </html>
    <script>
    </script>
    
    

    06-监听器监听复杂类型.html
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
    </head>
    
    <body>
        <div id="app">
            <input type="text" v-model="obj.name" />
        </div>
        <script src="./vue.js"></script>
        <script>
            const vm = new Vue({
                el: '#app',
                data: {
                    obj: {
                        name: 'zs'
                    }
                },
                // 监听
                watch: {
                    // 监听 obj ,如果监听成功 newVal 就是obj的最新值 newVal 也是对象
                    // 因为obj是复杂类型 引用类型,直接这么写,监听的是对象的地址 【所以只有地址发送改变时,才会监听到。】
                    // obj(newVal) {
                    //   console.log(newVal.name)
                    // }
    
                    // 方式1 : 监听对象+ 深度监听 【注意语法】
                    obj: {
                        deep: true, // 深度监听
                        immediate: true, // 立即监听
                        // 处理
                        handler(newVal) {
                            console.log(newVal.name)
                        }
                    },
    
                    // 方式2: 简单粗暴的直接监听对象里的属性(name)
                    'obj.name' (newVal) {
                        console.log(newVal)
                    }
                }
            })
        </script>
    </body>
    
    </html>
    
    

    08-监听器的小案例.html
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <title>Document</title>
      </head>
      <body>
        <!-- 
            需求 : 监听文本框内容的字符串长度 (3-6) , 如果超过范围,提示格式不正确
        -->
        <div id="app">
          <input type="text" v-model="msg" />
          <span v-show="isShow">格式不正确</span>
        </div>
        <script src="./vue.js"></script>
        <script>
          const vm = new Vue({
            el: '#app',
            data: {
              msg: '',
              isShow: false
            },
            watch: {
              msg(newVal) {
                if (newVal.length >= 3 && newVal.length <= 6) {
                  console.log('格式正确')
                  this.isShow = false
                } else {
                  console.log('格式不正确')
                  this.isShow = true
                }
              }
            }
          })
        </script>
      </body>
    </html>
    
    

    09-计算属性和监听器的区别.html
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
    </head>
    
    <body>
        <!-- 
        计算属性 computed       
        监听器 watch
    
        计算属性 : 
          - 根据已知值, 得到一个新值
          - 新值随着`相关的数据`发生变化而变化
          - 是一个新值, 不是data里的值
          区别 :
            - 别人改变, 影响到了我【我:即计算属性】
        
        监听器
          - 监听数据的变化  
          - 监听的不是一个新值(可以是data里的值)
          
          区别 :
          - 我改变了, 去影响别人 【被监听的数据改变了,会触发一些操作。】 【当被监听的数据改变了,就......】
       -->
    
        <div id="app"></div>
        <script src="./vue.js"></script>
        <script>
            const vm = new Vue({
                el: '#app',
                data: {
                    num1: 100,
                    num2: 200
                },
                computed: {
                    totalNum() {
                        return this.num1 + 20
                    }
                },
                watch: {
                    num2(newVal) {
                        // console.log(newVal)
                        if (newVal <= 205) {
                            console.log('我想干第一件事')
                        } else {
                            console.log('我想干第二件事')
                        }
                    }
                }
            })
        </script>
    </body>
    
    </html>
    
    

  • 相关阅读:
    浅谈纯文本&&富文本&&Markdown区别
    浅谈CSS图片base64编码技术
    postman测试请求API:方式post、上传文件file
    Antd版本V3-->V4迁移问题:初始化调整
    浅谈switch语句的技巧
    react路由传参
    react dangerouslySetInnerHTML用法
    SPA单页应用的2种类型分页技术(React、Vue等组件化开发)
    (3)re模块(正则表达式模块)
    (2)hashlib模块(加密算法模块)
  • 原文地址:https://www.cnblogs.com/jianjie/p/12605498.html
Copyright © 2011-2022 走看看