1.认识Mixin
由于组件和组件之间有时候存在相同的代码逻辑,我们希望对相同的代码逻辑进行抽取。 Mixin提供了一种非常灵活的方式帮我们进行 mixin是一个对象,比如: demoMixin.js
export const demoMixin = {
data(){
return {
msg:'hello mixin'
}
},
methods:{
foo(){
console.log('demo mixin')
}
},
created(){
console.log('created')
this.foo()
}
}
App.vue
<template>
<div>{{msg}}</div>
<button @click="foo">1111</button>
</template>
<script>
import {demoMixin} from "./components/01_mixin和extend/demoMixin.js"
export default {
name: 'App',
mixins:[demoMixin],
}
</script>
可见,即使我们没有定义过msg变量和foo方法,我们依然可以通过混入,直接调用
mixin混入的合并规则:
1.对于data中相同的变量名:冲突时,优先当前组件的变量
2.声明周期合并时,将多个声明周期钩子放入数组中,全部执行
3.对象类型合并时,直接合并
全局混入Mixin:
main.js
import { createApp } from 'vue'
import App from './App.vue'
import { demoMixin } from './components/01_mixin和extend/demoMixin'
const app = createApp(App)
app.mixin(demoMixin)
app.mount('#app')
这样,所有的组件就可以用demomixin中的数据和方法了!
2.extends
extends在扩展继承第三方组件上功劳很大,不仅保留了原组件的所有功能,还能按照你所需覆盖原有功能,和mixins的区别是:mixins不会覆盖方法和生命周期钩子,但是extends会。
<template>
<div>
<h2>home</h2>
<div>{{msg}}</div>
</div>
</template>
<script>
import titleVue from "./title.vue"
export default {
extends:titleVue,
}
</script>
3.composition API
在optionAPI中,单文件中的一个功能模块的代码是分离开的,过于分散,难以阅读和理解。因此vue3提出了全新的api
vue3的灵魂:setup函数
3.1 setup的参数
<template>
<div>
<h2>new API</h2>
<button @click="btnClick">按钮</button>
</div>
</template>
<script>
export default {
props:{
message:String
},
// setup函数的参数:props,context
// setup函数的返回值
// setup中没有绑定this,不能使用
setup(props,context){
// props,父组件传递过来的属性
console.log(props)
// context包含三个属性 1.attrs,2.slots,3.emit
const {attrs,slots,emit} = context
}
}
</script>
setup接受两个参数 props和context:
props: 接受父组件传递过来的属性
context: 包含三个属性-attrs、slots和emit
3.2 setup的返回值
setup可以返回一个对象,其中的属性可以在template中使用
setup(props,context){
// props,父组件传递过来的属性
console.log(props)
// context包含三个属性 1.attrs,2.slots,3.emit
const {attrs,slots,emit} = context
let counter = 0
const increment = ()=>{
counter++
}
return {
title:'add the counter',
name:'wjm',
counter,
increment
}
}
返回的属性和方法都可以在template中使用,但此时,setup返回对象中的数据并不是响应式的;
reactive API
如果想要为setup中的数据提供响应式的特性,我们可以用vue提供的reactive对要响应式的数据进行包裹
<script>
import {reactive} from 'vue'
export default {
props:{
message:String
},
setup(props,context){
const {attrs,slots,emit} = context
const state = reactive({
counter:0
})
const increment = ()=>{
state.counter++
}
return {
title:'add the counter',
name:'wjm',
state,
increment
}
}
}
</script>
ref API
也可以使用vue提供的ref
<script>
import {ref} from 'vue'
export default {
setup(props,context){
let counter = ref(0)
const increment = ()=>{
//需要修改时,对value属性修改
counter.value++
}
return {
title:'add the counter',
name:'wjm',
counter,
increment
}
}
}
</script>
调用ref方法后,返回一个可变的响应式对象,其内部的值是在value属性中保存的
如果要在template中使用时,vue会帮我们自动解包,直接使用即可,不必调用value
ref的解包只能是一个浅层解包,将ref包裹进对象后就不能解包了
readonly API
如果我们传入给其他组件的响应式对象,希望其使用,但是不能被修改,vue3为我们提供了readonly方法
readonly会返回原生对象的只读代理,(set方法被劫持的proxy)
<script>
import {reactive,ref,readonly} from 'vue'
export default {
setup(){
// 普通对象
const info1 = {name:'wjm'};
const readonlyInfo1 = readonly(info1)
// 响应式对象 reactive
const info2 = reactive({
name:'wjm'
})
const readonlyinfo2 = readonly(info2)
// 响应式对象 ref
const info3 = ref('wjm')
const readonlyinfo3 = readonly(info3)
const updateState = ()=>{
info3.value = 'mr wu'
}
return {
updateState
}
}
}
</script>
3.3 setup不绑定this
在setup被调用之前,data,computed,methods等都没有被解析;源码中,options处理部分在setup的调用时,没有绑定任何this,所以无法在setup中获取this