vue3入门

81 阅读4分钟

1 setup函数

  1. 组件中所有的数据、方法均写在setup函数中
  2. 数据和方法直接定义在setup中,不在需要data,methods
  3. setup返回值如果是一个对象,可以在模版中直接使用,还可以返回一个渲染函数
  4. 尽量不要跟vue2混用,vue2可以访问vue3setup中的配置,vue3不能访问vue2的配置,如果冲突以vue3为主
  5. setup不能是async函数 ex:(下面写法会失去响应式)
setup(){
    let a = 111
    let b = 222
    function sayHello(){
        console.log(111)
    }
    return {
        a,
        b,
        sayHello
    }
}

注意点:

  • setup执行时机比beforeCreate快,this是undefined
  • setup接受2个参数(props,context)
  • 1 props:值为对象,包含:组件外部传递过来且组件内部声明接收了的属性
  • 2 context:上下文对象

2 ref函数

ref函数是帮助数据响应式,拿到的是一个ref引用对象,注意这种写法需要属性.value获取值,模版中直接用不需要.value,对象形式:obj.value.属性名获取值。ref对于基本类型通过Object.defineProperty(),get,set实现响应式,对于引用类型通过proxy处理。

setup(){
    let a = ref(111)
    let b = ref(222)
    let c = ref({
        name:'张三',
        age:18
    })
    function sayHello(){
       a.value = 456
       c.value.name='李四'
    }
    
    return {
        a,
        b,
        sayHello
    }
}

3 reactive函数

reactive只对引用类型有效,不能处理基本类型,返回一个代理对象(proxy对象),直接可以通过obj.属性名拿到值。

4 回顾vue2响应式原理

  1. 对象
  • 通过Object.defineProperty()对属性读取修改进行拦截(数据劫持)
  1. 数组
  • 通过重写更新数组的一系列方法进行拦截(包裹数组更新方法)

存在问题

  • 新增属性,删除属性界面不会更新
  • 直接通过下标修改数组界面不会更新
Object.defineProperty(data,index,{
    get(){},
    set(){}
})

5 vue3响应式原理

  1. 通过proxy(代理):拦截对象中任意属性变化,包括属性读写,添加,删除等。
  2. 通过Reflect(反射):对代理对象属性进行操作。
let person = {
    name:'章三',
    age:18
}
const p = new Proxy(person,{
    //读取属性时调用
    get(target,propName){ 
        // target=>person对象 propName=>属性名
        return Reflect.get(target,propName)
    },
    //修改/追加 某个属性时调用
    set(target,propName,value){ 
        // value=>修改后的值
        Reflect.set(target,propName,value)
    }
    //删除某个属性时调用
    deleteProperty(target,propName){ 
        return Reflect.deleteProperty(target,propName)
    }
})

6 reactive与ref对比

  1. 定义数据角度
  • ref用来定义基本数据类型,reactive用来定义对象(数组)类型数据。ref也可以用来定义对象(数组)类型数据,内部会通过reactive转为代理对象 2 原理角度
  • ref通过Object.defineProperty()get,set实现响应(数据劫持)
  • reactive通过Proxy(数据劫持),并通过Reflect来操作原对象内部的数据 3 使用角度
  • ref定义数据,操作需要.value,在模版中直接使用
    1. reactive操作与读取均不需要.value

7 computed函数 && watch函数

computed:

setup(){
    
   const person = {
       firstName:'张',
       lastName:'三'
   }
   person.fullName = conputed(() => `${firstName}${lastName}` )
    
    return {
        person,
    }
}

watch:

setup(){
    const person = {
       name:'张',
       age:18
   }
   const str = ref('hello')
   const num = ref(0)
   //监听一个值
   wtach(num,(newVal,oldVal) => {
       console.log(newVal)
   })
   //监听多个值
   wtach([num,str],(newVal,oldVal) => {
       console.log(oldVal) // [0,'hello']
   })
   //第三个参数 配置项
   wtach([num,str],(newVal,oldVal) => {
       console.log(oldVal) // [0,'hello']
   },{immediate:true})
    return {
        num,
        str,
        person
    }
}

注意:

  • 1 watch监听一个reactive定义的对象类型,目前没办法拿到正确的oldvalue。
  • 2 强制开启深度监听(deep属性无效,reactive监听一个对象的情况)( 如果监听的是一个对象中的某个属性,deep生效)
  • 3 如果想监听对象中的某个属性,第一个参数写成函数并把这个属性作为返回值返回即可
wtach(()=>person.age,(newVal,oldVal) => {
      //此写法监听age属性并且oldvalue不受影响
   })

  • 4 监听对象中的多个属性,第一个参数的回调返回值写在数组里
  • 5 watch在监听基本类型数据时,不需要.value。在监听用ref监听的对象时,需要.value.属性名(这时监听的不再是ref定义的数据,而是ref求助reactive所定义的数据)或直接监听obj.value或这开启deep:true。

watchEffect函数

  • watchEffect不用指明监听哪个属性,只要在回调函数中用到的属性都会监听。类似于computed,但computed更注重计算出的值,watchEffect更注重逻辑。

vue3生命周期

vue3可以继续使用vue2的生命周期钩子,但是有两个改名了

  • beforeDestory => beforeUnmount
  • destoryed => unmounted vue3也提供了组合式api形式的生命周期钩子
  • beforeCreate => setup()
  • created => setup()
  • beforeMount => onBeforeMount
  • mounted => onMounted
  • beforeUpdate => onBeforeUpdate
  • updated => onUpdated
  • beforeDestroy => onBeforeUnmount
  • destroyed => onUnmounted
  • activated => onActivated
  • deactivated => onDeactivated

toRef和toRefs

toRef与toRefs把数据变为响应式数据

  setup() {
    // toRefs
    // const money = ref(100)
    // const car = reactive({
    //   brand: '宝马',
    //   price: 1000000
    // })
    // const name = ref('zs')

    const state = reactive({
      money: 100,
      car: {
        brand: '宝马',
        price: 1000000
      },
      name: 'zs'
    })

    return {
      // money,
      // car,
      // name
      ...toRefs(state) //ES6扩展运算符,会取消双向数据绑定的特性,使用toRefs(),转为响应式数据
    }
  }

toRaw和markRaw

  • 我们更新数据不需要改变界面,就可以用toRaw和markRaw
  • toRaw将一个reactive生成的响应式对象转为普通对象(不支持)
  • markRaw会将一个对象永远变成不是响应式的对象 customRef用来自定义一个响应式数据

5905FA22-EC2A-4DAC-B71F-A6942EFB0AF3.png