认识Mixin
组件和组件之间有时会存在相同的代码逻辑,可以使用mixin对相同代码逻辑进行抽取。
编写一个mixin.js文件
export const demoMixin = {
data() {
return {
message: 'helloworld'
}
},
methods: {
foo() {
console.log('执行mixin')
}
}
}
在要使用的组件中引入
import {demoMixin} from './mixins/demoMixin'
export default {
mixins: [demoMixin],
}
此时可以使用mixin中的data或methods等
mixin合并规则
- 如果是data返回值对象,重名了以当前组件为准
- 生命周期:生命周期的钩子函数会被合并到数组中,都会被调用
- 如果值为对象,例如methods,components,重名了以当前组件为准
全局混入
在main.js中
app.mixin({
data() {
},
methods: {
}
})
setup函数
setup其实就是组件的另一个选项,这个选项强大到可以替代之前编写的大部分其他选项,比如methods,computed,watch等等
setup参数
setup(props,context){
}
props是父组件传递来的值被放在props对象中,因为setup函数不绑定this。 context包含三个属性
- attrs:所有非props的attribute。例如子组件中绑定的id,class等。
- slots:父组件传来的插槽
<home>
<template #default>
</template>
</home>
- emit.发送事件。
setup返回值
返回值是一个对象,也就是说可以将setup里的返回值当作vue2的data使用。但是这样是没有响应式的。
<template>
<div class="hello">
{{ title }}
</div>
</template>
setup() {
return {
title: '桂林山水甲天下'
}
}
reactiveAPI
写一个简单的计数器
<template>
<div class="hello">
<button @click="increment">+1</button>
{{ counter }}
</div>
</template>
setup(props,{attrs}) {
let counter = 100;
const increment = () => {
counter++;
console.log(counter);
}
return {
counter,
increment,
}
}
此时发现counter不是响应式的 需要引入一个reactive函数,此时代码修改为
<template>
<div class="hello">
{{ title }}
<button @click="increment">+1</button>
{{ state.counter }}
</div>
</template>
<script>
import { reactive } from 'vue';
export default {
name: 'HelloWorld',
props: {
msg: String
},
setup(props,{attrs}) {
const state = reactive({
counter: 100
})
const increment = () => {
state.counter++;
}
return {
title: '桂林山水甲天下',
state,
increment,
}
}
}
</script>
Ref APi
reactiveAPI要求我们传入的是一个对象或者数组类型,如果传入一个基本数据类型会报一个警告, 此时可以使用一个refAPI。ref会返回一个可变的响应式对象,该对象作为一个响应式的引用维护着它内部的值,这就是ref名称的来源。它内部的值是在ref的value属性中被维护的。
<template>
<div class="hello">
{{ title }}
<button @click="increment">+1</button>
<!-- 当我们在template模板中使用ref对象,它会自动进行解包 -->
{{ counter }}
</div>
</template>
<script>
// import { reactive } from 'vue';
import { ref } from 'vue';
export default {
name: 'HelloWorld',
props: {
msg: String
},
setup(props,{attrs}) {
let counter = ref(100)
const increment = () => {
counter.value++;
}
return {
title: '桂林山水甲天下',
counter,
increment,
}
}
}
在开发中推荐使用ref,(codewhy讲的) ref解包是一个浅层解包,如果
//此时{{info.counter}}不会正常显示
counter = ref(100)
info = {
counter
}
认识readOnlyAPI
我们可以通过reactive或者ref获取到一个响应式对象,但是在某些情况下,我们传入其他地方的这个响应式对象希望在另一个地方被使用,但不能被修改。此时可以使用readOnly。
<template>
<div class="hello">
<button @click="updateState">修改</button>
</div>
</template>
<script>
import { reactive, ref,readonly } from 'vue';
export default {
name: 'HelloWorld',
props: {
msg: String
},
setup(props,{attrs}) {
let counter = ref(100);
const info = {
name: 'juju'
}
// 1.普通对象
const readonlyInfo = readonly(info);
//2.响应式对象
const info2 = reactive({
name: 'juju'
})
const readonlyinfo2 = readonly(info2)
//3.ref对象
const info3 = ref("juju");
const readonlyinfo3 = readonly(info3);
const updateState = () => {
readonlyInfo.name = 'why';
readonlyinfo2.name = 'why';
readonlyinfo3.value = 'why'; //通过返回的readonlyInfo代理修改会报警告
}
return {
updateState
}
}
}
此时修改readonly对象会报警告