vue2和vue3的使用区别

  1. 项目启动

Vue2:new Vue()  创建应用
Vue.use()  使用插件
Vue.component()  注册全局组件 

Vue3:
// 创建一个vue应用
// 1. 导入createApp函数
// 2. 编写一个根组件App.vue,导入进来
// 3. 基于根组件创建应用实例
// 4. 挂载到index.html的#app容器
 
import {createApp} from 'vue'
import App from './App.vue'
const app = createApp(App)
app.mount('#app')
  1. 生命周期

对于生命周期来说,整体上变化不大,只是大部分生命周期钩子名称上 + “on”,功能上是类似的。不过有一点需要注意,Vue3 在组合式API(Composition API,下面展开)中使用生命周期钩子时需要先引入,而 Vue2 在选项API(Options API)中可以直接调用生命周期钩子,如下所示。
// vue3
<script setup>     
import { onMounted } from 'vue';   // 使用前需引入生命周期钩子
 
onMounted(() => {
  // ...
});
 
// 可将不同的逻辑拆开成多个onMounted,依然按顺序执行,不会被覆盖
onMounted(() => {
  // ...
});
</script>
 
// vue2
<script>     
export default {         
  mounted() {   // 直接调用生命周期钩子            
    // ...         
  },           
}
</script> 
常用生命周期对比如下表所示。
setup 是围绕 beforeCreate 和 created 生命周期钩子运行的,所以不需要显式地去定义。
import { 
  defineComponent, 
  onBeforeMount, 
  onMounted, 
  onBeforeUpdate, 
  onUpdated, 
  onBeforeUnmount, 
  onUnmounted, 
  onErrorCaptured, 
  onRenderTracked, 
  onRenderTriggered, 
} from "vue"; 
export default defineComponent({ 
  //beforeCreate和created是vue2的 
  beforeCreate() { 
    console.log("------beforeCreate-----"); 
  }, 
  created() { 
    console.log("------created-----"); 
  }, 
  setup() { 
    console.log("------setup-----"); 
    // vue3.x生命周期写在setup中 
    onBeforeMount(() => { 
      console.log("------onBeforeMount-----"); 
    }); 
    onMounted(() => { 
      console.log("------onMounted-----"); 
    }); 
    onBeforeUpdate(() => { 
      console.log("------onBeforeUpdate-----"); 
    }); 
    onUpdated(() => { 
      console.log("------onUpdated-----"); 
    }); 
    onBeforeUnmount(() => { 
      console.log("------onBeforeUnmount-----"); 
    }); 
    onUnmounted(() => { 
      console.log("------onUnmounted-----"); 
    }); 
    onErrorCaptured(() => { 
      console.log("------onErrorCaptured-----"); 
    }); 
    onRenderTracked(() => { 
      console.log("------onRenderTracked-----"); 
    }); 
    // 调试哪些数据发生了变化 
    onRenderTriggered((event) => { 
      console.log("------onRenderTriggered-----", event); 
    }); 
  }, 
}); 
  1. 多根节点

// vue2中在template里存在多个根节点会报错
<template>
  <header></header>
  <main></main>
  <footer></footer>
</template>
 
// 只能存在一个根节点,需要用一个<div>来包裹着
<template>
  <div>
    <header></header>
    <main></main>
    <footer></footer>
  </div>
</template>

// 但是,Vue3 支持多个根节点,也就是 fragment。即以下多根节点的写法是被允许的。
<template>
  <header></header>
  <main></main>
  <footer></footer>
</template>
  1. Options API 与 Composition API

Vue 组件可以用两种不同的 API 风格编写:Options API 和 Composition API。
  1. Options API
使用 Options API,我们使用选项对象定义组件的逻辑,例如data、methods和mounted。由选项定义的属性在 this 内部函数中公开,指向组件实例,如下所示。
<template>
  <button @click="increment">count is: {{ count }}</button>
</template>
 
<script>
export default {
  data() {
    return {
      count: 0
    }
  },
  methods: {
    increment() {
      this.count++;
    }
  },
  mounted() {
    console.log(`The initial count is ${this.count}.`);
  }
}
</script>
  1. Composition API
