随着Vue3即将发布,许多人都在想”Vue2与Vue3有何不同?”
尽管我们之前已经写过有关重大变化的文章,但实际上并没有真正深入地了解我们的代码将如何变化。因此,为了显示这些更改,我们将在Vue2和Vue3中构建一个简单的表单组件。
在本文中,您将了解Vue2和Vue3之间的主要编程差异,并逐步成为一名更好的开发人员。
如果您想知道如何构建第一个Vue3应用程序,请查阅Vue3 Composition API教程及示例。
让我们开始吧!
对于大多数组件,Vue2和Vue3中的代码将非常相似。但是,Vue3支持Fragments,这意味着组件可以具有多个根节点。
在渲染列表中的组件时,可以减少不必要的包装div元素,这特别有用。在这种情况下,我们将为两个版本的Form组件保留一个根节点。
<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>
唯一真正的区别是我们访问数据的方式。在Vue3中,我们的响应式数据都包装在一个响应式状态变量中,因此我们需要访问该状态变量以获取我们的值。
<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>
这是一个重大的区别:Vue2 Options API与Vue3 Composition API。
Options API将我们的代码分为不同的属性:数据,计算属性,方法等。但是,Composition API允许我们按功能而不是属性的类型对代码进行分组。
假设对于表单组件,我们只有两个数据属性:用户名和密码。
Vue2代码:
export default {
props: {
title: String
},
data() {
return {
username: '',
password: ''
}
}
}
在Vue 3.0中,我们必须通过使用新的setup()方法进行更多的工作,在该方法中应进行所有组件初始化。
另外,为了使开发人员能够更好地控制数据响应,我们可以直接访问Vue的 reactive API。
创建响应性数据包含三个步骤:
代码如下:
import { reactive } from 'vue'
export default {
props: {
title: String
},
setup() {
const state = reactive({
username: '',
password: ''
})
return { state }
}
}
然后,在模板中,我们可以使用state.username和state.password访问它们
Vue2 Options API有一个单独的方法部分。在其中,我们可以定义所有方法并以所需的任何方式组织它们。
export default {
props: {
title: String
},
data() {
return {
username: '',
password: ''
}
},
methods: {
login() {
// login method
}
}
}
Vue3 Composition API中的setup方法也可以处理方法。它的工作方式与声明数据有些类似。我们必须先声明我们的方法,然后返回它,以便组件的其他部分可以访问它。
export default {
props: {
title: String
},
setup() {
const state = reactive({
username: '',
password: ''
})
const login = () => {
// login method
}
return {
login,
state
}
}
}
在Vue2中,我们可以直接在组件选项中设置生命周期钩子。
export default {
props: {
title: String
},
data() {
return {
username: '',
password: ''
}
},
mounted() {
console.log('component mounted')
},
methods: {
login() {
// login method
}
}
}
现在有了Vue3 Composition API,几乎所有内容都在setup()方法内部。这包括mounted生命周期钩子。
但是,默认情况下不包括生命周期钩子,我们必须导入onMounted方法,作为Vue3中调用的方法。这与之前导入reactive相同。
然后,在setup方法中,可以通过给onMounted方法传递函数参数来使用它。
import { reactive, onMounted } from 'vue'
export default {
props: {
title: String
},
setup() {
// ..
onMounted(() => {
console.log('component mounted')
})
// ...
}
}
让我们添加一个计算属性,将我们的用户名转换为小写字母。
为了在Vue2中完成此操作,我们需要添加computed字段到我们的options对象中。我们可以像这样定义我们的属性:
export default {
// ..
computed: {
lowerCaseUsername () {
return this.username.toLowerCase()
}
}
}
Vue3的设计允许开发人员导入他们使用的内容。本质上,它不希望开发人员必须包含从未使用过的东西,这在Vue2中正成为一个日益严重的问题。
因此,要在Vue3中使用计算属性,我们首先必须将computed导入到组件中。
然后,类似于我们之前创建响应式数据的方式,我们可以使一个响应式数据成为这样的计算值:
import { reactive, onMounted, computed } from 'vue'
export default {
props: {
title: String
},
setup() {
const state = reactive({
username: '',
password: '',
lowerCaseUsername: computed(() => state.username.toLowerCase())
})
// ...
}
}
访问Props带来了Vue2和Vue3之间的重要区别。
在Vue2中,我们可以轻松访问P。让我们添加一个简单的示例,例如在加载完成钩子上打印出标题属性:
mounted() {
console.log('title: ' + this.title)
}
但是在Vue3中,我们不再使用this来访问Props,发出事件和获取属性。现在setup()方法采用了两个参数:
使用props参数,上面的代码将如下所示:
setup(props) {
// ...
onMounted(() => {
console.log('title: ' + props.title)
})
// ...
}
同样,在Vue2中发出事件非常简单,但是Vue3使您可以更好地控制如何访问属性/方法。
假设在我们的情况下,我们想在按下“提交”按钮时向父组件发出一个登录事件。
Vue2代码只需要调用this.$emit并传入我们的payload对象即可。
login() {
this.$emit('login', {
username: this.username,
password: this.password
})
}
但是,在Vue3中,我们不能再直接使用this.$emit。
幸运的是,上下文context对象公开了emit方法。
我们要做的就是将context添加为setup()方法的第二个参数。我们将解构上下文对象,以使我们的代码更简洁。
然后,我们只需要调用emit发送事件即可。像以前一样,emit方法采用两个参数:
setup(props, { emit }) {
// ...
const login = () => {
emit('login', {
username: state.username,
password: state.password
})
}
// ...
}
我们已经完成了。如您所见,Vue2和Vue3中的所有概念都是相同的,但是我们访问属性的某些方式已经有所改变。
总的来说,我认为Vue3将帮助开发人员编写更有组织的代码,尤其是在大型项目中。这主要是因为Composition API允许我们按照特定功能将代码组织在一起,甚至可以将功能提取到单独文件中,然后根据需要将其导入组件中。
在Vue2中用于表单组件的代码:
<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>
在Vue3中:
<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>
希望本教程能够帮助您了解和上手Vue代码在Vue3中不同表现形式。编码愉快!