vue的知识点整理

VUE

1.初始化VUE

  1. 引入vue.js

    直接下载,使用script标签导入或MDN引入,或npm

  2. 引入vue.js后,其向我们提供了一个构造函数Vue,在js中new Vue()后会返回 一个实例对象,定义一个变量接收const vm=new Vue()
  3. 在构造函数内传入一个对象参数{},const vm=new Vue({})

2.VUE中的配置参数

①.el(或$mount)
作用:配置控制的元素,表示Vue要控制的区域,值为css选择器

 
 <div id="app">div>
  const vm = new Vue({
    el: '#app' // 控制id为app的元素
  })

  const vm = new Vue({})
  vm.$mount('#app');

②.data

  • 类型:对象
  • 作用:存放要用到的数据,数据为响应式的
      const vm = new Vue({
        el: '#app',
        data: {
         ‘xxx’:'yyyy',
        }
      })
    

③.插值表达式

  • 使用方法: {{ }}
  • 可以将vue中的数据填在插值表达式中

数据包括:data中的变量、数字、字符串、布尔值、underfined、null、数组、对象、表达式(运算表达式、逻辑表达式、三元表达式、函数调用)

注意:在插值表达式中直接书写对象类型值时,不要将三个{}连在一起,这样会报错

注意:只要插值表达式中使用了数据,必须在data中声明过,否则会报错;
除非使用了data中引用类型(对象)中的未被声明的变量。
(在作用域上找不到,报错 ;在原型链上找不到,值为undefined;undefined为js基本类型值,所以就不报错啦 )

3.VUE的响应式原理

  • 问:为什么data会直接出现在vm实例对象中咧?

答:当创建vue实例时,vue会将data中的成员代理给vue实例,目的是为了实现响应式,监控数据变化,执行某个监听函数

  • 问:实例中除了data数据外,其他东西是啥子?

为了防止名称冲突。因为会将data中数据代理给vue,假如说我们自己写的data名称和vue中自带的属性冲突了,那么就会覆盖vue内部的属性,所以vue会把自己内部的属性成员名称前加上$或_,如果加上的是$,代表是我们可以使用的,如果加上的是_,是vue自己内部使用的方法或属性,我们不需要调用

(1)数据发生以下变化,均不会重新渲染页面

– 1、更改的数据必须是存在的数据,否则不能重新渲染页面,因为他监听不到;
–2、更改的数据必须已渲染过的数据,否则从性能角度考虑,不会重新渲染页面;
–3、利用索引直接设置一个数组项时;
–4、修改数组的长度时;
–5、添加或删除对象

(2)如何响应式的更新数组和对象?

更改数组:
1. 利用数组变异方法:push、pop、shift、unshift、splice、sort、reverse
2. 利用vm.$set/Vue.set实例方法
3. 利用vm.$set或Vue.set删除数组中的某一项

vm.$set是Vue.set的别名
使用方法:Vue.set(object, propertyName, value),也就是这个意思:Vue.set(要改谁,改它的什么,改成啥)

vm.$delete是Vue.delete的别名
使用方法:Vue.delete(object, target),也就是这个意思:Vue.delete(要删除谁的值,删除哪个)

  • 更改数据后,页面会立刻重新渲染吗?

vue更新DOM的操作是异步执行的,只要侦听到数据变化,将开启一个异步队列,如果一个数据被多次变更,那么只会被推入到队列中一次,这样可以避免不必要的计算和DOM操作。

(3)vm.$nextTick & Vue.nextTick

  • 如何在更改数据后,看到渲染后的页面上的值?

答:利用vm.$nextTick或Vue.nextTick,在页面重新渲染,DOM更新后,会立刻执行vm.$nextTick

使用方式:
①、

const vm = new Vue({})
// 1. 使用vm.$nextTick
vm.$nextTick(() => {})
// 2. 使用Vue.nextTick
Vue.nextTick(() => {})

②、vm.nextTick和Vue.nextTick还可以作为Promise使用

const vm = new Vue({})
// 1. 使用vm.$nextTick
vm.$nextTick().then(() => {})
// 2. 使用Vue.nextTick
Vue.nextTick().then(() => {})
  • vm.$nextTick 和 Vue.nextTick的区别?

Vue.nextTick内部函数的this指向window

  Vue.nextTick(function () {
    console.log(this); // window
  })

