迎接Vue3.0系列 | 如何在Vue2与Vue3中构建相同的组件

4月16日,Vue 开发团队终于在今天发布了 3.0-beta.1 版本,也就是测试版。通常来说,从测试版到正式版,只会修复 bug,不会引入新功能,或者删改老功能。所以,如果你对新版本非常感兴趣,或者有新项目即将上马,不妨尝试一下新版本。

迎接Vue3.0系列 | 如何在Vue2与Vue3中构建相同的组件

随着Vue3即将发布,许多人都在想“Vue2与Vue3有何不同?”

为了显示这些更改,我将在Vue2和Vue3中构建一个简单的表单组件。

在本文结尾,你将了解Vue2和Vue3之间的主要编程差异,并逐步成为一名更好的开发人员。

迎接Vue3.0系列 | 如何在Vue2与Vue3中构建相同的组件

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

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

Vue2

<code>

<

template

>

<

div

class

=

'form-element'

>

<

h2

>

{{ title }}

h2

>

<

input

type

=

'text'

v-model

=

'username'

placeholder

=

'Username'

/>

<

input

type

=

'password'

v-model

=

'password'

placeholder

=

'Password'

/>

<

button

@

click

=

'login'

>

Submit

button

>

<

p

>

Values: {{ username + ' ' + password }}

p

>

div

>

template

>

/<code>

唯一真正的区别是我们访问数据的方式。在Vue3中,我们的响应式数据都包装在响应式状态变量中——因此我们需要访问该状态变量以获取我们的值。

Vue3

<code>

<

template

>

<

div

class

=

'form-element'

>

<

h2

>

{{ state.title }}

h2

>

<

input

type

=

'text'

v-model

=

'state.username'

placeholder

=

'Username'

/>

<

input

type

=

'password'

v-model

=

'state.password'

placeholder

=

'Password'

/>

<

button

@

click

=

'login'

>

Submit

button

>

<

p

>

Values: {{ state.username + ' ' + state.password }}

p

>

div

>

template

>

/<code>
迎接Vue3.0系列 | 如何在Vue2与Vue3中构建相同的组件

这是主要的区别——Vue2 Options API与Vue3 Composition API。

Options API将我们的代码分为不同的属性:数据,计算属性,方法等。同时,Composition API允许我们按功能而不是属性类型对代码进行分组。

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

Vue2代码看起来是这样的——我们只需在 data 属性中放入两个值。

Vue2

<code>

export

default

{

props

: {

title

: String },

data

() {

return

{

username

:

''

,

password

:

''

} } }/<code>

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

另外,为了使开发人员能够更好地控制响应式,我们可以直接访问Vue的响应式API。

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

  • 从Vue导入 reactive
  • 使用 reactive 方法声明我们的数据
  • 让我们的 setup() 方法返回reactive数据,以便我们的模板可以访问它

在代码方面,它将看起来像这样。

Vue3

<code>

import

{ reactive }

from

'vue'

export

default

{

props

: {

title

:

String

}, setup () {

const

state = reactive({

username

:

''

,

password

:

''

})

return

{ state } } }/<code>

然后,在模板中,我们像 state.username 和 state.password 一样访问它们。

迎接Vue3.0系列 | 如何在Vue2与Vue3中构建相同的组件

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

Vue2

<code>

export

default

{

props

: {

title

: String },

data

() {

return

{

username

:

''

,

password

:

''

} },

methods

: { login () { } } }/<code>

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

Vue3

<code>

export

default

{

props

: {

title

:

String

}, setup () {

const

state = reactive({

username

:

''

,

password

:

''

})

const

login =

()

=>

{ }

return

{ login, state } } }/<code>
迎接Vue3.0系列 | 如何在Vue2与Vue3中构建相同的组件

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

Vue2

<code>

export

default

{

props

: {

title

: String },

data

() {

return

{

username

:

''

,

password

:

''

} },

mounted

() {

console

.log

(

'component mounted'

) },

methods

: {

login

() { } } }/<code>

现在有了Vue3 Composition API,几乎所有内容都在 setup() 方法内部,这包括 mounted 的生命周期钩子。

但是,默认情况下不包括生命周期挂钩,因此我们必须导入 onMounted 方法,作为Vue3中调用的方法,这看起来与早期导入 reactive 相同。

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

Vue3

<code>

import

{ reactive, onMounted }

from

'vue'

export

default

{

props

: {

title

:

String

}, setup () { onMounted(

()

=>

{

console

.log(

'component mounted'

) }) } }/<code>
迎接Vue3.0系列 | 如何在Vue2与Vue3中构建相同的组件

让我们添加一个计算属性,将我们的用户名转换为小写字母。为了在Vue2中完成此操作,我们将一个计算字段添加到我们的options对象中。

Vue2

<code>export 

default

{ computed: { lowerCaseUsername () {

return

this

.username.toLowerCase() } } }/<code>

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

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

然后,类似于我们之前创建 reactive 数据的方式,我们可以使一条 reactive 数据成为这样的计算值:

Vue3

<code>

import

{ reactive, onMounted, computed }

from

'vue'

export

default

