vue3 componsition API

329 阅读4分钟

Vue3.0 和 Vue2.0对比

Vue2和Vue3主函数不同

Vue2通过new Vue(),而且Vue3通过createApp来创建实例

  //一些细节上的差异:
  //vue2中vue实例中的响应式数据可以以对象的方式写入,vue3只能以函数的方式写
  var vue = new Vue({
    el:"#app",
    data:{
        name:'maple'
    }
  })
  // vue3
   let app = Vue.createApp({ 
   //这样写会报错
   //dataOptions.call is not a function
      data: {
        name: "张三",
        age: 20,
      },
    });
    app.mount('#app')

挂载

// vue3中并没有el选项,必须通过mount实现组件的挂载(地址:jsbin.com/koqeteqini/…) // vue2可以通过el$mount挂载组件,如果两者出现el的优先级更高

//vue3
 let app = Vue.createApp({
     el:"#app",   //页面渲染的name并不会生效
 });
 app.mount('#app')

响应式

  1. Vue2.0没有在定义的时候添加响应式,那么那面想要响应式的话,需要通过Vue.set来添加响应式数据 链接,通过Vue.delete来删除响应式数据
var vue = new Vue({
  el: "#app",
  data() {
    return {
      obj: {},
    };
  },
  created() {
  // 给数据添加响应式
    Vue.set(this.obj, "age", 11);
  },
  methods: {
    add() {
      this.obj.age++;
    },
  },
});

如果是数组,那么通过数组的7个API也可以更改响应式数据。pushpopreverseshiftunshiftsortsplice

  1. vue3响应式处理:

消除了当前 Vue 2 系列中基于 Object.defineProperty 所存在的一些局限,这些局限包括:1 对属性的添加、删除动作的监测; 2 对数组基于下标的修改、对于 .length 修改的监测; 3 对 Map、Set、WeakMap 和 WeakSet 的支持

ref和reactive的使用

ref在事件处理函数中要加上.value来修改对象上的属性,在模板中使用不需要 ref一般用于简单数据类型,ref在复杂数据类型上不太好用。reactive一般用于复杂数据类型数据

let person = ref({
    name:'小王',
    age:11
})
let updateAge = ()=>{
    person.value.age ++
    }
}
{{person.name}}

Vue3写法 computed、watch

区别:

  1. computed是通过多个值得到一个结果,watch不会得到值,并且可以得到新值和旧值
  2. computed是有缓存的,watch没有缓存
let stu = reactive({
    name:"laowang",
    age:11
})
//监听对象,默认开启深度监听(设置deep不起作用)
watch(stu,(newVal,oldVal)=>{
    console.log(111)
    if(newVal.age>20){
        alert("年龄太大")
    }
},{
    //
    deep:true,
    immediate:true
})

//如果监听对象的一个属性,建议使用下面这种
watch(()=>stu.age,(newVal,oldVal)=>{
    console.log(111)
    if(newVal>20){
        alert("年龄太大")
    }
},{
    deep:false,
    immediate:true
})

computed写法

let firstName = 'wang'
let lastName = ' feng'
//定义不可读的写法
let fullName = computed(()=>firstName+lastName)
//定义可读的计算属性
let fullName = computed({
  get(){
    return firstName+' ' +lastName
  },
  set(val){
    firstName = val.split(' ')
    console.log(firstName[2])
    return firstName[0] + firstName[2]
  }
})

watchEffect

watchEffect默认会执行一次,当值变化时会再次执行

let addAge = () =>{
    stu.age ++
}
let changeName = ()=>{
    stu.name = 'xiaowang'
}

//默认会打印一次`woshi`
//当name或者age任意值发生变化时会打印`woshi`
watchEffect(()=>{
    let name = stu.name
    let age = stu.age
    console.log('woshi') 
})

模块化

生命周期钩子函数

组合式生命周期钩子函数:onBeforeMountonMountedonbeforeUpdatedonUpdateonWillUnMountonUnMounted

toRef

用法:将一个reactive里面的成员转化成ref对象 toRef(reactiveObject,key)

let person = reactive({
    name:'laowang',
    age:11
})

let personRef = toRef(person,'name')

toRefs

用法:将一个reactive转化成ref对象

let person = reactive({
    name:'laowang',
    age:11
})

let personRef = toRefs(person)

//通常在返回的时候使用
...toRefs(person)

readOnly

传入一个对象(响应式对象或者普通)或者ref,对象的任意嵌套属性都是只读的

const car = readonly({
    name:"大众",
    color:'white',
    price:"3000",
    children:{
        age:111
    }
})
console.log(isReadonly(car))
car.children.age = 2   //警告

验证式api

  • isRef():判断是否是ref对象
  • isReactive():判断是否是reactive对象
  • isReadonly():判断是否是readonly对象
  • isProxy() :判断是否是proxy对象 (readonly和reactive都是)

shallowRef

let person = shallowRef({
  name: "xiaowang",
  age: 11,
});
let updateName = () => {
  //通过这种方式可以更新视图
  person.value = {
    name: "laowang",
  };
};
let updateAge = () => {
//通过这种方式不行
  person.value.age = 22;
};

shallowRef shallowReactive shallowReadonly

shallowRef:只能通过value修改数据

let p1 = shallowRef({
  name:'laowang',
  age:11
})
let updateAge = ()=>{
  p1.value = {
    name:"xiaowang",
    age:6
  }
}

这种方式并不能修改数据

let p1 = shallowRef({
  name:'laowang',
  age:11
})
let updateAge = ()=>{
  p1.value.age ++
}

shallowReactive:只能修改第一层的数据,深层的对象不能更改

let stu2 = shallowReactive({
  name:"往前",
  age:11,
  friend:{
    name:"BY2",
    age:20,
    car:{
      name:"奔驰",
      color:'red'
    }
  }
})
let updateAge = ()=>{
  stu2.age++
}
let updateFriend = ()=>{
  //数据已经发生变化,但是视图不更新
  stu2.friend.age++
  console.log(stu2)
}

shallowReadonly:不能修改第一层属性,当时修改深层的属性,但是不会更新视图

let p1 = shallowReadonly({
  name:"laowang",
  age:11,
  children:{
    name:"xiaowang",
    age:12
  }
})
let updateAge = ()=>{
  p1.name = "111"  
  console.log(p1)  //会有警告,第一层的name输出的依然是laowang
}

深层修改

let updateAge = ()=>{
  p1.children.age ++  
  console.log(p1)  //第二层的age会发生变化,但是并不会更新视图
}

toRaw

将一个代理对象转化成普通对象,这个普通对象就是原来的对象

let p1 = {
  name:"laowang",
  age:11
}
let p2 = reactive(p1)
let p = toRaw(p2)
console.log(p1 === p)

markRaw

会给对象添加一个属性__v_skip: true,添加后的该属性不能转化成响应式对象

let p1 = {
  name:"laowang",
  age:11
}
let p2 = markRaw(p1)
let p3 = reactive(p2)
console.log(p3)