使用 Composition API,我们使用导入的 API 函数定义组件的逻辑。在 SFC 中,Composition API 通常使用
<template>
  <button @click="increment">Count is: {{ count }}</button>
</template>
 
<script setup>
import { ref, onMounted } from 'vue';
 
const count = ref(0);
 
function increment() {
  count.value++;
}
 
onMounted(() => {
  console.log(`The initial count is ${count.value}.`);
})
</script>
  1. 异步组件(Suspense)

Vue3 提供 Suspense 组件,允许程序在等待异步组件加载完成前渲染兜底的内容,如 loading ,使用户的体验更平滑。使用它,需在模板中声明,并包括两个命名插槽:default 和 fallback。Suspense 确保加载完异步内容时显示默认插槽,并将 fallback 插槽用作加载状态。
<tempalte>
  <suspense>
    <template #default>
      <List />
    </template>
    <template #fallback>
      <div>
        Loading...
      </div>
    </template>
  </suspense>
</template>
在 List 组件(有可能是异步组件,也有可能是组件内部处理逻辑或查找操作过多导致加载过慢等)未加载完成前,显示 Loading...(即 fallback 插槽内容),加载完成时显示自身(即 default 插槽内容)。
  1. Teleport

Vue3 提供 Teleport 组件可将部分 DOM 移动到 Vue app 之外的位置。比如项目中常见的 Dialog 弹窗。
<button @click="dialogVisible = true">显示弹窗</button>
<teleport to="body">
  <div class="dialog" v-if="dialogVisible">
    我是弹窗,我直接移动到了body标签下
  </div>
</teleport>
  1. 路由

使用 createRouter 工厂函数来创建路由实例,然后将其传递给根组件使用:
import { createRouter, createWebHistory } from 'vue-router' 
import HelloWorld from './components/HelloWorld.vue' 
const routes = [ 
  { path: '/', component: HelloWorld } 
] 

const router = createRouter({ 
  history: createWebHistory(), 
  routes 
}) 
export default router 
  1. 请求

在 Vue 3.0 中,官方推荐的 HTTP 请求库是 axios 的替代品—— vite-plugin-mock,该库内置了一套基于 axios 的请求拦截和响应拦截机制,并且已经在 Vite 中默认启用了。这种方式可以大大减少编写重复代码的工作量,同时也支持更好的类型推断和类型校验(使用 async/await 来封装请求代码)。
  1. 代码上

import组件
<template>   
    <Chart />  
</template>  <script setup>  
   // 必须将后缀补全  
   //  一个import即可,无需在组件属性中添加,因为<script setup> 会自动把组件注册到当前组件 
   import Chart from './chart.vue' 
</script> 
Vue2不能v-if v-for 同时使用,因为v-for会先执行,但Vue3可以:
<div v-if="show"> 
  <div v-for="item in items" :key="item.id">{{ item }}</div> 
</div> 
Vue3 v-bind可以省略
v-model :
<input v-model="count" type="number"> 
<!-- 等价于 --> 
<input :value="count" @input="count = $event.target.value" type="number”> 


<el-dialog v-model:visible="isVisible" v-model:content="content"></el-dialog> 
<!-- 相当于 --> 
<el-dialog 
    :visible="isVisible" 
    :content="content" 
    @update:visible="isVisible" 
    @update:content="content" 
></el-dialog> 摒弃 .sync ,直接使用v-model 
定义全局变量:
// 之前(Vue 2.x) 
Vue.prototype.$http = () => {} 
Vue.prototype.url= 'http://123' 
// 之后(Vue 3.x) 
const app = createApp({}) 
app.config.globalProperties.$http = () => {} 
app.config.globalProperties.url= 'http://123' 
插槽slot:
// vue2.0使用插槽基本上直接使用slot进行操作,其中vue2.0经历了两次更迭,2.6.0版本slot升级为v-slot 
<div> 
    <slot :current="toolTipData" name="test"></slot> // 具名 作用域插槽 
    <slot></slot> //默认插槽 
