快速了解Vue2.x与Vue3.x的差异

Vue3.x出来以后跟Vue2.x有很多写法上面的差异差异,最开始的创建就有一定的不同了,以前Vue2.x通过new Vue(),手动生成,并且全局API挂在Vue上,如下:

   // vue2 
   import Vue from 'vue'import App from './App.vue';
   Vue.component('loading', {})
   new Vue({
     render: h => h(App)
   }).$mount('#app')

现在Vue3.x通过createApp实例化,并且全局API挂在vue实例上 app,如下:

    // vue3
    import { createApp } from 'vue'
    import ElementPlus from 'element-plus'
    import * as ElIconModules from "@element-plus/icons-vue";
    import 'element-plus/dist/index.css'
    import App from './App.vue'
    import router from './router'
    import store from './store'
    const app = createApp(App)
    app.use(store)
    app.use(ElementPlus)
    app.use(router)
    app.component('loading', {})
    Object.keys(ElIconModules).forEach(function (key) {
        app.component(ElIconModules[key].name, ElIconModules[key]);
    });
    app.mount('#app')

以下还有一些差异跟大家分享一下

1. 生命周期钩子

① 2.x
export default {
  name: '',
  data() {
    return {}
  },
  components: {},
  methods: {},
  computed: {},
  beforeCreate() {
    console.log('beforeCreate 创建vue实例完成之前所执行的')
  },
  created() {
    console.log('created 实例创建完成之后的,初始化data和methods')
  },
  beforeMount() {
    console.log('beforeMount 开始编译把data里面的数据和vue语法生成html模板')
  },
  mounted() {
    console.log('mounted 开始挂载编译生成的html渲染到页面')
  },
  beforeUpdate() {
    console.log('beforeUpdate 当data里面数据改变时触发')
  },
  updated() {
    console.log('updated data里面的数据和页面保持同步')
  },
  beforeDestroy() {
    console.log('beforeDestroy vue实例从运行状态进入销毁状态,data、methods、指令等还处于可用状态')
  },
  destroyed() {
    console.log('destroyed 组件完全被销毁,data、methods、指令等已经不可用了')
  }
}
② 3.x
export default defineComponent({
  name: "ed",
  props: {
    title: {
      type: String,
      default: "",
    },
  },
  //setup取消了beforeCreate和created在beforeCreate和created之前执行
  setup(porps, { emit }) {
    onBeforeMount(() => {
      console.log("onBeforeMount - 组件挂载到节点上之前执行的函数");
    });
    onMounted(() => {
      console.log("onMounted - 组件挂载完成后执行的函数");
    });
    onBeforeUpdate(() => {
      console.log("onBeforeUpdate - 组件更新之前执行的函数");
    });
    onUpdated(() => {
      console.log("onUpdated - 组件更新完成之后执行的函数");
    });
    onBeforeUnmount(() => {
      console.log("onBeforeUnmount - 组件卸载之前执行的函数");
    });
    onUnmounted(() => {
      console.log("onUnmounted - 组件卸载完成后执行的函数");
    });
    const state = reactive({
      //数据
      username: "",
      password: "",
      lowerCaseUsername: computed(() => state.username.toLowerCase()), //计算属性
    });
    //方法
    const fn= () => {};
    return {
      fn,
      onMounted,
      ...toRefs(state),
    };
  },
  computed: {},
  components: {},
  data() {
    return {};
  },
  methods: {},
});

以上可以看出vue2.0和3.0差异
Vue2--------------Vue3
beforeCreate----setup()
created----setup()
beforeMount----onBeforeMount
mounted----onMounted
beforeUpdate---- onBeforeUpdate
updated ---- onUpdated
beforeDestroy ---- onBeforeUnmount
destroyed ---- onUnmounted
并且还可以看出vue2.0中响应性数据一般都在data,computed,方法基本都是局限在methods中使用,而3.0响应性数据正常可以通过引入的reactive,把数据放入reactive中,通过setup()方法来返回我们的响应性数据,函数可以直接放在setup中并return出去,这使代码会更加简便和整洁

2.双向数据绑定原理

Vue2.x 基于Object.definePropert()对数据进行劫持 结合 发布订阅模式的方式来实现的。 Vue3.x基于Proxy来做数据大劫持代理,可以原生支持到数组的响应式,不需要重写数组的原型,还可以直接支持新增和删除属性,比Vue2.x的Object.defineProperty更加的清晰明了。
proxy和definePropert差异:
proxy相比于definePropert,defineProperty只能监听某个属性,不能对全对象监听,proxy可以省去for in、闭包等内容来提升效率(直接绑定整个对象即可),也可以监听数组,不用再去单独的对数组做特异性操作 vue3.x可以检测到数组内部数据的变化,但是proxy无法兼容全部浏览器,无法polyfill

