• Vue3 Composition API(案例)


    前言:如果你是从vue2转到vue3的一份子,那么你重点学一下核心内容Composition API 。vue3的更新使代码写起来更加清晰,而且更接近于原生开发,对TS支持友好,现在我们来学习一下API。

    如果你也想学一下TS那么请看这里 带你学习语法Typescript

    setup api

    setup(props,context){
      // 不可以通过this获取所以要通过参数获取
      console.log(props.message)
      console.log(context.attrs.id + ' ' + context.attrs.class)
      console.log(context.emit)
      console.log(context.slots)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    返回值return{ }可以代替 data(){}可以在模板中直接引用

    setup()函数里可以写函数 可以代替methon{} 写方法

    reactive

    // 响应式方法一
    
    // const state = reactive({
    //   title: 'hello kun',
    //   content: 100
    // })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    ref

    // 响应式方法二 挂载后可以直接在template中引用,不需要.value,vue自动解包为你省了一步
    // 但是下面方法里依然还是要.value的
    //template中浅层的解包,如果嵌套了不能解包。但是reactive中嵌套可以解包,但是我们不建议这么做
    const title = ref('hello kun')
    const content = ref(100)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    readonly

    一个proxy的set方法被劫持,可以传用但是不能修改,返回只读的代理

    1,普通对象

    无法响应式,比如我们可以传入到子组件,子组件无法修改但是无法做到响应式

    2,传入reactive对象

    子组件不能改,但是是响应式的,可以在这里改state1 或者ref的state3
    const state1 = reactive({
      name:'kun',
      height:1.88
    })
    const state2 = readonly(state1)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3, 传入ref对象

    const state3 = ref("why")
    const state4 = readonly(state3)
    
    • 1
    • 2

    了解:reactive判断的api

    isproxy

    检查对象是否是由 reactive 或 readonly创建的 proxy

    isReactive

    检查对象是否是由 reactive创建的响应式代理:

    如果该代理是 readonly 建的,但包裹了由 reactive 创建的另一个代理,它也会返回 true;

    isReadonly

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

    toRaw

    返回 reactive 或 readonly 代理的原始对象(建议保留对原始对象的持久引用。请谨慎使用)。

    shallowReactive

    创建一个响应式代理,它跟踪其自身 property 的响应性,但不执行嵌套对象的深层响应式转换 (深层还是原生对象)。

    shallowReadonly

    创建一个 proxy,使其自身的 property 为只读,但不执行嵌套对象的深度只读转换(深层还是可读、可写的)。

    torefs

    对reactive返回的对象进行解构获取的值,那么无论是修改结构后的变量,还是修改reactive返回的state对象,数据都不是响应式的,

    vue提供了各函数torefs,可以将reactive返回的对象中的属性都转成ref

     const state = reactive({
          name:'zlk',
          age:18
        })
        let {name,age} = toRefs(state);
        const btnclick = () => {
          // state.name = 'kun'
          name.value = 'kun'
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    state.name和name.value建立链接,任何一个修改都会变化

    toref

    如果我们只希望转换一个属性为ref,而不是整个reactive对象,可以使用toref方法

    const state = reactive({
      name:'zlk',
      age:18
    })
    const name = toRef(state,'name')
    const {age} = state;
    
    const btnclick = () => {
      // state.name = 'kun'
      name.value = 'kun'
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    ref其他api

    const info = shallowRef({name:'kun'})
    
    const btnclick = () => {
      info.value.name = 'feiji'
      triggerRef(info)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    shallowRef浅层ref,未响应式

    triggerRef手动触发后,响应式了

    customRef

    <template>
    <div>
      <input v-model="message">
      <h3>{{message}}</h3>
    </div>
    </template>
    
    
    const message = ref('hello');
    return{
      message
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    这是普通双向绑定,

    我们来自定义一个ref,做防抖

    import {customRef} from "vue";
    
    export function useref(value,delay = 1000){
        let timer;
        return customRef((track, trigger) => {
            return{
                get(){
                    track(); // 收集依赖
                    return value 
                },
                set(newvalue){
                    clearTimeout(timer)  // 防抖
                    timer = setTimeout(() => {
                        value = newvalue  //赋值
                        trigger(); //更新模板依赖
                    },delay)
                }
            }
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    computed

    方式一:接收一个getter函数,并为 getter 函数返回的值,返回一个不变的 ref 对象

    setup(){
      let first = ref("kun");
      let last = ref("ba");
      let haha = 'nihao'
      const fullName = computed(() => {
        return first.value + ' ' + last.value
      })
      return{
        first,
        last,
        fullName,
        haha
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    方式二:接收一个具有 get 和 set 的对象,返回一个可变的**(可读写)ref 对象**;

    setup(){
      let first = ref("kun");
      let last = ref("ba");
    
    
      let fullName = computed({
        get:() => {
          return first.value + ' ' + last.value
        },
        set:(newvalue) => {
          const names = newvalue.split(" ");
          first.value = names[0];
          last.value = names[1];
        }
      })
    
      const btnclick = () => {
        fullName.value = "coder kun"
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    watchEffect

    watchEffect传入的函数会被立即执行一次,并且在执行的过程中会收集依赖;

    只有收集的依赖发生变化时,watchEffect传入的函数才会再次执行;

    const name = ref("hello")
    const age = ref("18")
    
    watchEffect(() => {
      console.log("watcheffect",name.value,age.value)
    })
    const btnclick = () => {
      name.value = "hi"
      age.value = 23
    }
    return{
      name,
      age,
      btnclick
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    watchEffect的停止侦听

    setup(){
      const name = ref("hello")
      const age = ref("18")
    
     const stop = watchEffect(() => {
        console.log("watcheffect",name.value,age.value)
      })
      const btnclick = () => {
        // name.value = "hi"
        // age.value = 23
        age.value++;
        if (age.value > 25){
          stop();
        }
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    这个时候我们可以获取watchEffect的返回值函数,调用该函数即可。

    watchEffect清除副作用

    setup中使用ref

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MkkYrxak-1669985503691)(C:\Users\jia\AppData\Roaming\Typora\typora-user-images\image-20221004012044488.png)]

    watchEffect的执行时机

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u1XWWW8P-1669984040392)(C:\Users\jia\AppData\Roaming\Typora\typora-user-images\image-20221004012322694.png)]

    setup(){
      const name = ref("zlk");
      const age = ref(18);
      const titleref = ref(null)
      const stopwatch = watchEffect(() => {
        console.log(titleref.value)
      },{
        flush:"post"
      })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    调整watchEffect的执行时机

    {
    flush:“post”
    }

    Watch的使用

    单个数据源监听

    一个getter函数:但是该getter函数必须引用可响应式的对象(比如reactive或者ref);

    直接写入一个可响应式的对象,reactive或者ref(比较常用的是ref);

    ref

    // const name = ref('zlk')
    // const age = ref(18)
    
    // watch(name , (newname,oldname) => {
    //   console.log(newname,oldname)
    // })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    reactive

    // const state = reactive({
    //   name:'zlk',
    //   age:18
    // })
    // watch(() => state.name, (newname,oldname) => {
    //   console.log(newname,oldname)
    // })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    侦听器还可以使用数组同时侦听多个源

    // watch([name,age], (newname,oldname) => {
    //   console.log(newname,oldname)
    // })
    
    • 1
    • 2
    • 3

    侦听一个数组或者对象 ,使用一个getter函数,并且对可响应对象进行解构

    // const names = reactive(["abc","bnm","nba"])
    // watch(() => [...names],(newvalue,oldvalue) => {
    //   console.log(newvalue,oldvalue)
    // })
    
    • 1
    • 2
    • 3
    • 4

    侦听一个深层的侦听,那么依然需要设置 deep 为true:

    p也可以传入 immediate 立即执行;

    声明周期钩子

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZVomp9Jc-1669984040402)(C:\Users\jia\AppData\Roaming\Typora\typora-user-images\image-20221006145743691.png)]

    setup(){
      const content = ref(0);
      console.log("开始创建组件")
      onMounted(() => {
        console.log("onMounted-组件挂载到页面之后")
      })
      onBeforeMount(() => {
        console.log("onBeforeMount-组件挂载到页面之前")
      })
      onUpdated(() => {
        console.log("onUpdated-组件更新之后")
      })
      onActivated(() => {
        console.log("onActivated")
      })
      onUnmounted(() => {
        console.log("onUnmounted")
      })
      onBeforeUpdate(() => {
        console.log("onBeforeUpdate-组件更新之前")
      })
      const btnclick = () => {
        content.value++;
      }
      return{
        content,
        btnclick
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    created 和 beforecreate直接在setup里面写就可以了,vue3取消了,例如之前我们请求数据在created中请求,现在可以直接在setup里面写axios代码不用函数包裹调用

  • 相关阅读:
    .NET 6使用ImageSharp给图片添加水印
    NPM 使用入门
    @Transactional 注解使用详解
    Hive之grouping sets用法详解
    产品经理这个背锅侠
    C/C++|基于回调函数实现异步操作
    【git】Git 指令统计代码行数
    一款.NET开源的i茅台自动预约小助手
    oracle21c报错 【ORA-65096: 公用用户名或角色名无效】
    c语言的基本类型有哪些
  • 原文地址:https://blog.csdn.net/weixin_44600810/article/details/128154125