学习列表

初学Vue(一)-- Vue简单入门

初学vue(二)-- 条件渲染、修饰符、循环

初学vue(四)-- axios前后端交互、组件

初学vue(五)-- 路由


异步 DOM 更新

  1. Vue 中采用了 异步DOM更新 的机制
  2. 如何更新页面?
  • 数据发生改变后, vue 没有立即将数据的改变更新到视图中,
  • 而是等到数据不再变化的时候 一次性的 将 数据的改变更新到视图中

     //1. 验证了
     for (let i = 0; i < 1000; i++) {
         this.count++
     }
  1. 为什么是异步 DOM 更新?
  • 性能的考虑
  • 因为对于前端来说, 修改数据进行 DOM 操作是常有的事情,如果频繁操作 DOM,会严重影响页面的加载性能
  • DOM 操作这是前端的性能的瓶颈
  • 比如 : for (let i = 1; i < 10000; i++>) 如果同步 就要重新渲染 1000 次
  1. 验证 异步 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
  1. 需求 : 在数据更新后,立即获取到更新后的内容

    DOM 更新后,会执行 this.&dollar;nextTick() 的回调函数,所以能拿到值
// setTimeout(() => {
//      console.log(document.querySelector('h1').innerText)
//   }, 1000)
this.$nextTick(() => {
  console.log(document.querySelector('h1').innerText) // 100
})

一:过滤器

  1. 概念 :
  • vue 中的过滤器(filter) : 数据格式化 ,
  • 也就是说,让数据按照我们规定的一种格式输出
  • 比如 : 对于日期来说,将日期格式化转化为 年-月-日 小时:分:秒 格式的过程
 // 直接显示
 <h1>{{ date  }}</h1>
 显示 :   2019-01-11T10:11:19.566Z
 不是我们想要的
 我们想要的 : 2019-01-11 18-11-53
  1. 全局过滤器 和 局部过滤器
  • 说明 : 通过全局方式创建的过滤器,在任何一个 Vue 实例中都可以使用 (一般情况下,为了项目方便管理,都是一个 vue 实例)
  • 注意点: 使用全局过滤器的时候,应该先创建全局过滤器,再创建 Vue 实例
  • 局部创建的过滤器 只能在当前 vue 实例中使用
  1. 怎么注册 全局过滤器
// 第一个参数 : 过滤器的名字
// 第二个参数 : 是一个回调函数,只要使用过滤器的时候,这个回调函数就会执行
///           通过回调函数的返回值得到格式化后的数据
Vue.filter('date', res => {
  return '嘻嘻'
})
  1. 使用过滤器 示例 :
// 组件
 <h1>时间戳-格式 {{ date2 | date }}</h1>

// js
  Vue.filter('date', res => {
         return `${res.getFullYear()}-${res.getMonth()}-${res.getDate()} ${res.getHours()}:${res.getMinutes()}:${res.getSeconds()}`
      })
  1. moment 插件
  • moment 地址
  • 使用

    1. 安装 : `npm i moment`
    2. 引入 :
    3. 使用
  • 日期 => 指定格式 moment(res).format('YYYY-MM-DD HH-mm-ss')
  • 时间戳 => 指定格式 moment(res).format('YYYY-MM-DD HH-mm-ss')
  • // 全局
    Vue.filter('date', res => {
      return moment(res).format('YYYY-MM-DD HH-mm-ss')
    })
  1. 参数问题
  • 示例
<h1>时间戳-格式 {{ date2 | date('YYYY-MM-DD HH-mm-ss',888) }}</h1>

// 默认值
Vue.filter('date', (res, format = 'YYYY-MM-DD', arg) => {
  console.log(arg)
  return moment(res).format(format)
})
  1. 局部过滤器

    在 vm 的配置项里写一个 filters
    对应的是一个对象
 filters: {
    date(res, format = 'YYYY-MM-DD', arg) {
      return moment(res).format(format)
    }
  }

二:计算属性 computed

在模板中双向绑定一些数据或表达式,如果表达式过长或者逻辑更复杂时,就会变得臃肿和难以阅读,比如:

<div>
    {{text.split(',').reverse().join(',')}}
<div>
    
<div id='app'>
        {{reversedText}}
<div>

<script>
    var app = new Vue({
        el:'#app',
        data:{
            text:'123,456'
        },
        computed: {
            reversedText: function(){
                //这里的this指向的是当前的Vue实例
                return this.text.split(',').reverse().join(',');
            }
        }
    })
    
</script>

所有的计算属性都以函数的形式写在Vue实例内的computed选项内,最终返回计算后的结果。

你可以发现,这个例子完全可以用methods内的方法完成,甚至用methods的方法使用还能够接收参数,跟更加灵活,那么为什么要使用计算属性呢,因为计算属性是基于它的依赖缓存的。一个计算属性所依赖的数据发生变化时,它才会重新取值,所以text只要不改变,计算属性也就不更新,例如:

