Vue2转Vue3看这一片就够了!

一、Vue3初体验

1.1 Vue3与Vue2的语法区别

​ 由于选项式API——Vue2的代码是按区域去划分代码块的,比如:methods方法区域,computed计算区域,watch观察区域。但是由于代码量增加,Vue2的情况下写的代码数据与逻辑并不能很好的归并到一起,为增加代码的可读性,所以我们使用组合式API——Vue3代替。

二、语法区别

1.1 setup

  • setup()在组件被创建之前执行,这里不需要使用this,this不会指向实例。
  • 在vue3中舍弃了**beforeCreate()created()方法,在这两个方法内写的方法都可以在setup()**中执行。
  • setup()会将内部的参数通过【return】暴露给其他组件。
  • 通过【ref】可以实现响应式变量
  • 通过【reactive】可以实现响应式对象
  • 通过【】解构出来的数据不具备响应式,但是我们可以通过【toRefs】把它变成响应式
<template>
  <div>
    <div>
      {{ msg }}
      <button @click="updateMsg">改变msg</button>
    </div>
    <div>
      <!-- 模板会自动解析value值 -->
      {{ counter }}
      <button @click="updateCounter">改变counter</button>
    </div>
    <div>
      <!-- 模板会自动解析value值 -->
      {{ obj }}
      <button @click="updateObj">改变obj</button>
    </div>
    <div>
      {{ name }}
      {{ age }}
      {{children}}
      <button @click="updateObj">改变obj</button>
    </div>
  </div>
</template>

<script>
// 引入响应式
import {ref, reactive,toRefs} from "vue";

export default {
  name: "App",
  setup() {
    // 定义变量 【非响应式】
    let msg = "MSG"

    // 定义方法
    function updateMsg() {
      msg = "msg"
      console.log("msg", msg)
    }

    // 通过ref定义响应式变量
    const counter = ref(0); // ref()返回的是一个带 value的对象
    function updateCounter() {
      counter.value++;
      console.log("counter", counter);
    }

    // 通过reactive定义引用类型的数据
    const obj = reactive({
      name: "张三",
      age: 18,
      children:{
        name:"张三丰",
        age:0
      }
    })
    function updateObj() {
      obj.name = "李四";
      obj.age = 19;
    }

    // 暴露参数
    return {
      msg,
      updateMsg,
      counter,
      updateCounter,
      obj,
      updateObj,
      ...obj,// 解构出来的变量无响应式
      ...toRefs(obj), // 使用toRefs则有响应式
    }
  }
}
</script>

<style scoped>
</style>
1.1.1 props与context
<template>
  <div>
    <v ref="v" :message="msg" :class="c" @updatePropsMessage="updateMessage" @updateClass="updateClass"></v>
    <button @click="updateMessage('点击了父组件按钮')">父组件</button>
    <button @click="updateCount">父组件修改子组件</button>
  </div>
</template>

<script>
// 引入响应式
import {ref, reactive, onMounted} from "vue";
import V from "@/components/v.vue";

export default {
  name: "App",
  components: {V},
  setup(props,context) {
    const msg = ref("最初的msg");

    // 子组件通过context.emit调用父组件
    function updateMessage(value) {
      if (value) {
        msg.value = value
      }
      console.log("msg", msg.value);
    }

    // 子组件使用context.attrs
    const c = ref("pink")
    function updateClass(value) {
      c.value = value
    }

    // 父组件调用子组件方法方式
    const v=ref(null)
    function updateCount(){
      v.value.updateCount()
    }
    return {
      msg,
      updateMessage,
      c,
      updateClass,
      updateCount,
      v
    }
  }
}
</script>

<style scoped>
.pink {
  background-color: pink;
}

.green {
  background-color: green;
}
</style>

子组件

<template>
  <div>
    我是V组件,我得到的数值是 {{ message }}
    <button @click="updateMessage">子组件</button>
    <span>子组件计数:{{count}}</span>
  </div>
</template>

<script>
import {ref, reactive, toRefs} from "vue";

