Vue 3.0 项目初始化
第一步,安装 vue-cli:
npm install -g @vue/cli
第二步,初始化 vue 项目:
vue create vue-next-test
升级 Vue 3.0 项目
目前创建 Vue 3.0 项目需要通过插件升级的方式来实现,
vue-cli 还没有直接支持,我们进入项目目录,并输入以下指令:
cd vue-next-test
vue add vue-next
vue2.0 vs 3.0
- 默认进行懒观察(按需监听)
在 2.x 版本里,不管数据多大,都会在一开始就为其创建观察者。当数据很大时,这可能会在页面载入时造成明显的性能压力。3.x 版本,只会对「被用于渲染初始可见部分的数据」创建观察者,而且 3.x 的观察者更高效
- 核心方法不同
vue2:使用 Object.difinePropertype 方法,如果数据的层次过多,需要递归的去解析对象中的属性,依次增加 set 和 get 方法
vue3: 使用 proxy方法,proxy不需要递归,也不需要给属性添加 get 和 set 方法,所以性能提升2-3倍
- 更精准的变更通知。
举例来说:2.x 版本中,使用 Vue.set 来给对象新增一个属性时,这个对象的所有 watcher 都会重新运行;3.x 版本中,只有依赖那个属性的 watcher 才会重新运行
- 3.0 新加入了 TypeScript 以及 PWA 的支持
- 按需引入
Vue2.x中new出的实例对象,所有的东西都在这个vue对象上,这样其实无论你用到还是没用到,都会跑一变。而vue3.0中可以用ES module imports按需引入,如:keep-alive内置组件、v-model指令,等等。
生命周期
vue3.0中取消了 beforeCreate 和 created 两个周期,因为setup会在这个这个周期前执行,因此你可以在setup中进行你需要的处理。其他的生命周期全部以on开头。
import {
onBeforeMount,
onMounted,
onBeforeUnmount,
onBeforeUpdate,
onDeactivated,
onUnmounted,
onUpdated
} from '@vue/composition-api'
export default {
setup(){
onBeforeMount(() =>{
console.log('onBeforeMount');
})
onMounted(() =>{
console.log('onMounted');
})
onBeforeUnmount(() =>{
console.log('onBeforeUnmount');
})
onBeforeUpdate(() =>{
console.log('onBeforeUpdate');
})
onDeactivated(() =>{
console.log('onDeactivated');
})
onUnmounted(() =>{
console.log('onUnmounted');
})
onUpdated(() =>{
console.log('onUpdated');
})
}
}
状态和事件绑定
Vue 3.0 中定义状态的方法改为类似 React Hooks 的方法
Vue 3.0 中初始化状态通过 setup 方法,
定义状态需要调用 ref 方法。接下来我们定义一个事件,用来更新 count 状态:
<template>
<div class="test">
<h1>test count: {{count}}</h1>
<button @click="add">add</button>
</div>
</template>
<script>
import { ref } from 'vue'
export default {
setup () {
const count = ref(0)
const add = () => {
count.value++
}
return {
count,
add
}
}
}
</script>
count 值的时候不能直接使用 count++,而应使用 count.value++
计算属性和监听器
<template>
<div class="test">
<h1>test count: {{count}}</h1>
<div>count * 2 = {{doubleCount}}</div>
<button @click="add">add</button>
</div>
</template>
<script>
import { ref, computed, watch } from 'vue'
export default {
setup () {
const count = ref(0)
const add = () => {
count.value++
}
watch(() => count.value, val => {
console.log(`count is ${val}`)
})
const doubleCount = computed(() => count.value * 2)
return {
count,
doubleCount,
add
}
}
}
</script>
获取路由
<script>
import { getCurrentInstance } from 'vue'
export default {
setup () {
const { ctx } = getCurrentInstance()
console.log(ctx.$router.currentRoute.value)
}
}
</script>
vuex
store/ index.js
import Vuex from 'vuex'
export default Vuex.createStore({
state: {
test: {
a: 1
}
},
mutations: {
setTest(state, val) {
console.log(val);
state.test.a = val
}
}
});
// 调用
<template>
<div class="test">
<h1>a: {{a}}</h1>
<button @click="update">update vuex</button>
</div>
</template>
<script>
import { getCurrentInstance } from 'vue'
export default {
setup () {
const { ctx } = getCurrentInstance()
const a = computed(() => ctx.$store.state.test.a)
const update = () => {
ctx.$store.commit('setTest', count)
}
return {
count,
add,
newCount,
a,
update
}
}
}
</script>
模块化
<template>
<div class="test">
<h1>test count: {{count}}</h1>
<button @click="addFn">add</button>
<button @click="removeFn">remove</button>
</div>
</template>
<script>
import { ref, onBeforeMount } from 'vue'
export default {
setup () {
const count = ref(0)
const add = addFn(count)
const remove = removeFn(count)
return {
...add,
...remove,
count
}
}
}
function addFn(count) {
const addFn = () => {
count.value ++
}
return {
addFn
}
}
function removeFn(count) {
const removeFn = () => {
count.value --
}
return {
removeFn
}
}
</script>