本文主要讲解 Vue2 与 Vue3 的区别,帮助你在1小时内搞定Vue3使用.

关于 Vue2中的 data,computed,mounted…都有对应详解和小例子.

yarn install vue@3 vuex@4 vue-router@4

1. 核心:setup()

setup的意义: 在 vue3 中多了一个钩子函数 setup(),它最大得作用就是让你对模块的逻辑进行细化提取,以便于让你的组件更为通用,更容易封装,从而减少代码量。

setup() 是一个函数,首先需要把它当做一个普通的function setup(){...}, 在函数内可以写任何内容。

① setup()中的this如何使用?

在 setup() 函数内部,官方为了防止开发者误用 this,直接将 this 设置为 undefined,通过 console.log(this)可以验证.

setup() {
  console.log(this); // undefined
}

既然 setup()中没有了 this, 那么像以前那样 this.$router.push(), this.$refs.dom 等等方法和属性该如何使用呢?

官方早已想到了这一点,将 route ,refs 这样原本绑定在 this 的对象都专门提取了出来,所以使用方法变为了 三步走(麻烦了不少):

  • 1. 引入对象
  • 2. 使用对象
  • 3. 返回该对象
<template>
  <div ref="test">test content</div>
</template>;
import { ref } from "vue";
import { useRoute } from "vue-router"; // 1.引入
export default {
  setup() {
    const route = useRoute(); // 2.使用
    let testRef = ref("test");
    let anyObject;

    return {
      route, // 3.返回
      testRef,
    };
  },
};

tips: 这里有个小细节一定要注意, setup() 中一定不能返回 undefined, 比如上面的对象 anyObject 只进行了申明,没有赋值,那么他默认就是undefined,一定不能返回。 一旦不小心返回了 undefined,你的代码就无法运行了,关键是很难定位到错误在哪

export default {
  setup() {
    let anyObject;
    return {
      anyObject, // 错误!!不能返回任何undefined
    };
  },
};

② setup的在vue生命周期的定位

setup 在生命周期中,运行于 created 和 beforeCreated 之前, 作用就是代替 created 和 beforeCreated。也就是说在 vue2 中使用 created 和 beforeCreated 的地方,使用 setup() 即可

vu3.0 同样把生命周期也提取了出来,并给了个名字:hooks(钩子函数)

所以在 setup 中可以访问这些生命周期的 hooks :onBeforeMount,onMounted,onBeforeUpdate,onUpdated,onBeforeUnmount,onUnmounted,onErrorCaptured,onRenderTracked,onRenderTriggered,例如:

import { onMounted } from "vue";
export default {
  setup() {
    // setup中生命周期使用示例
    onBeforeMount(() => {
      console.log("setup中访问生命周期 onBeforeMount");
    });

    onMounted(() => {
      console.log("setup中访问生命周期 onMounted");
    });

    onMounted(() => {
      console.log("setup中访问生命周期 onMounted");
    });
    // 其他 hooks 同理...
    // ...
    return {};
  },
};

2. 核心:响应式

  • 1)原 data 中定义的属性,改为使用 ref() 和 reactive()
  • 2)原 computed 中定义的属性,改为使用 computed()
  • 3)原 methods 中定义的方法,改为使用 setup()中定义,并且由 setup()返回
  • 3)原 watch 中定义的被观察属性,改为使用 watchEffect()

接下来举例说明


第一,data 使用区别

其中对于 字符串(name),数字(age)这样的原始数据类型属性使用 ref, 对于引用类型(ceo),对象数组使用 reactive

// vue2中data定义及其使用
export default {
  data(){
    return {
      name: "ifredom",
      age: 18,
      ceo: {
        name:"雷军"
        sex: "man",
        age: 44
      }
    }
  },
  mounted(){
    console.log(this.name)
    console.log(this.age)
    console.log(this.ceo)
  }
};
// vue3中data定义及其使用
import { ref, reactive, onMounted } from "vue";
export default {
  setup() {
    const name = ref("ifredom");
    const age = ref(18);
    const ceo = reactive({
      name: "雷军",
      sex: "man",
      age: 44,
    });

    onMounted(() => {
      console.log(this.name);
      console.log(this.age);
      console.log(this.ceo);
    });
    return {
      name,
      age,
      ceo,
    };
  },
};

第二,computed 使用区别

computed()也是三步走,引入,使用,返回

// vue2中 computed定义及其使用
export default {
  data(){
    return {
      name: "ifredom",
      age: 18,
      ceo: {
        name:"雷军"
        sex: "man",
        age: 44
      }
    }
  },
  computed:{
    workAge(){
      console.log("工作十年后");
      return this.ceo.age + 10
    }
  },
  mounted(){
    console.log(this.workAge)
  }
};
// vue3中 computed 定义及其使用
import { ref, reactive, onMounted } from "vue";
export default {
  setup() {
    const name = ref("ifredom");
    const age = ref(18);
    const ceo = reactive({
      name: "雷军",
      sex: "man",
      age: 44,
    });

    const workAge = computed(() => {
      console.log("工作十年后");
      return ceo.age + 10;
    });

    onMounted(() => {
      console.log(workAge);
    });
    return {
      name,
      age,
      ceo,
      workAge,
    };
  },
};

