全面拥抱vue3.0

vue2.0和vue3.0的区别

  • 重写了虚拟DOM的实现(跳过静态节点,只处理动态节点)。
  • update性能提高1.3~2倍。
  • SSR(服务处理)速度提高了2~3倍。
  • 可以将无用的模块剪辑,仅打包需要的(按需打包)。
  • 不在限于模板中的单个根节点。
  • 更好的typeScript支持。
  • 组合式API(setup)替换原有的OptionsAPI
    • 根据逻辑相关性组织代码,提高可读性和可维护性
    • 更好的重用逻辑代码(避免mixins混入时命名冲突的问题)
    • 但是依然可以沿用Options
    //Options API
    export default {
        data() {
            return{
            
            }
        },
        methods:{
        
        },
        computed:{
        
        }
    }
    
    //组合式API
    export default {
        setup(){
        
        }
    }
    复制代码

如何创建vue3.0项目

基于vue/cli配置vue3.0

  • vue/cli脚手架必须是4.3.1版本以上
  • 使用创建项目命令vue create 项目名
  • 最后加上vue add vue-next,创建3.0的项目

基于vite配置vue3.0

  • 有尤雨溪开发的web开发工具,基于浏览器原生ES imports的开发服务器(利用浏览器解析imports,在服务器端按需编译返回,完全跳过了打包这个概念,服务器随起随用),同时不仅有vue文件的支持,还搞定了热更新,而且热更新的速度不会随着模块增多而变慢。
  • npm init vite-app 项目名
  • cd 项目名
  • npm i
  • npm run dev

掌握setup和响应式系统API

响应式系统工具集

ref

  • 接收一个参数值并返回一个响应式且可改变的ref对象。
    • ref对象拥有一个指向内部值的一个属性.value
    • 当ref在模板中使用的时候,他会自动解套,无需在模板内部额外写.value(意思是return出来以后,用小胡子就可以直接使用)
    • ref不是Proxy实现的。

unref

  • 如果参数是一个ref,则返回它的value值,否则返回参数本身,他是val = isRef(val)? val.value:val的语法槽
let a = '你好',
b = ref(2)
console.log(unref(a,b)) //'你好',2
复制代码

toRef

  • 将参数转化为ref对象,例如
    let a = 0;
    console.log(toRef(a)) //ObjectRefImpl {_object: 0, _key: undefined, __v_isRef: true}
    复制代码

toRefs

  • 把响应式对象转为普通对象,该普通对象每一个property都是一个ref,和响应式对象property一一对应。

isRef

  • 判断该值是否为ref对象,如果是则返回true,否则是false
        let a = 0
        console.log(isRef(a)) // false
    复制代码

isProxy

  • 检查一个对象是否由reactive或者readonly方法创建的代理

isReactive

  • 检查一个对象是否由reactive创建的响应式代理。
    • 如果这个代理是由reactive创建的,但是又被reactive创建的另一个代理包裹了一层,那么同样会返回true

isReaonly

  • 检查一个对象是否由readonly创建的只读代理。

readonly

  • 传入一个对象(响应式或者普通)或ref,返回一个原始对象的只读代理,一个只读的代理是深层的,对象内部任何嵌套的属性也只是只读的。

高级系统响应式API

customRef

computed

  • 传入一个getter函数,返回一个默认不可手动修改的ref对象。
// 第一种写法:不可手动修改值
setup() {
   let a =  computed(()=>{
       let total = state.supNum + state.oppNum
       return ((state.supNum/total)*100).toFixed(2) + '%'
   })
   return{
       a
   }
}

//第二种写法:可以利用set修改,当a所依赖的值supNum和oppNum改变会触发get回调函数,如果修改a的值会触发set回调函数(a.vlue = a.vlue+1就会触发)
setup() {
   let a =  computed({
   get:()=>{
       let total = state.supNum + state.oppNum
       return ((state.supNum/total)*100).toFixed(2) + '%'
   }
   set:(val)=>{
       console.log(val,222)
   }   
   })
   return{
       a
   }
}

复制代码

watchEffect

  • 立即执行传入的一个函数,并响应式追踪其依赖,并在其依赖变更时重新运行该函数。
    setup(props){
        watchEffect(()=>{
            console.log(props.title)//第一次渲染的时候就会立即执行一次
        })
        let y = ref(0),
        z = ref(0);
        //如果需要监听多个值
        watchEffect(()=>{
            console.log(y.value,z.value)//必须写value值,因为咱们监听的是value值,不是y的ref对象
        })
    }
    复制代码