{

props

: {

title

:

String

}, setup () {

const

state = reactive({

username

:

''

,

password

:

''

,

lowerCaseUsername

: computed(

()

=>

state.username.toLowerCase()) }) } }/<code>
迎接Vue3.0系列 | 如何在Vue2与Vue3中构建相同的组件

访问Props带来了Vue2和Vue3之间的一个重要区别——这意味着完全不同的东西。

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

以往,我们都可以轻松访问Props——让我们添加一个简单的示例,例如在mounted的钩子上打印出标题prop:

Vue2

<code>mounted () {
  

console

.log(

'title: '

+

this

.title) }/<code>

但是在Vue3中,我们不再使用它来访问Props、发出事件和获取属性。

相反,setup() 方法采用两个参数:

  • props——对组件prop的不可变访问
  • context——Vue3公开的选定属性(emit、slots、 attrs)

使用props参数,上面的代码将如下所示。

Vue3

<code>setup (props) {
   

  onMounted(

()

=>

{

console

.log(

'title: '

+ props.title) }) }/<code>
迎接Vue3.0系列 | 如何在Vue2与Vue3中构建相同的组件

类似地,在Vue2中发出事件非常简单,但是Vue3为您提供了对如何访问属性/方法的更多控制。

例如,在我们的例子中,我们想在按下“Submit”按钮时向父组件发出登录事件。

Vue2代码只需要调用 this.$emit 并传入我们的有效参数对象即可。

Vue2

<code>login () {
  

this

.$emit(

'login'

, { username:

this

.username, password:

this

.password }) }/<code>

然而,在Vue3中,我们现在知道这不再意味着同样的事情,所以我们必须做得不同。

幸运的是,上下文对象(context)公开了 emit,这使我们拥有与此相同的东西。

我们要做的就是将 context 添加为 setup() 方法的第二个参数,我们将解构上下文对象,以使我们的代码更简洁。

然后,我们只需要调用emit发送事件即可。然后,像以前一样,emit方法采用两个参数:

  • 事件名称
  • 与事件一起传递的有效参数对象

Vue3

<code>setup (props, { emit }) {
   

  

const

login =

()

=>

{ emit(

'login'

, {

username

: state.username,

password

: state.password }) } }/<code>
迎接Vue3.0系列 | 如何在Vue2与Vue3中构建相同的组件

如您所见,Vue2和Vue3中的所有概念都是相同的,但是我们访问属性的某些方式已经有所变化。

总的来说,我认为Vue3将帮助开发人员编写更有组织的代码——特别是在大型代码库中。这主要是因为Composition API允许您按特定功能将代码分组在一起,甚至可以将功能提取到自己的文件中,然后根据需要将其导入组件中。

Vue2中用于表单组件的完整代码:

<code>

<

template

>

<

div

class

=

'form-element'

>

<

h2

>

{{ title }}

h2

>

<

input

type

=

'text'

v-model

=

'username'

placeholder

=

'Username'

/>

<

input

type

=

'password'

v-model

=

'password'

placeholder

=

'Password'

/>

<

button

@

click

=

'login'

>

Submit

button

>

<

p

>

Values: {{ username + ' ' + password }}

p

>

div

>

template

>

<

script

>

export

default

{

props

: {

title

:

String

}, data () {

return

{

username

:

''

,

password

:

''

} }, mounted () {

console

.log(

'title: '

+

this

.title) },

computed

: { lowerCaseUsername () {

return

this

.username.toLowerCase() } },

methods

: { login () {

this

.$emit(

'login'

, {

username

:

this

.username,

password

:

this

.password }) } } }

script

>

/<code>

这是在Vue3中的完整代码:

<code>

<

template

>

<

div

class

=

'form-element'

>

<

h2

>

{{ state.title }}

h2

>

<

input

type

=

'text'

v-model

=

'state.username'

placeholder

=

'Username'

/>

<

input

type

=

'password'

v-model

=

'state.password'

placeholder

=

'Password'

/>

<

button

@

click

=

'login'

>

Submit

button

>

<

p

>

Values: {{ state.username + ' ' + state.password }}

p

>

div

>

template

>

<

script

>

import

{ reactive, onMounted, computed }

from

'vue'

export

default

{

props

: {

title

:

String

}, setup (props, { emit }) {

const

state = reactive({

username

:

''

,

password

:

''

,

lowerCaseUsername

: computed(

()

=>

state.username.toLowerCase()) }) onMounted(

()

=>

{

console

.log(

'title: '

+ props.title) })

const

login =

()

=>

{ emit(

'login'

, {

username

: state.username,

password

: state.password }) }

return

{ login, state } } }

script

>

/<code>

我希望本教程有助于重点介绍Vue代码在Vue3中看起来与众不同的某些方式。如有其他疑问,请留下你的意见!

如果对你有所启发和帮助,可以点个关注、收藏、转发,也可以留言讨论,这是对作者的最大鼓励。

作者简介:Web前端工程师,全栈开发工程师、持续学习者。

私信回复大礼包送某网精品视频课程网盘资料,准能为你节省不少钱!

#科技青年# #423头条知识节#


分享到:


相關文章: