vue2和vue3有哪些区别和不同

Vue v3.x 概述

Vue 3 引入了一些新功能和一系列重大更改。让我们看看这些更改将如何影响我们的应用程序。

Vue V3.x 重大更改

在 Vue 3 中,重大更改基本上分为七类:

  • 全局 API
    (负责 Vue 的行为方式) - 您很可能想要查看这些更改。
  • 模板指令
    (对 v- 指令的工作方式所做的更改) - 您很可能想要查看这些更改。
  • 组件
    (对组件工作方式的更改) - 如果您的应用程序使用组件,则您很可能要查看这些更改
  • 呈现函数(允许您以编程方式创建 HTML 元素)
  • 自定义元素(告诉 Vue 有关创建自定义 HTML 元素的信息)
  • 次要更改(这些可能不会影响您,但您仍然需要查看这些更改)
  • 删除了 API(在 Vue 3 中不再可用的内容)

在所有更改中,有一些是任何应用程序都会使用的,例如全局API和组件。因此,如果你想开始使用新的 Vue 版本,就需要考虑它们。

值得一提的是以下附加更改:

  • 您创建 Vue 应用程序和组件实例的方式已更改(全局 API)
  • 应始终将数据选项声明为函数(细微更改)
  • 对同一元素使用 v-if 和 v-for 时的优先级更改(模板 Ddrectives)
  • 应为组件事件(组件)声明发出选项

有关更改的完整列表,您可以转到文档

现在,让我们更详细地看一下其中的一些更改。

全局属性

vue2

  • 对于一些第三方插件,Vue2通常使用原型原型来挂载到VUE对象上。
import Vue from 'vue'
Vue.prototype.$http=Axiox
Vue.prototype.$echart= Echart

vue3

  • Vue3Global 属性配置中提供了一个名称,可以替换 Vue2 中的原型globalProperties
app.config.globalProperties.$http = Axios
app.config.globalProperties.$echart = Echart
  • 使用 $ http
import {getCurrentInstance} from 'vue'

setup () {
      const { ctx } = getCurrentInstance();
			onMounted(() => {
				console.log(ctx.$http)
			})
      .......
}

REF 和 V-用于生成

vue2

VUE2中的V-FOR与REF一起使用,当引用批量模板时,获得的REF是一个数组。

  <div v-for = "i in 3" ref = "setItemref": key = "i"> {
     
     {i}} </ div> // Here are arrays
 
 mounted() {
      console.log(this.$refs.setItemRef)
},

vue3

VUE3 中的 REF 绑定是一个函数,

<div v-for = "item in 3": ref = "setItemRef"> </ div> // This is a function

setup(){
		let itemRefs = []
			const setItemRef = el => {
				itemRefs.push(el)
			}
			onMounted(() => {
				console.log(itemRefs)
			})
}

REF 的 DOM 模式已更改,但结果是相同的

异步组件

在路由中,通常使用延迟加载的方式来引入组件。

vue2

 component: () => import('@/views/homePage/index.vue'),

vue3

在 Vue3 中引入一个新方法--->定义异步组件来打包 Vue2 介绍的内容defineAsyncComponent

import { defineAsyncComponent } from 'vue'
 component: defineAsyncComponent(() => import('./NextPage.vue'))

自定义说明

更改挂钩函数的命名

vue2

VUE2 中绑定的钩子函数是

  • bind - 指令绑定到元素。仅发生一次。
  • inserted - 将元素插入父 DOM 时。
  • update - 当元素更新,但子元素尚未更新时,将调用此挂接。
  • componentUpdate - 一旦组件和子级更新,将调用此挂接。
  • unbind - 接触绑定。一旦指令被删除,将调用此钩子。只呼叫一次。

vue3

钩子函数的命名与生命周期的钩子函数一致

  • bind → beforeMount
  • inserted → mounted
  • beforeUpdate:new!这是在元素本身更新之前调用的,非常类似于组件生命周期挂钩。
  • componentUpdated → updated
  • beforeUnmount:new!与组件生命周期挂钩类似,它将在卸载元素之前调用。
  • unbind -> unmounted

挂接函数中的引用组件实例

某些实例需要获取组件中实例的某些属性