export default {
  props: {
    message: {
      type: String,
      default: "子组件"
    }
  },
  setup(props,context) {
    // 子传父
    function updateMessage(){
      // console.log("slots",context.slots)
      // console.log("emit",context.emit)
      // console.log("expose",context.expose)
      context.emit("updatePropsMessage","点击了子组件按钮")
      if (context.attrs.class === 'pink') {
        context.emit("updateClass", "green");
      } else {
        context.emit("updateClass", "pink");
      }
    }

    const count=ref(0)
    function updateCount(){
      count.value++;
    }
    context.expose({
      updateCount
    })
    return {
      updateMessage,
      count,
      updateCount
    }
  }
}
</script>

<style scoped>

</style>

1.2 watch

  • 需要导入【watch,watchEffect】方法
  • watch】:watch(侦听响应式引用,回调函数),只能监听指定的属性
  • watchEffect】:对象类型深度监听,自动收集方法内需要监听的变量。
<template>
  <div>
    <div>
      {{ count }}
      <button @click="updateCount">改变</button>
    </div>
    <div>
      {{ user }}
      <button @click="updateUser">改变</button>
    </div>
  </div>
</template>

<script>
// 引入响应式
import {ref, reactive, toRefs, watch,watchEffect} from "vue";

export default {
  name: "App",
  setup() {
    /**
     * count start
     */
    const count = ref(0)

    function updateCount() {
      count.value++;
    }
    // watch(侦听响应式引用,回调函数),只能监听指定的属性
    watch(count,(newValue,oldValue)=>{
      console.log("oldValue",oldValue)
      console.log("newValue",newValue)
    })

    /**
     * count end
     */
    /**
     * user start
     */
    const user = reactive({
      name: "张三",
      age: 18
    })

    function updateUser() {
      user.name = "李四"
      user.age = 14
    }
    // 对象类型深度监听,自动收集方法内需要监听的变量。
    watchEffect(()=>{
      console.log("user.name",user.name);
      console.log("user.age",user.age);
      // 可以同时监听多个
      console.log("count",count.value);
    })
    /**
     * user end
     */
    return {
      count,
      updateCount,
      user,
      updateUser
    }
  }
}
</script>

<style scoped>
</style>

1.3 computed

  • computed】会返回一个方法对象
<template>
  <div>
    <div>
      {{ a }}
      <button @click="updateA">改变</button>
    </div>
    <div>
      {{ b }}
      <button @click="updateB">改变</button>
    </div>
    <div>
      {{ add  }}
    </div>
  </div>
</template>

<script>
// 引入响应式
import {ref, reactive,computed} from "vue";

export default {
  name: "App",
  setup() {
    const a=ref(0)
    function updateA(){
      a.value++;
    }
    const b=ref(0)
    function updateB(){
      b.value++;
    }
    // 创建为一个函数
    const add=computed(()=>{
      return a.value+b.value;
    })
    return {
      a,
      updateA,
      b,
      updateB,
      add
    }
  }
}
</script>

<style scoped>
</style>

1.4 provide 与 inject

  • provide 用于传递数据
  • **inject **用于接收数据

父组件

<template>
  <div>
    <v></v>
    <button @click="update">改变</button>
  </div>
</template>

<script>
// 引入响应式
import {provide, ref, reactive} from "vue";
import V from "@/components/v.vue";

export default {
  name: "App",
  components: {V},
  setup(props, context) {
    const name = ref("张三");
    provide('name', name)

    function update() {
      name.value = "王五"
    }

    return {
      update
    }
  }
}
</script>

<style scoped>

</style>

子组件

<template>
  <div>
    {{name}}
  </div>
</template>

<script>
import {inject} from "vue";

export default {
  setup(props,context) {
    // 接收字段,默认值
    const name=inject('name','李四')
    return {
      name
    }
  }
}
</script>

<style scoped>

</style>

三、生命周期

1.1 Vue2 与Vue3生命周期对比