vm.$nextTick内部函数的this指向Vue实例对象

  vm.$nextTick(function () {
    console.log(this); // vm实例
  })
  • nextTick实现原理
    – 异步任务分为宏任务(macro)和微任务(micro)
    – 宏任务比较慢(如setTimeout等),微任务比较快(如Promise.then()等)
    – 微任务在前,宏任务在后(eventloop,事件环)
      // 控制台打印顺序:promise > timeout
      setTimeout(() => {
        console.log('timeout');
      }, 0)  
      Promise.resolve().then(() => {
        console.log('promise');
      })
    
    – 在nextTick的实现源码中,会先判断是否支持微任务,不支持后,才会执行宏任务
      if(typeof Promise !== 'undefined') {
        // 微任务
        // 首先看一下浏览器中有没有promise
        // 因为IE浏览器中不能执行Promise
        const p = Promise.resolve();
    
      } else if(typeof MutationObserver !== 'undefined') {
        // 微任务
        // 突变观察
        // 监听文档中文字的变化,如果文字有变化,就会执行回调
        // vue的具体做法是:创建一个假节点,然后让这个假节点稍微改动一下,就会执行对应的函数
      } else if(typeof setImmediate !== 'undefined') {
        // 宏任务
        // 只在IE下有
      } else {
        // 宏任务
        // 如果上面都不能执行,那么则会调用setTimeout
      }
    
  • 曾经vue用过的宏任务
    • MessageChannel 消息通道 宏任务

(4)剖析Vue响应式原理

const data={
    name:'lin',
    age:18,
    sex:'man',
    love:{
        food:'fish',
        play:'swing'
    },
    hobby:['asfda','afasd'],
}

//针对数组变异方法的处理
const arrayProto=Array.prototype;
const arrayMethods=Object.create(arrayProto);//创建一个新的数组原型方法的对象
['push','pop','shift','unshift','sort','splice','reverse'].forEach(method=>{
    arrayMethods[method]=function(){
        arrayProto[method].call(this,...arguments);
        render();//变异,原来数组的方法上没有重新渲染
    }
})


function defineReactive(data,key,value){
    observer(data[key]);
    Object.defineProperty(data,key,{
        get(){
            console.log('du');
            return value;
        },
        set(newValue){
            if(newValue!=value){
                value=newValue;
                console.log('xie');
                render();
            }
        }
    })
}


function observer(data){
    if(Array.isArray(data)){//为了防止数组情况出现,vue不能对数组进行递归遍历,因为太耗性能,所以使用数组的变异方法
        data.__proto=arrayMethods;
        return;
    }

    if(typeof data ==='object'){
        for (let key in data) {
            defineReactive(data,key,data[key]);
        }    
    }
}

function render(){
    console.log('页面渲染');
}

//实现$set
function $set(data,key,value){
    if(Array.isArray(data)){
        data.splice(key,1,value);
        return value;
    }
    else if(typeof data ==='object'){
        defineReactive(data,key,value);//给新添加的值也加上监听
        render();
        return value;
    }
}

//实现$delete
function $delete(data,key){
    if(Array.isArray(data)){
        data.splice(key,1);
        return;
    }
    delete data[key];
    render();
 
}

observer(data);

4.VUE的相关指令

(1) v-pre

  • 跳过这个元素和它的子元素的编译过程。可以用来显示原始 Mustache 标签。跳过大量没有指令的节点会加快编译。
    
    <span v-pre>{{ msg }}span>
    

(2)v-cloak

  • 这个指令保持在元素上直到关联实例结束编译

  • 可以解决闪烁的问题

  • 和 CSS 规则如 [v-cloak] { display: none } 一起用时,这个指令可以隐藏未编译的 Mustache 标签直到实例准备完毕

    [v-cloak] {
      display: none;
    }
    
    
    <div v-cloak>
      {{ message }}
    div>
    

(3)v-once

  • 只渲染元素一次。随后的重新渲染,元素及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能
    
    <span v-once>{{msg}}span>
    
    <div v-once>
      <h1>commenth1>
      <p>{{msg}}p>
    div>
    

(4)v-text

  • 更新元素的 textContent
    <span v-text="msg">span>
    
    <span>{{msg}}span>
    

v-text VS Mustache

  • v-text替换元素中所有的文本,Mustache只替换自己,不清空元素内容
  • v-text 优先级高于 {{ }}

(5)v-html

  • 更新元素的innerHTML
  • 注意:内容按普通 HTML 插入,不会作为 Vue 模板进行编译
  • 在网站上动态渲染任意 HTML 是非常危险的,因为容易导致 XSS 攻击。只在可信内容上使用 v-html,永不用在用户提交的内容上。

(6)条件渲染指令v-if、v-else、v-else-if、v-show

①v-if

  • 用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 truthy 值的时候被渲染。

切换多个元素

  • 因为 v-if 是一个指令,所以必须将它添加到一个元素上,但是如果想切换多个元素呢?此时可以把一个