第三,methods 使用区别

方法的 定义,调用,统统在 setup() 中完成

// vue2中 methods 定义及其使用
export default {
  data() {
    return {};
  },
  methods: {
    fetchUserInfo() {
      console.log("查询用户信息");
    },
  },
  mounted() {
    this.fetchUserInfo();
  },
};
// vue3中 methods 定义及其使用
export default {
  setup() {
    // 定义
    fetchUserInfo(){
      console.log("查询用户信息")
    }
    onMounted(() => {
      // 使用
      fetchUserInfo()
    });
    return {
      // 返回 (当你在template中用到此方法时才需要返回,否则不用)
      fetchUserInfo
    };
  },
};

第四,watch 使用区别

watchEffect()是监听函数内所有数据源,watch()监听单一数据源
同时 Vue3 对 watchEffect 进行了扩展,返回了一个标志函数const stop = watchEffect();可以调用 stop() 停止监听

// vue2中 watch 定义及其使用
export default {
  data() {
    return {
      name: "ifredom",
    };
  },
  watch: {
    name(newVal, oldVal) {
      console.log("name改变了");
      console.log(this.name);
    },
  },
  mounted() {
    this.name = "Tony";
  },
};
// vue3中 watch 定义及其使用
export default {
  setup() {
    let name = ref("ifredom");

    // 监听单一数据源,此处为 name
    watch(name, (newVal, oldVal) => {
      console.log("name改变了");
      console.log(name.value);
    });

    // 监听函数内所有数据源
    const stop = watchEffect(() => {
      console.log("name改变了");
      console.log(name.value);
    });

    // 调用,则选择停止监听
    // stop()

    onMounted(() => {
      name.value = "Tony";
    });

    return {
      // 返回 (当你在template中用到此方法时才需要返回,否则不用)
      fetchUserInfo,
    };
  },
};

3. 生命周期

选项 API 生命周期 和 组合式 API 之间的映射

Vue3.0 是对 Vue2.0 的重构升级,

2.0 周期名称3.0 周期名称说明
beforeCreate使用 setup()
created使用 setup()
beforeMountonBeforeMount组件挂载之前
mountedonMounted组件挂载完成
beforeUpdateonBeforeUpdate数据更新,虚拟 DOM 打补丁之前
updatedonUpdated数据更新,虚拟 DOM 渲染完成
beforeUnmountonBeforeUnmount组件销毁之前
unmountedonUnmounted组件销毁后
errorCapturedonErrorCaptured捕获子孙组件被调用错误 (err, vm, info)
renderTrackedonRenderTracked捕获渲染栈异常
renderTriggeredonRenderTriggered渲染识别

4. Vuex 使用

// vue3中 vuex 定义及其使用
import { useStore } from "vuex";
export default {
  setup() {
    const store = useStore();

    // vuex4中的定义方式与vuex3中一模一样
    const roles = store.state.user.roles;
    return {
      roles,
    };
  },
};

5. directive 指令使用

template中使用<input v-defineFocus />

// vue2.0 版本
import Vue from "vue";
// 注册,定义
Vue.directive("defineFocus", {
  bind: function () {},
  inserted: function () {},
  update: function () {},
  componentUpdated: function () {},
  unbind: function () {},
});
//  vue3.0 版本
import { createApp } from "vue";
import App from "./App.vue";

const app = createApp(App);

app.directive("defineFocus", {
  // 当dom渲染完成后,执行 mounted(el)...
  mounted(el) {
    console.log("defineFocus 指令");
    console.log(el);
    el.focus();
  },
});
app.mount("#app");

在Vue3.0中,directive 有以下这些生命周期 hooks(钩子函数),与Vue2.0所含的hooks有较大的区别:

import { createApp } from "vue";
const app = createApp({});

app.directive("defineFocus", {
  // 当元素父组件的钩子函数 mounted() 完成之前,调用此hooks
  beforeMount() {},
  // 当元素父组件的钩子函数 mounted()完成后,调用此hooks
  mounted() {},
  // 当元素父组件中的任意节点(Vnode)更新之前,调用此hooks
  beforeUpdate() {},
  // 当元素父组件中的任意节点(Vnode)更新时,调用此hooks. (已经更新)
  updated() {},
  // 当元素父组件即将卸载之前,调用此hooks.
  beforeUnmount() {},
  // called when the bound element's parent component is unmounted
  // 当元素父组件即将卸载完成,调用此hooks.
  unmounted() {},
});
Logo

前往低代码交流专区

更多推荐