3.支持碎片

vue2只能有一个节点

<template>
  <div class="form">
    <h3></h3>
  </div>
</template>

vue3可以有多个节点

<template>
  <div class="form"></div>
  <h3></h3>
</template>

4.取消filter

2.x经常在组件中可以使用filter,但在 3.x 中,过滤器已移除,且不再支持。建议可以使函数方法调用或计算属性来替换它们。

5. 函数组件写法改变 - h

在 2.x 中,render 函数会自动接收 h 函数当一个参数

// vue2
Vue.component('loading', {
	render(h) {
		return h('div', {title: ''}, [''])
	},
})

在 3.x 中,h 函数现在是全局通过vue导入的,而不是作为参数自动传递。

// vue3
import { h } from 'vue'
app.component('loading', {
	render(props, context) {
		return h('div', {title: ''}, [''])
	},
})

6. router、vuex、refs的以及nextTick使用

// vue2
<div ref="popover"></div>

import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
// 字符串
this.$router.push('home')
// 对象
this.$router.push({path: '/login?url=' + this.$route.path});
// 命名的路由
this.$router.push({ name: 'user', params: { userId: 123 }})
// 带查询参数,变成/backend/order?selected=2
this.$router.push({path: '/backend/order', query: {selected: "2"}});
//访问store属性下state下面的name
this.$store.state.name
//访问store里的user.js的login方法,从而要更新。
this.$store.dispatch(‘Login’, this.loginForm)
//
this.$nextTick(() => {
  console.log(this.$refs.popover)
});
methods: {
   ...mapMutations({add:'JIA',jf:'JIAN'}),
   ...mapActions(['jadd','delayAdd'])
},
// vue3
<div ref="popover"></div>

import{ nextTick , ref} from "vue";
import { useRouter } from "vue-router";
import { mapGetters } from "vuex";
import { useStore } from "vuex";
export default defineComponent({
  setup() {
    const popover= ref(null);
    const router = useRouter();
    const store = useStore();
    const state = reactive({
      urls: "",
      user: '',
    });

    const toggleSideBar = () => {
      store.dispatch("app/toggleSideBar");
    };
    const goTO = () => {
      router.push({ path: "/user/info" });
    };
    onMounted(() => {
      nextTick(() => {
        console.log(popover.value)
      })
    });
    return {
      toggleSideBar,
      ...toRefs(state),
      onMounted,
      goTO,
      popover
    };
  },
  computed: {
    ...mapGetters(["sidebar", "avatar", "device", "name"]),
  },
  components: { },
  data() {
    return {};
  },
});

7.computed和watch区别

//vue2
 watch:{
    'form.minimumChargeAmount':{
      handler(val){
        console.log(val)
      }
    },
    name(newValue, oldValue){
        console.log("修改了name", newValue, oldValue);
    },
    result: {
      immediate: true,
      deep: true,
      handler(newValue, oldValue) {
        console.log("修改了result", newValue, oldValue);
      },
    },
  },
computed: {
    totalPage: function () {
      return Math.ceil(this.total / this.pageSize);
    },
   fullName: {
      get() {
        return this.firstName + "-" + this.lastName;
      },
      set(val) {
        const nameArr = val.split("-");
        this.firstName = nameArr[0];
        this.lastName = nameArr[1];
      },
    },
}
//vue3
import {
  defineComponent,
  reactive,
  computed,
  toRefs,
  watch,
  ref,
  watchEffect,
} from "vue";
export default defineComponent({
  name: "",
  setup() {
    const state = reactive({
      //数据
      username: "",
      password: "",
      lowerCaseUsername: computed(() => state.username.toLowerCase()), //计算属性
      demo: "demo",
      name1: "1",
      name2: "2",
    });
    let name = computed(() => state.name1 + "-" + state.name2);
    let sure = computed({
      get() {
        return state.name1 + "-" + state.name2;
      },
      set(val) {
        const nameArr = val.split("-");
        state.name1 = nameArr[0];
        state.name2 = nameArr[1];
      },
    });
    //监听指定对象下面的属性
    // watch(
    //   () => state.demo,
    //   (newValue, oldValue) => {
    //     console.log("state.demo", newValue, oldValue);
    //   },
    //   {
    //     immediate: true,
    //   }
    // );
    let sum = ref(0);
    let msg = ref("watch使用");
    // 监视ref所定义的多个响应式数据
    watch(
      [sum, msg],
      ([s, m], [olds, oldm]) => {
        console.log("sum/msg变化", s, m, olds, oldm);
      },
      { immediate: true }
    );

    watchEffect(() => {
      console.log("监听state.demo", state.demo);
    });
    return {
      ...toRefs(state),
      name,
      sure,
      sum,
      msg,
    };
  },
  components: {},
  data() {
    return {};
  },
});
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值