watch

  • watch完全等价于2.0的watch
    • watch需要侦听特定的数据源,并在回调函数中执行。
    • 默认情况是懒执行的,也就是说仅在侦听的源变更时才执行回调。第一次加载页面是不执行的,和watchEffect不一样。
    //侦听单个数据
    setup(){
    watch(state,()=>{
        console.log(state.supNum)
    })
    //侦听state下的某个数据
    watch(()=>state.supNum,()=>{
        console.log('你好'+state.supNum)
    })
    //侦听ref创建的响应式数据,输出改变后的值和之前的值
    let x = ref(0)
    setup(){
        watch(x,(x,prevX)=>{
            console.log(x,prevX)
        })
    }
    //侦听多个数据用数组传参,数组中任意值改变都会触发watch函数
    watch([x,y],([x,y],[prevx,prevy]=>{
        console.log(x,y,prevx,prevy)//prevx,prevy改变之前的值
    }))
    复制代码

watchEffect和watch的区别

  • 不需要手动传入依赖值。
  • 每次初始化时会执行一次回调函数来获取依赖值。
  • 无法获取原值,只能获取改变后的值。

setup

  • setup函数是一个新的组件选项,作为在组件内使用的CompositionAPI的入口点。
    • 初始化props和beforeCreate之间调用
    • 可以接收props和context
    • this在setup中不可用,因为实在beforeCreate之前执行的,这时候还没有创建this实例。
  • setup(props)
    • props是基于Proxy代理的响应数据
  • setup语法
    setup(){
        //return出去的值可以直接在html中使用,{
         
         {num}}
        return{
        
        }
    }
    复制代码

构建响应式数据

方法一,利用ref,一般处理简单值的响应式

  • 原理还是基于defineProperty监听value值
<template>
  <div>
    <h3>{
   
   { title }}</h3>
    <div>
      <p>支持人数:{
   
   { supNum }}</p>
      <p>反对人数:{
   
   { oppNum }}</p>
      <p>支持率:</p>
      <button @click="change(0)">支持</button>
      <button @click="change(1)">反对</button>
    </div>
  </div>
</template>

// 第一种直接使用ref,比较麻烦
setup() {
    let supNum = ref(0),
    oppNum = ref(0);
    functiom change(x){
        x == 0? supNum.value++:oppNum.value++
    }
    return{
        supNum,
        oppNum,
        change,
    }
}

// 第二种ref,创建一个ref对象
setup(){
    let state = ref({
        supNum:0
        oppNum:0
    })
    function change(x){
        x == 0? state.value.supNum++ : state.value.oppNum++
    }
    return{
        state
    }
//html在使用的时候,{
   
   {state.supNum}}
}
复制代码

方法二,利用 reactive

  • 基于Proxy对数据进行深度的监听,以此构建响应式
    • 接收一个普通对象然后返回该普通对象的响应式代理
    • 响应式转换是深层的,会影对象内部所有嵌套的属性
setup() {
    let state = reactive({
       supNum: 0,
       oppNum; 0
    })
    function change(x){
        x == 0? state.supNum++ : state.oppNum++
        // 比Object.defineProperty好用在于,对与数据或者并未初始化的对象成员,都可以随意的改变值,而且具备响应式的数据。
    }
    return{
        ...toRefs(state),
        change
    }
    //html在使用的时候,{
   
   {supNum}}
}
复制代码

模板refs

<template>
  <div>
    <div ref="root">你好</div>
  </div>
</template>
export default {
setup(){
    let root = ref();
    onMounted(()={
        console.log(root.value) //返回值是div元素
    })
    return{
        root
    }
}
}
复制代码

生命周期函数

  • beforeCreate=>使用setup
  • create=>使用setup
  • beforeMount=>onBeforeMount 第一次挂载之前
  • mounted=>onMounted 第一次挂载之后
  • beforeUpdate=>onBeforeUpdate 组件更新之前
  • updated=>onUpdated 组件更新之后
  • beforeDestroy=>onBeforeUnmount 组件销毁之前
  • destoryed=>onUnmounted 组件销毁之后
  • errorCaptured=>onErrorCaptured

猜你喜欢

转载自blog.csdn.net/sqLeiQ/article/details/117249006