vue2

  • 需要通过 vNod 获取实例
Vue.directive('has', {
  inserted: (el, binding, vnode) => checkPermission(el, binding, vnode),
});

export const checkPermission = (el, binding, vnode) => {
    ...
     Const permissionarr = vnode.context. $ store.state.PermissionID // All permission ID
    ...
}

vue3

  • 从绑定中获取对象
export const checkPermission = (el, binding, vnode) => {
    ...
     Const permissionarr = binding.instance. $ store.State.PermissionID // All permission ID
    ...
}

v-bind=“$attrs”

自定义元素元素交互

IS 用法

vue2

  • 组件:
<component :is="currentTabComponent"></component>
  • html
<table>
  <tr is="blog-post-row"></tr>
</table> 

vue3

  • 子组件Assembly
<component is="currentTabComponent"></component>
  • html
<table>
  <TR V-IS = "'blog-post-rot"> </ tr> // V-IS is similar to binding a variable, and we need a component name, a string, so wrapped with single quotes
</table> 

事件

  • Vue3 移除、、,三种方法,只保留。$on$off$once$emit

滤波器

过滤器函数在 Vue3 中被删除。建议使用方法或计算代替,实际上,在 Vue2 中,你可以实现这两种方式。

部分过滤器

vue2

 <p>{
     
     {message|toLower}}</p>
 
 data() {
     return {
     message: 'ABC'
     }
 },
 filters: {
     toLower(value) {
     	return value.toLowerCase()
     }
 }

vue3

  • Vue3 是用计算或方法定义的
<p>{
     
     {messageToLower}}</p>

import {	
    computed,
    ref,	
} from 'vue';

setup(){

    let message = ref('ABC')
    let messageToLower = computed(() => {
        // console.log(message)
        return message.value.toLowerCase()
    })
    return{
    	messageToLower,
    }
	
}

全局过滤器

vue2

Vue.filter('toLower',  (value)=> {
	return value.toLowerCase()
})

vue3

  • 在main.js中注册
const app =createApp(App)
app.config.globalProperties.$filter={
	toLower(value){
		return value.toLowerCase()
	}
}
<p>{
     
     {$filters.toLower(message)}}</p>

根节点

vue2

  • Vue2只有一个根节点只能存在template
<template>
  <div id="app">
  	...
  </div>
</template>

vue3

  • Vue3 中可以存在多个节点
<template>
  <div>...</div>
  <a>...</a>
  <p>...</p>
</template>

template

<template>
  <div class="wrap">
    <div>{
   
   { num }}</div>
    <Button @ click = "getdata"> change data </ ​​button>
  </div>
</template>
<style lang="less" scoped>
  .wrap {
    width: 100%;
    height: 100%;
    border: 1px solid red;
  }
</style>

vue2

<!-- vue2 -->
<script>
  export default {
    data() {
      return {
        num: 333,
      };
    },
    //
    mounted() {
      alert('111');
      this.getData();
    },
    methods: {
      getData() {
        this.num = '2222';
      },
    },
  };
</script>

vue3.0

<!-- vue3.0 -->
<script>
  import { defineComponent, ref } from 'vue';
  export default defineComponent({
    setup() {
      let num = ref(1223);
      function getSecondData(params) {
        alert('222');
      }
      function getData(params) {
        num.value = 'weruwiru';
        getSecondData();
      }
      return {
        num,
        getData,
      };
    },
  });
</script>

vue3.2

<!-- vue3.2 -->
<script setup>
  import { ref } from 'vue';
  let num = ref(1223);
  function getSecondData(params) {
    alert('222');
  }
  function getData(params) {
    num.value = 'weruwiru';
    getSecondData();
  }
</script>

功能组件

全球原料药

内联模板

vue2

  • 使用内联模板属性

  • Vue2 中的文档会提示这样一个词,所以我几乎用了

    但是,内联模板会使模板的作用更难理解。因此,作为最佳实践,请选择组件模板 Option 或.vue One中的file<template> Elements来定义模板。>

vue3

删除此功能,

唯一键

输入 V-IF

vue2

  • 在 Vue2 中,V-IF 中的关键是 V-Else 控制组件或元素。
  • 如果您没有密钥,您将被重复使用。<你好世界>组件仅创建一个