</div> 
//父组件调用该组件 
<test> 
    <template> 
       <div>默认插槽</div> 
    </template> 
     // 作用域插槽 
    <template slot-scope="{ current }" slot="test"> 
       <el-form label-width="80px" :model="current"> 
         <el-form-item label="id:"> 
           <el-link type="info">{{ current.id }}</el-link> 
         </el-form-item> 
       </el-form> 
     </template>
</test> 
//==============vue3.0使用插槽 
//在vue3.0中,插槽使用v-slot 简写用# 
<div>     
   <slot name="test" :newData="slotsData"></slot> 
   <slot></slot> 
</div> 
<HelloWorld msg="Welcome to Your Vue.js + TypeScript App"> 
    <template #default> // 可以写为v-slot:default  #后面跟的是插槽名称 
       <div>默认插槽</div> </template> 
     //作用域插槽 
    <template #test="{ newData }"> // 可以写为v-slot:test="newData" 
      <p>{{ newData.aa }}</p> 
      <p>{{ newData.bb }}</p> 
    </template> 
</HelloWorld> 
//一个组件里面具有多个插槽时,一定要带上名称,否则可能会导致作用域错乱 
toRefs 用于将一个 reactive 对象转化为属性全部为 ref 对象的普通对象:
<template> 
  <div> 
    <p>计数:{{ num }}s</p> 
    <p>主人年龄:{{ person.age }}</p> 
    <p>主人姓名:{{ person.name }}</p> 
    <p>动物类别:{{ atype }}</p> 
    <p>动物名称:{{ aname }}</p> 
    <p>动物年龄:{{ aage }}</p> 
  </div> 
</template> 
<script> 
import { defineComponent, reactive, ref, toRefs } from "vue"; 
export default defineComponent({ 
  setup() { 
    //使用ref声明基本类型 
    const num = ref(0); 
    //使用ref声明对象 
    const person = ref({ age: 20, name: "张三" }); 
    //使用reactive声明对象 
    const animal = reactive({ atype: "猫", aname: "小花", aage: 5 }); 
    setTimeout(() => { 
      person.value.age = person.value.age + 1; 
      person.value.name = "李四"; 
      animal.aage++; 
    }, 1000); 
    setInterval(() => { 
      num.value++; 
    }, 1000); 
    return { 
      num, 
      person, 
      ...toRefs(animal), 
    }; 
  }, 
}); 
</script> 
Readonly只读变量:
import { reactive, readonly } from 'vue' 

const original = reactive({ count: 0 }) 
const copy = readonly(original) 

// 通过 original 修改 count,将会触发依赖 copy 的侦听器 
original.count++ 
// 通过 copy 修改 count,将导致失败并出现警告 
copy.count++ // 警告: "Set operation on key 'count' failed: target is readonly." 
watch监听:
//监听reactive对象: 
watch( 
      () => animal.aage, 
      (curAge, preAge) => { 
        console.log("新值:", curAge, "老值:", preAge); 
      } 
    ); 

//监听ref变量 
watch(num, (newVal, oldVal) => { 
      console.log("新值:", newVal, "老值:", oldVal); 
    }); 
 
//多个值的监听 
watch([() => animal.aage, num], ([curAge, newVal], [preAge, oldVal]) => { 
      console.log("新值:", curAge, "老值:", preAge); 
      console.log("新值:", newVal, "老值:", oldVal); 
    }); 
 
//监听对象复杂时,请使用深度监听 让函数的第三个参数为deep:true 
watch( 
      () => state.animal, 
      (newType, oldType) => { 
        console.log("新值:", newType, "老值:", oldType); 
      }, 
      { deep: true } 
    ); 

//停止监听函数 
   const stopWatchRoom = watch( 
      () => state.animal, 
      (newType, oldType) => { 
        console.log("新值:", newType, "老值:", oldType); 
      }, 
      { deep: true } 
    ); 
    setTimeout(() => { 
      // 停止监听 
      stopWatchRoom(); 
    }, 3000); 
默认情况下,watch 是惰性的, 给第三个参数中设置immediate: true即可立即执行回调函数;
点赞

当前页面评论已关闭。

隐藏
变装