• vue3学习笔记


    在Vue3.0中创建响应式数据需要引用ref,reactive这两个方法,ref一般用来创建基本数据类型的响应式数据,reactive一般用来创建引用数据类型的响应式数据。
    在模板中使用,跟之前没有区别,需要注意的是,ref属于将基本类型数据包装成应用类型,在模板中正常使用。在方法中访问的时候需要带上.value才能访问到。
    为什么要这么写呢?是因为Proxy的原因,Proxy要进行数据劫持的时候需要接收一个对象,所以ref就对基本数据类型的数据进行了包装,使其可以进行响应式。
     
    ref例子:
    <template>
      <div>
        {{ count }}
        <button @click="add">+</button>
      </div>
    </template>
    
    <script>
    import { ref } from "vue";
    
    export default {
      /* 在Vue3.0中创建响应式数据需要引用ref,reactive这两个方法,ref一般用来创建基本数据类型的响应式数据,reactive一般用来创建引用数据类型的响应式数据。
    在模板中使用,跟之前没有区别,需要注意的是,ref属于将基本类型数据包装成应用类型,在模板中正常使用。在方法中访问的时候需要带上.value才能访问到。为什么要这么写呢?是因为Proxy的原因,Proxy要进行数据劫持的时候需要接收一个对象,所以ref就对基本数据类型的数据进行了包装,使其可以进行响应式。 */
    
      name: "Test",
      setup(props, context) {
        const count = ref(0); // 定义响应式数据count
        const objData = {
          name: "erha",
          age: "1",
          skill: "拆家",
        };
        const add = ()=>{
          count.value++;  
        }
        return {
          count,
          add,
        };
      },
    };
    </script>
    由于Proxy的机制原因,如果将reactive中的响应式数据进行解构,那么原先的响应式数据就变成不可响应的了。 
    为什么将可观察对象中的属性解构出来后,变成不再可观察了呢?因为通过reactive方法创建的可观察对象,内部的属性本身并不是可观察的,而是通过Proxy代理实现的读写观察,如果将这些属性解构,这些属性就不再通过原对象的代理来访问了,就无法再进行观察。
    Composition API提供了一种方法来解决此机制带来的问题,那就是toRefs,它可以将reactive创建的可观察对象,转换成可观察的ref对象
    当使用了toRefs的时候在模板中只需要使用name即可
    <template>
      <div>
        <!-- {{ data.age }} -->
        {{age}}
      </div>
    </template>
    
    <script>
    import { reactive, toRefs } from "vue";
    
    export default {
      /* 由于Proxy的机制原因,如果将reactive中的响应式数据进行解构,那么原先的响应式数据就变成不可响应的了。 为什么将可观察对象中的属性解构出来后,变成不再可观察了呢?因为通过reactive方法创建的可观察对象,内部的属性本身并不是可观察的,而是通过Proxy代理实现的读写观察,如果将这些属性解构,这些属性就不再通过原对象的代理来访问了,就无法再进行观察。Composition API提供了一种方法来解决此机制带来的问题,那就是toRefs,它可以将reactive创建的可观察对象,转换成可观察的ref对象 */
    //   当使用了toRefs的时候在模板中只需要使用name即可
    
      name: "Test",
      setup(props, context) {
        const data = reactive({
          name: "lisa",
          age: 18,
        });
        let { name , age} = toRefs(data)
        // data.age = 20; //响应式
        // age = 30; //非响应式
        data.age = 30; //也是响应式
        return {
        //   data,
        ...toRefs(data)
        };
      },
    };
    </script>

    Composition API提供的computed方法就相当于2.x版本中的计算属性。使用如下:

    <template>
      <div>
        {{ count }}
        {{ doubeCount }}
      </div>
    </template>
    
    <script>
    import { ref, computed } from "vue";
    
    export default {
      /* Composition API提供的computed方法就相当于2.x版本中的计算属性。 */
    
      name: "Test",
      setup(props, context) {
        const count = ref(2);
        const doubeCount = computed(() => {
          return count.value * 2;
        });
    
        return { count, doubeCount };
      },
    };
    </script>

    Composition API提供的watch方法相当于就是2.x的观察属性。

    watch方法接收两个参数,第一个参数是一个函数,第二个参数也是个函数,第一个参数函数返回值表示要监听哪个数据,第二个参数函数,表示监听成功后的逻辑,该函数的第一个参数就是监听到目标数据变化后的值。同时watch可以监听多个数据。

    使用如下:

    <template>
      <div class="test">
        <div>watch: count+num:{{ countAddNum }}</div>
        <button @click="addCount">点击+1</button>
      </div>
    </template>
    
    <script>
    import { ref, computed, watch } from "vue";
    export default {
      /* watch方法接收两个参数,第一个参数是一个函数,第二个参数也是个函数,第一个参数函数返回值表示要监听哪个数据,第二个参数函数,表示监听成功后的逻辑,该函数的第一个参数就是监听到目标数据变化后的值。同时watch可以监听多个数据。 */
      name: "Test",
      setup() {
        const count = ref(0); // 定义响应式数据count
        const num = ref(1); // 定义响应式数据num
    
        const countAddNum = computed(() => {
          // 计算属性
          return count.value + num.value;
        });
        // 相当于watch
        watch(
          [() => count.value, () => num.value],
          ([count, num], [oldCount, oldNum]) => {
            // watch 同时观察count和num两个值
            console.log(
              `count:${count},num:${num} oldCount:${oldCount},oldNum:${oldNum}`
            );
          }
        );
        watch(
          () => {
            return count.value;
          },
          (newcount) => {
            console.log("count变啦", newcount);
          }
        );
        // 相当于methods
        const addCount = () => {
          // 定义增加count方法
          count.value++;
        };
    
        // 统一return出去
        return {
          count,
          num,
          addCount,
          countAddNum,
        };
      },
    };
    </script>
    在Vue2.x版本中频繁出现的this,在Vue3.0中也消失了,取而代之的是Composition API提供的getCurrentInstance方法,用来获取当前组件实例,然后通过ctx获取当前上下文。
    下面是路由跳转的例子:
    <template>
      <button @click="pushRoute">push</button>
    </template>
    
    <script>
    import { getCurrentInstance } from "vue";
    
    export default {
      name: "Test",
      setup(props, context) {
        const { ctx } = getCurrentInstance();
        console.log(ctx);
        const pushRoute = () => {
          // 编程导航
          ctx.$router.push({
            path: "/",
          });
        };
        return {
          pushRoute,
        };
      },
    };
    </script>
     
     
    最后看一下Vue3.0中的生命周期,生命周期也是有所改动,钩子函数名称均发生变化。
    beforeCreate,created生命周期在setup方法中自动执行,其余生命周期钩子函数都是从Vue中引入使用(注意在setup方法中使用)
    <template>
      <div>
        <h1>{{ msg }}</h1>
        <div>{{ a }}</div>
        <button @click="setA">加A</button>
      </div>
    </template>
    <script>
    import {
      ref,
      onBeforeMount,
      onMounted,
      onBeforeUpdate,
      onUpdated,
      onBeforeUnmount,
      onUnmounted,
      onErrorCaptured,
      onRenderTracked,
      onRenderTriggered,
    } from "vue";
    export default {
      setup(props, context) {
        // console.log(props.msg, context)
        const a = ref(0);
        const setA = () => {
          return a.value++;
        };
        // 相当于 beforeMount
        onBeforeMount(() => {
          console.log("onBeforeMount");
        });
        // 相当于 mounted
        onMounted(() => {
          console.log("onMounted");
        });
        // 相当于 beforeUpdate
        onBeforeUpdate(() => {
          console.log("onBeforeUpdate");
        });
        // 相当于 updated
        onUpdated(() => {
          console.log("onUpdated");
        });
        // 相当于 beforeDestroy
        onBeforeUnmount(() => {
          console.log("onBeforeUnmount");
        });
        // 相当于 destroyed
        onUnmounted(() => {
          console.log("onUnmounted");
        });
        onErrorCaptured(() => {
          // 错误监控 参考文章 https://zhuanlan.zhihu.com/p/37404624
          console.log("onErrorCaptured");
        });
        onRenderTracked(() => {
          // 已渲染
          console.log("onRenderTracked");
        });
        onRenderTriggered(() => {
          // 当组件更新时会首先触发此生命周期钩子 onRenderTriggered->onRenderTracked->onBeforeUpdate->onUpdated
          console.log("onRenderTriggered");
        });
        return {
          a,
          setA,
        };
      },
      name: "HelloWorld",
      props: {
        msg: String,
      },
    };
    </script>

     参考:https://www.jianshu.com/p/b6ec99ff1cb5

  • 相关阅读:
    在阿里云服务器(ECS)上从零开始搭建nginx服务器
    HTML5和CSS3新特性一览
    【react】---手动封装一个简易版的redux
    【react】---17新增的生命周期
    vue单页面应用刷新网页后vuex的state数据丢失的解决方案
    [VUE]object.defineProperty的基本使用
    JavaScript / 本地存储
    转载--httpclient原理和应用
    关于mybatis mapper.xml中的if判断
    idea maven install时,打包找不到微服务common中公用的包
  • 原文地址:https://www.cnblogs.com/jervy/p/14081323.html
Copyright © 2020-2023  润新知