<!---->
<template v-if="loginType === 'username'">
   <hello-world title="username"></hello-world>
</template>
<template v-else>
   <hello-world title="email"></hello-world>
</template>
 <Button @ Click = "ChangeType"> Switch </ button>
  • 使用 Key,每个开关将呈现组件(在 KEY 中提供)
<template v-if="loginType === 'username'">
    <hello-world title="username" key="a"></hello-world>
</template>
<template v-else>
    <hello-world title="email" key="b"></hello-world>
</template>
 <Button @ Click = "ChangeType"> Switch </ button>

vue3

Vue3 默认为键,此键始终是唯一的,不同于其他键,不能使用相同的来强制重用分支。

<div v-if="condition">Yes</div>
<div v-else>No</div>

在模板中的 V-for 中 KEY

vue2

在 Vue2 的 Template 选项卡上,你可以使用 V-FOR 指令,但不能绑定 Key,只能在子节点上绑定唯一的 KEY。

<template v-for="item in list">
  <div :key="item.id">...</div>
</template>

vue3

键可以绑定到 Vue3 中的模板

<template v-for="item in list" :key="item.id">
  <div>...</div>
</template>

设置数据

这就是主要区别所在 —— Vue2 Options API 与 Vue 3 Composition API。

选项 API 将我们的代码分为不同的属性:数据、计算属性、方法等。同时,组合API允许我们按函数而不是属性类型对代码进行分组。

对于窗体组件,假设我们只有两个数据属性:a 和 a。username        password

Vue2 代码看起来像这样 – 我们只是在数据属性中折腾了两个值。

export default {
  props: {
    title: String,
  },
  data() {
    return {
      username: "",
      password: "",
    };
  },
};

在 Vue 3 中,我们必须通过使用一种新方法来投入更多的精力,其中所有组件初始化都应该进行。setup()

此外,为了让开发人员能够更好地控制什么是反应式的,我们可以直接访问 Vue 的反应性 API。

创建反应式数据涉及三个步骤:

  • 从 vue 导入reactive

  • 使用反应式方法声明我们的数据

  • 让我们的方法返回反应式数据,以便我们的模板可以访问它setup

就代码而言,它看起来有点像这样。

import { reactive } from "vue";

export default {
  props: {
    title: String,
  },
  setup() {
    const state = reactive({
      username: "",
      password: "",
    });

    return { state };
  },
};

然后,在我们的模板中,我们像和state.username        state.password

在 Vue 2 与 Vue 3 中创建方法

Vue2 选项 API 有一个单独的方法部分。在其中,我们可以定义我们所有的方法并以我们想要的任何方式组织它们。

Vue 3 Composition API中的 setup 方法也处理方法。它的工作方式有点类似于声明数据——我们必须首先声明我们的方法,然后返回它,以便我们组件的其他部分可以访问它。

创建我们的模板(根目录)

对于大多数组件,Vue 2 和 Vue 3 中的代码即使不相同,也会非常相似。但是,Vue 3 支持 Fragments,这意味着组件可以有多个根节点。

这在渲染列表中的组件以删除不必要的包装器 div 元素时特别有用。但是,在这种情况下,我们将为表单组件的两个版本保留一个根节点。

Vue3

唯一真正的区别是我们如何访问我们的数据。在 Vue 3 中,我们的响应式数据都包装在一个响应式状态变量中——因此我们需要访问这个状态变量来获取我们的值。

生命周期挂钩

在 Vue2 中,我们可以直接从我们的组件选项中访问生命周期钩子。对于我们的示例,我们将等待mounted 事件。

现在使用 Vue 3 组合 API,几乎所有内容都在 setup() 方法中。这包括已安装的生命周期挂钩。

但是,默认情况下不包含生命周期钩子,因此我们必须导入onMounted在 Vue 3 中调用的方法。这看起来与之前导入响应式的方法相同。

然后,在我们的 setup 方法中,我们可以通过将 onMounted 方法传递给我们的函数来使用它。

计算属性

让我们添加一个计算属性,将我们的用户名转换为小写字母。

为了在 Vue2 中实现这一点,我们向选项对象添加了一个计算字段。从这里,我们可以像这样定义我们的属性……

