新特性
vue-composition-api-rfc.netlify.app/zh/api.html…
- ref、reactive、computed、watch
- 新的生命周期
- 自定义钩子函数
- Teleport(组件位置替换)
- Suspense(异步加载组件实现)
- 全局Api、配置项的优化
- 更好的支持typescript
全局api和初始化应用的变化
全局config
vue3将全局配置挂在了app实例上而不是构造函数上,好处是是的应用之间的配置互不影响
//vue2的全局config配置是直接挂在Vue构造函数上的
//例如
Vue.config.errorHandler = (err)=>console.log(err)
//vue3的全局api是在当前应用实例上修改的,不会影响其他应用
//例如
const app1 = createApp(AppComponent1)
const app2 = createApp(AppComponent2)
app1.config.errorHandler.(err)=>console.log(err,'app1')
app2.config.errorHandler.(err)=>console.log(err,'app2')
全局方法
vue3为了减小打包体积,将很多方法都采用了具名导出的方式(如 createApp、nextTick等),这使得初始化实例的方式也有所区别
例如:
const app1 = createApp(AppComponent1)
const app2 = createApp(AppComponent2)
因为vue3不再有Vue构造函数,所以一些全局的自定义属性或者方法也没法通过Vue.prototype.xx挂在到vm实例上,这时候需要借助app.config.globalProperties来实现这一功能
例如:
//如果项目采用了typescript,那么就需要扩展一下`@vue/runtime-core`模块,否则在使用的时候会报找不到$http属性
//在main.ts加上如下代码
declare module '@vue/runtime-core' {
interface ComponentCustomProperties {
$http: any;
}
}
app.config.globalProperties.$http = () => {
//do something
}
vue3的中间件也是通过每个应用实例下的use方法去注册,且支持链式调用
app1.use(middleware1).use(middleware2).mount('#app')
composition Api
ref
需要注意的是setup返回的变量都是Ref类型,修改ref的值需要修改ref.value,在其他的方法中也能通过this.xx直接修改
使例子
<template>
<div class="test-font">
{{ msg }}
</div>
<button class="test-button" @click="changeMsg">修改msg</button>
</template>
<script lang="ts">
import { defineComponent, ref } from "vue";
export default defineComponent({
setup() {
const msg = ref("hello ref");
setTimeout(() => {
msg.value = "1000ms after";
}, 1000);
return {
msg,
};
},
methods: {
changeMsg() {
this.msg = "this is change msg";
},
},
});
</script>
computed
computed接收一个函数,改函数的返回值作为计算属性的值
<template>
<div class="test-font">
<div>num:{{ num }}</div>
<div>double-num:{{ doubleNum }}</div>
<button class="test-button" @click="addOne">+1</button>
</div>
</template>
<script lang="ts">
import { defineComponent, ref, computed } from "vue";
export default defineComponent({
setup() {
const num = ref(0);
const doubleNum = computed(() => {
return num.value * 2;
});
const addOne = () => {
num.value++;
};
return {
num,
doubleNum,
addOne,
};
},
});
</script>
reactive
在setup中,reactive可以为我们集中定义属性
<template>
<div class="test-font">
<div>name:{{ name }}</div>
<div>age:{{ age }}岁</div>
<div>height:{{ height }}米</div>
<div>weight:{{ weight }}公斤</div>
<div>weight-2:{{ weight2 }}斤</div>
<div>attr:{{ attr }}</div>
<div>淦饭了没:{{ eat }}</div>
<button class="test-button" @click="changeMsg">淦饭</button>
</div>
</template>
<script lang="ts">
import { defineComponent, reactive, toRefs, computed } from "vue";
interface DataProps {
name: string;
age: number;
height: number;
weight: number;
weight2: number;
attr: string;
eat: string;
changeMsg: () => void;
}
export default defineComponent({
setup() {
const data: DataProps = reactive({
name: "熊志强",
age: 18,
height: 1.85,
weight: 135,
weight2: computed(() => {
return data.weight / 2;
}),
attr: "帅一批",
eat: "没有",
changeMsg: () => {
data.eat = "淦了";
},
});
return {
...toRefs(data),
};
},
});
</script>
watch监听
vue3提供了再setup中使用的数据监听函数watch,因为setup只是在初始化的时候调用一次,无法根据数据变化实时调用,所以提供了watch方法解决这个问题
下面是wacth方法的简单使用实例:
setup(){
//监听单个的ref
const a = ref(0)
watch(a,(newval,oldval)=>{
console.log(newval,oldval)
})
//监听多个ref
const b = ref(0)
watch([a,b],(newval,oldval)=>{
console.log(newval,oldval)
})
//监听reactive
const reactiveData = reactive({
a:1,
b:2,
c:3
})
watch(data,(newVal,oldVal)=>{
console.log(newVal,oldVal)
})
//监听reactive下的某一个属性
watch([()=>data.a,()=>data.b],(newVal,oldVal)=>{
console.log(newVal,oldVal)
})
}
provide、inject
根组件注入
//parent Component
import {provide,ref} from 'vue'
setup(){
const foo = ref('')
provide('foo',foo)
}
//descendant component
import {inject} from 'vue'
setup(){
const foo = inject('foo','默认值')
return{
foo
}
}
ps:如果setup中有异步操作,inject必须在异步操作之前
路由相关
import {useRoute,useRouter} from ''vue-router
setup(){
const route = useRoute() //等同于vue2的this.$route
const router = useRouter() //等同于vue2的this.$router
}
生命周期
有两个生命周期名称修改以及两个新增
// 修改的
beforeDestroy -> beforeUnmount
destroyed -> unmounted
//新增的
renderTracked
renderTriggered
vue3提供了在setup中使用的生命周期函数
/*
生命周期函数对应表
beforeCreate -> 与setup并行
created -> 与setup并行
beforeMount -> onBeforeMount
mounted -> onMounted
beforeUpdate -> onBeforeUpdate
updated -> onUpdated
beforeUnmount -> onBeforeUnmount
unmounted -> onUnmounted
errorCaptured -> onErrorCaptured
renderTracked -> onRenderTracked
renderTriggered -> onRenderTriggered
*/
import { onMounted } from 'vue'
defineComponent({
setup(){
onMounted(() => { console.log('mounted') })
}
})
变更
- .sync修饰符 => v-model:propName
目前遇到的问题
- keep-alive不可用