周期Vue2Vue3
实例创建开始beforeCreate没有,setup代替了
实例创建完成created没有,setup代替了
方法创建开始beforeMountonBeforeMount
方法创建完成mountedonMounted
页面更新开始beforeUpdateonBeforeUpdate
页面更新完成updatedonUpdated
组件卸载开始beforeUnmountonBeforeUnmount
组件卸载结束unmountedonUnmounted
错误捕获errorCapturedonErrorCaptured
追踪到响应式依赖renderTrackedonRenderTracked
变更触发了组件渲染renderTriggeredonRenderTriggered
组件被插入到 DOMactivatedonActivated
组件从 DOM 中被移除deactivatedonDeactivated
组件实例在服务器上被渲onServerPrefetch

1.2生命周期使用示例

  • 钩子使用需要引入。
  • 可以分多个区域,多次执行生命周期函数。
<template>
  <div>
    <div>
      {{ a }}
      <button @click="updateA">改变</button>
    </div>
    <div>
      {{ b }}
      <button @click="updateB">改变</button>
    </div>
    <div>
      {{ add  }}
    </div>
  </div>
</template>

<script>
// 引入响应式
import {ref, reactive,onMounted} from "vue";

export default {
  name: "App",
  setup() {
    const a=ref(0)
    function updateA(){
      a.value++;
    }
    onMounted(()=>{
      updateA();
    })
    const b=ref(0)
    function updateB(){
      b.value++;
    }
    onMounted(()=>{
      updateB();
    })
    onMounted(()=>{
      updateA();
      updateB();
    })
    return {
      a,
      updateA,
      b,
      updateB
    }
  }
}
</script>

<style scoped>
</style>

四、Vu3语法糖

在setup里面写代码需要引入并暴露变量、方法,使用起来比较麻烦,这里我们使用****标记,代码可以简介很多。

示例:

父组件

<template>
  <div>
    <v></v>
    <button @click="update">改变</button>
  </div>
</template>

<script setup>
import {provide,ref} from "vue";
import V from "@/components/v.vue";
const name = ref("张三");
provide('name', name)

function update() {
  name.value = "王五"
}

</script>

<style scoped>

</style>

子组件

<template>
  <div>
    {{name}}
  </div>
</template>

<script setup>
import {inject} from "vue";
const name=inject('name','李四')
</script>

<style scoped>

</style>
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue.js是一种流行的JavaScript框架,用于构建用户界面。Vue 2和Vue 3是Vue.js的两个主要版本,它们之间有一些重要的区别。下面是关于Vue 2和Vue 3转换的一些介绍: 1. 响应性系统:Vue 2使用基于Object.defineProperty的响应式系统来追踪数据的变化。而Vue 3使用Proxy来实现响应式系统,这使得追踪数据变化更加高效和灵活。 2. 组合式API:Vue 3引入了组合式API,这是一种新的API风格,可以更好地组织和重用组件逻辑。相比之下,Vue 2主要使用选项式API。 3. 性能优化:Vue 3在性能方面进行了一些改进,包括更好的树摇动优化、编译器优化和更小的包大小。这些改进使得Vue 3在运行时性能方面比Vue 2更好。 4. TypeScript支持:Vue 3对TypeScript的支持更加友好,包括更好的类型推断和类型定义。Vue 2也支持TypeScript,但Vue 3在这方面有更多的改进。 5. 其他改进:Vue 3还引入了一些其他改进,如Teleport(原名Portal)组件、Suspense组件、Fragment组件等,这些改进可以提供更好的开发体验和更灵活的组件结构。 如果你想将现有的Vue 2项目迁移到Vue 3,你需要注意以下几点: 1. 了解Vue 3的新特性和改变,以便适应新的API和语法。 2. 检查和更新你的代码,确保它在Vue 3中能够正常工作。特别是需要注意的是响应式系统的改变和组合式API的使用。 3. 更新相关的依赖项,如Vue Router和Vuex等,以确保它们与Vue 3兼容。 4. 迁移过程中,可以使用Vue 2和Vue 3之间的适配器库,如vue-demi,来简化迁移过程。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值