computed:{
    now:function(){
       return Date.now(); 
    }
}

这里的Date。now() 不是响应式依赖,所以计算属性now不会更新。但是methods则不同,只要重新渲染,它就会被调用,因此函数也会被执行。

使用计算属性还是methods取决于你是否需要利用到缓存,当遍历大数组和做大量计算时,应当使用计算属性,除非你不希望得到缓存。


计算属性用法

在一个计算属性内可以完成各种复杂的逻辑,包括运算,函数调用等,只要最终返回一个结果就可以了。

计算属性可以依赖同一实例内多个数据,只要其中任意一个发生变化,计算属性就会重新执行,视图也会更新。

例如:假设计算两个商品的价格

<div id='app'>
    总价:{{ prices }}
</div>

<script>
    var app = new Vue({
        el:'#app',
        data:{
            package1:[
                {
                    name:'iphone 7',
                    price:7199,
                    count:2
                },
                {
                    name:'ipad',
                    price:2888,
                    count:1
                }
            ],
            package2:[
                {
                    name:'apple',
                    price:3,
                    count:5
                },
                {
                    name:'banana',
                    price:2,
                    count:10
                }
            ]
        },
        computed:{
            prices:function(){
                var prices = 0;
                for(let i = 0,len = this.package1.length; i < len; i++){
                    prices += this.package1[i].price * this.package1[i].count;
                }
                for(let i = 0,len = this.package2.length; i < len; i++){
                    prices += this.package2[i].price * this.package2[i].count;
                }
                return prices;
            }
        }
    })
</script>

计算属性除了可以依赖同一实例的多个数据,也可以依赖不同实例的数据,例如:

<div id='app1'></div>
<div id='app2'>
    {{ reversedText }}    
</div>

<script>
    var app1 = new Vue({
        el:'#app1',
        data:{
            text:'123,456'
        }
    });
    var app2 = new Vue({
        el:'#app2',
        computed:{
            reversedText:function(){
                //这里依赖的是实例app1的数据text
                return app1.text.split(',').reverse().join(',');// => '456,123'
            }
        }
    })
</script>

计算属性的getter与setter

每一个计算属性都包含一个 gettersetter,默认调用getter访问,在你需要时也可以提供一个setter。当手动修改计算属性的值时,就会触发setter函数。例如:

<div id='app'>
    姓名: {{ fullName }} 
</div>

<script>
    var app = new Vue({
        el:'#app',
        data:{
            name:'张伟'
        },
        computed:{
            fullName:{
                //getter,用于读取
                get:function(){
                    return this.name;
                },
                //setter,用于写入
                set:function(newName){
                    this.name = newName;
                }
            }
        }
    })

三 : 监听 watch

  1. 说明 : Vue 中可以通过 watch 配置项,来监听 vue 实例中数据的变化
  2. 基本使用

    watch: {
        // 监听name属性的数据变化
        // 作用 : 只要name的值发生变化,这个方法就会被调用
        // 第一个参数 : 新值
        // 第二个参数 : 旧值,之前的前
        name(newVal,oldVal){
                console.log('新 :',newVal);
                console.log('旧 :',oldVal);
        }
    }
  3. 基本使用案例 :
    需求 : 监听用户名文本框字符个数(3-6),并显示格式验证
<input type="text" v-model="name" />
<span v-show="isShow">用户名的字符 在 6-12之间</span> if
(/^[0-9a-zA-Z]{3,6}$/.test(newVal)) { 验证 }
  1. 监听对象 (数组也属于对象)
// data :
 data: {
   obj: {
   name: 'zs'
   }
},
// 组件
<input type="text" v-model="obj.name" />
// 监听
  1. 开始监听对象的属性
// 从对象的角度来监听的
 因为对象和数组都是引用类型,引用类型变量存的是地址,地址没有变,所以不会触发watch
obj:{
    // 深度监听 属性的变化
    deep:true,
    // 立即处理 进入页面就触发
    immediate: true,  
    // 数据发生变化就会调用这个函数  
    handler( newVal ) {
      console.log( newVal.name );
     }
  },
 // 从属性的角度来监听
 'obj.name' ( newVal ) {
      console.log('监听对象的属性',newVal);
 }
  1. 计算属性和watch的区别
computed 和 watch的区别
computed :  计算属性
    - 1.根据已知值 ,得到一个新值 
        - 2. 新值随着已知值(相关的数据)变化而变化 
        1. 计算属性 ==> (得到的是)新值
        2. 计算属性(num)  ==> 是别人影响了我

watch : 监听器
1. 监听 ==> (监听)已知值
2. 监听数据 (num2) => 是我影响到了别人

四 : 本地缓存