Vue 3 的设计允许开发人员导入他们使用的东西,并且在他们的项目中没有不必要的包。本质上,他们不希望开发人员必须包含他们从未使用过的东西,这在 Vue2 中正成为一个日益严重的问题。

因此,要在 Vue 3 中使用计算属性,我们首先必须将计算属性导入到我们的组件中。

然后,与我们之前创建响应式数据的方式类似,我们可以将一段响应式数据作为计算值

访问props

访问 props 带来了 Vue 2 和 Vue 3 之间的重要区别——this意味着完全不同的东西。

在 Vue2 中,this几乎总是引用组件,而不是特定的属性。虽然这在表面上使事情变得容易,但它使类型支持变得痛苦。

然而,我们可以很容易地访问道具——让我们添加一个简单的例子,比如title在挂载的钩子中打印出我们的道具:

但是在 Vue 3 中,我们不再使用this来访问 props、发出事件和获取属性。相反,该setup()方法采用两个参数:

  • props– 对组件道具的不可变访问

  • context– Vue 3 公开的选定属性(emit、slots、attrs)

使用 props 参数,上面的代码看起来像这样。

Emitting事件

同样,在 Vue 2 中Emitting事件非常简单,但 Vue 3 让您可以更好地控制如何访问属性/方法。

假设在我们的例子中,当按下“提交”按钮时,我们想要向父组件发出登录事件。

Vue 2 代码只需要调用this.$emit并传入我们的有效负载对象。

然而,在 Vue 3 中,我们现在知道这this不再意味着同样的事情,所以我们必须以不同的方式来做。

幸运的是,上下文对象暴露emit给了我们同样的东西this.$emit

我们所要做的就是将context第二个参数添加到我们的设置方法中。我们将解构上下文对象以使我们的代码更简洁。

然后,我们只需调用 emit 来发送我们的事件。然后,就像以前一样,emit 方法接受两个参数:

  • 我们的活动名称

  • 与我们的事件一起传递的有效负载对象

 如何在 Vue 3 中创建应用程序和组件实例

在 Vue 3 中,你创建应用的方式发生了变化。Vue 应用程序现在使用新方法来创建应用程序实例。.createApp()

Vue 应用程序现在被视为根组件,因此您定义其数据选项的方式也发生了变化。

HTML 根元素尚未更改,因此在索引.html文件中,您仍将看到如下内容:

<div id="app"></div>

在 JavaScript 文件中,您需要了解一个重要的更改:您将不再用于创建新的应用程序实例,而是使用一个名为:new Vue()createApp()

// Vue 3 syntax

const app = Vue.createApp({
    // options object
})
app.mounth('#app') // Vue Instance - Root component

// Vue 2 syntax
const app = new Vue({
    // options object
    el: '#app'
})

如何在 Vue 3 中定义组件

要在 Vue 3 中定义组件,请不再使用 。相反,您现在使用应用程序根组件,如下所示:Vue.component()

/* Vue 3 syntax */
const app = Vue.createApp({
    // options here
})

app.component('componenet-name', {
    // component code here
})


/* Vue 2 syntax*/
Vue.component('component-name', {
    // component code here
})

如何在 Vue 3 中使用数据选项对象

假设主应用实例现在被视为根组件,则无法再将数据属性指定为对象。相反,您需要将其定义为返回对象的函数,就像通常在组件中所做的那样。

// Vue 3
const app = Vue.createApp({
    // options object
    data(){
        return {
            message: 'hi there'
        }
    }
})
app.mounth('#app') // Vue Instance - Root component

// Vue 2 syntax
const app = new Vue({
    // options object
    el: '#app'
    data: {
        message: 'hi there'
    }
})

Vue 3 中 v-if/v-for 的优先级更改

在 Vue 2 中,如果在同一元素上使用了两个指令,则 v-for 指令将优先于 v-if。但是在 Vue 3 中,v-if 总是优先。

但是,使用这两个指令并不是一个好主意。请务必访问此处的文档以了解更多信息。

如何在 Vue 3 中的组件事件上使用 Emits 属性(重大更改/新功能)

与该属性类似,现在在 Vue 3 中,还有一个属性,组件可以使用该属性来声明它可以向父组件发出的事件。propsemits

我强烈建议使用此属性,以避免在需要重新发出本机事件(如单击事件)的组件中两次发出事件。

以下是官方文档中的示例:

<template>
  <div>
    <p>{
   
   { text }}</p>
    <button v-on:click="$emit('accepted')">OK</button>
  </div>
</template>
<script>
  export default {
    props: ['text'],
    emits: ['accepted']
  }
</script>

emits 属性也可以接受对象。

我现在还不会深入探讨这个问题,但我保证迟早会在专门的视频系列中解决每个功能/变化。

Vue 路由器 v4.x 概述

随着 Vue.js 的新版本发布,我们也有了新版本的 Vue Router。新版本 v4.x 有一些重大更改,如果你想将项目迁移到新的 Vue 版本,你需要考虑这些更改。

Vue 路由器 V4 重大更改

两个重大更改特别值得一提,因为它们位于 Vue 路由器应用程序的基础。稍后需要了解它们才能迁移应用程序。

  • Vue 路由器实例已更改
  • 有一个新的历史记录选项

此处提供了更改的完整列表。

让我们深入看看这两个变化。

Vue 路由器 4 实例已更改

要创建新的 Vue 路由器实例,请不再使用 VueRuter 函数构造函数。

以下是 Vue Router v.3x 文档,因此您可以进行比较。

代码由以下原因更改:

// 3. Create the router instance and pass the `routes` option
// You can pass in additional options here, but let's
// keep it simple for now.
const router = new VueRouter({
  routes // short for `routes: routes`
})

// 4. Create and mount the root instance.
// Make sure to inject the router with the router option to make the
// whole app router-aware.
const app = new Vue({
  router
}).$mount('#app')

对此:

// 3. Create the router instance and pass the `routes` option
// You can pass in additional options here, but let's
// keep it simple for now.
const router = VueRouter.createRouter({
  // 4. Provide the history implementation to use. We are using the hash history for simplicity here.
  history: VueRouter.createWebHashHistory(), // <-- this is a new property and it is mandatory!
  routes, // short for `routes: routes`
})

// 5. Create and mount the root instance.
const app = Vue.createApp({})
// Make sure to _use_ the router instance to make the
// whole app router-aware.
app.use(router)

app.mount('#app')

在上面的代码中,要创建新的 Vue 路由器实例,您现在必须使用 VueRouter 对象并调用该方法。createRouter()

此外,新的历史记录属性是必需的 – 。您必须定义它,否则将收到控制台错误。history: VueRouter.createWebHashHistory()

接下来,您将使用该方法创建 Vue 实例,并使用变量来调用该方法。您将您在上一步中创建的路由器实例传递到该位置。createApp()app.use()

最后,您可以使用 在应用程序实例上挂载根 DOM 元素。app.mount('#app')

你可以阅读 Vue 路由器 v4.x 文档了解更多详情。

路由的变化:

main.js

// create and mount the Vue instance

const app = new Vue({
    router
}).$mount('#app')

对此:

// create and mount the Vue instance

const app = Vue.createApp({
    router
})
app.mount('#app')

Vue 路由器的实例化方式已更改

它从这个变化:

// create the router instance
const router = new VueRouter({
    routes
})

对此:

// create the router instance
const router = VueRouter.createRouter({
    // Provide the history implementation to use. We are using the hash history for simplicity here.
    history: VueRouter.createWebHashHistory(),
    routes, // short for `routes: routes`
})

上面的代码处理两个主要更改:已替换为 ,新选项现在将替换 。new VueRouter()VueRouter.createRouter()historymode

请访问 Vue 路由器 4 的文档以了解更多信息。

最后,让我们的应用程序知道我们正在使用 Vue 路由器。如果我们在 Vue 应用程序中注入了路由器实例,现在我们需要指示它使用 Vue 路由器,使用该方法执行此操作,并将路由器实例传递给它。.use()

由此更改:

// create and mount the Vue instance

const app = Vue.createApp({
    router
})
app.mount('#app')

对此:

// create and mount the Vue instance

const app = Vue.createApp({})
app.use(router)
app.mount('#app')

猜你喜欢

转载自blog.csdn.net/qq_22182989/article/details/125253780