1.存储值

监听数组和监听对象一样 需要深度监听
保存值,记得把对象转化为字符串(存的快 省空间)
   // 监听
   watch: {
      // 监听list
      todoList: {
         deep: true,
         handler(newVal) {
            // console.log('发生变化了', newVal)
            // 保存起来
            localStorage.setItem('todoList', JSON.stringify(newVal))
         }
      }
   },

2.取值 , 在 data 中可以初始值

记得给一个默认值 空数组 []
    const todoList =  JSON.parse(localStorage.getItem('todoList')) || [],

五、生命周期函数

  • 所有的 vue 组件,都是 vue 实例, 一个组件对应一个实例,并且接收相同的选项对象(一些根实例特有的选项除外)
  • 实例生命周期也叫做 : 组件生命周期

生命周期介绍

vue 生命周期钩子函数

  • 简单说 : 一个组件(实例) 从开始到最后消灭所经历的各种状态,就是一个组件(实例)的生命周期
  • 生命周期钩子函数的定义 : 从组件被创建,到组件挂在到页面上运行,再到页面关闭组件被销毁,这三个阶段总是伴随着组件各种的事件,这些事件,统称为组件的生命周期函数 (简称 : 钩子函数)
  • 开发人员可以通过 vue 提供的钩子函数,让我们写的代码参与到 vue 的生命周期里面来,让我们的代码在合适的阶段起到相应的作用
注意 :
  1. 注意 : vue 在执行过程中 会自动调用 生命周期钩子函数, 我们只需要提供这些钩子函数即可
  2. 注意 : 钩子函数的名称都是 vue 中规定好的

5.0 学习 vue 组件生命周期 学什么?

  1. Vue 内部执行的流程
  2. 钩子函数如何使用 (两个重要的钩子函数 created mounted)

5.1 钩子函数 - beforeCreate

  • 说明 : 在实例初始化之前,数据观测 和 event/watcher 事件配置之前被调用
  • 组件实例刚被创建,组件属性计算之前, 例如 data 属性 methods 属性
  • 注意 : 此时,无法获取 data 中的数据 和 methoids 中的方法
  • 场景 : 几乎不用

5.2 钩子函数 - created

  • 说明 : 组件实例创建完成,属性已绑定, 可以调用 methods 中的方法、可以获取 data 值
  • vue 实例生命周期 参考 1
  • vue 实例生命周期 参考 2
  • 使用场景 : 1-发送 ajax 2-本地存储获取数据
  • beforeCreate() {
        // 无法获取数据和事件
        console.warn('beforeCreate', this.msg, this.fn)
    },
    created() {
      console.warn('created', this.msg, this.fn)
    },

5.3 钩子函数 - beforeMounted()

  • 说明 : 在挂载开始之前被调用 (挂载:可以理解DOM 渲染)

5.3 钩子函数 - mounted()

  • 说明 : 挂载之后, DOM 完成渲染
  • 使用场景 : 1-发送 ajax 2-操作 DOM
  • 记得把template去掉 
    // 渲染DOM之前
     beforeMount() {
         // 渲染之前的  <h1 id="h1" @click="fn">{{ msg }}</h1>
       console.log(document.querySelector('h1'))
     },
     // 渲染DOM之后  <h1 id="h1">测试</h1>
     mounted() {
       console.log(document.querySelector('h1'))
     }

5.4 钩子函数 - beforeUpdated()

  • 说明:数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。你可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。
  • 注意:此处获取的数据是更新后的数据,但是获取页面中的 DOM 元素是更新之前的

    小提示 : 打印 this.&dollar;el ,打开小三角是之后的,是因为打印是有监听的功能,展示的是后面更改之后的

5.5 钩子函数 - updated()

  • 说明:组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。
  • beforeUpdate() {
        // 更新之前的值  :  信息
      console.warn('beforeUpdate',document.querySelector('h1').innerText)
    },
    updated() {
        // 更新之后的值 : 信息1111
      console.warn('updated', document.querySelector('h1').innerText)
    }

5.6 钩子函数 - beforeDestroy()

  • 说明:实例销毁之前调用。在这一步,实例仍然完全可用。
  • 使用场景:实例销毁之前,执行清理任务,比如:清除定时器等
  created() {

   this.timerId =   setInterval(() => {
      console.log(1111);

      }, 500);
   },

 // 如果当组件销毁了,还不清除定时器会出现性能问题
 // 在浏览器中可以尝试销毁  vm.$destroy()
 // 最后销毁
beforeDestroy() {
      clearInterval(this.timerId)
 },

5.7 钩子函数 - destroyed()

说明:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。


六 : 使用钩子函数来完善 数据存储

created {
    this.list = JSON.parse(localStorage.getItem('list'))
}

Bill
163 声望11 粉丝

职业:网管