1. setup
组合式api,在before create之前执行( 没法用this ), 属性,方法,生命周期钩子函数都写在这里面,要想在模版中使用setup中定义的属性或方法,记得要return出去
另外,在setup中使用vue的api或者一些函数时,要先引入
import { defineComponent, getCurrentInstance, ref, onMounted } from 'vue';
参数: setup( props, context ) { }
-
props 一个对象,里边有父组件向子组件传递的数据,子组件中使用props接受到的所有属性 -
context 上下文对象 setup( props, { attrs, slots, emit } ) attrs 是属性,相当于this.$attrs slots 插槽 相当于this.$slots emit 自定义事件 相当于this.$emit
2. 组合Api
-
ref 定义简单类型的响应式数据 const name = ref('张三')
另外,ref 获取元素 vue2中 获取
直接this.$refs.test vue3中 获取
需要 setup () {
const test = ref(null)
onMounted(() => {
console.log('test.value', test.value);
})
}
-
reactive 定义复杂类型的响应式数据 const obj = reactive({
name: '张三',
age: 18
})
-
toRef 转换响应式对象中某个属性为单独响应式数据
const obj = reactive({
name: '张三',
age: 18
})
const name = toRef(obj, 'name')
-
toRefs 转换响应式对象中所有属性为单独响应式数据,对象成为普通对象 setup () {
const obj = reactive({
name: '张三',
age: 10
})
console.log(obj)
const obj3 = toRefs(obj)
console.log(obj3)
const updateName = () => {
obj.name = '李四'
}
return {...obj3, updateName}
}
-
computed 计算属性 <template>
<div class="container">
<div>今年:{{age}}岁</div>
<div>后年:{{newAge}}岁</div>
</div>
</template>
<script>
import { computed, ref } from 'vue'
export default {
name: 'App',
setup () {
const age = ref(16)
const newAge = computed(()=>{
return age.value + 2
})
const newAge = computed({
get(){
return age.value + 2
},
set (value) {
age.value = value - 2
}
})
return {age, newAge}
}
}
</script>
-
watch 监听器 监听ref定义的响应式数据 监听多个响应式数据数据 监听reactive定义的响应式数据 监听reactive定义的响应式数据,某一个属性 深度监听 deep: true 默认执行 immediate: true <template>
<div class="container">
<div>
<p>count的值:{{count}}</p>
<button @click="add">改数据</button>
</div>
<hr>
<div>
<p>{{obj.name}}</p>
<p>{{obj.age}}</p>
<p>{{obj.brand.name}}</p>
<button @click="updateName">改名字</button>
<button @click="updateBrandName">改品牌名字</button>
</div>
</div>
</template>
<script>
import { reactive, ref, watch } from 'vue'
export default {
name: 'App',
setup () {
const count = ref(0)
const add = () => {
count.value++
}
const obj = reactive({
name: 'ls',
age: 10,
brand: {
id: 1,
name: '宝马'
}
})
const updateName = () => {
obj.name = 'zs'
}
const updateBrandName = () => {
obj.brand.name = '奔驰'
}
watch(obj, ()=>{
console.log('数据改变了')
})
watch(()=>obj.brand, ()=>{
console.log('brand数据改变了')
},{
deep: true,
immediate: true
})
return {count, add, obj, updateName, updateBrandName}
}
}
</script>
-
父子组件之间通讯 props emit 父子组件之间传值,在vue2中,父传子是通过在子组件中props接受父组件中传递的值,子传父是通过this.$emit 抛出一个事件 在vue3中,大概也是这样,只是写法不同
-
父传子 在setup种使用props数据 setup(props){ // props就是父组件数据 } <template>
<div class="container">
<h1>父组件</h1>
<p>{{money}}</p>
<hr>
<Son :money="money" />
</div>
</template>
<script>
import { ref } from 'vue'
import Son from './Son.vue'
export default {
name: 'App',
components: {
Son
},
setup () {
const money = ref(100)
return { money }
}
}
</script>
<template>
<div class="container">
<h1>子组件</h1>
<p>{{money}}</p>
</div>
</template>
<script>
import { onMounted } from 'vue'
export default {
name: 'Son',
props: {
money: {
type: Number,
default: 0
}
},
setup (props) {
console.log(props.money)
}
}
</script>
-
子传父 触发自定义事件的时候emit来自 setup(props,{emit}){ // emit 就是触发事件函数 } <template>
<div class="container">
<h1>父组件</h1>
<p>{{money}}</p>
<hr>
+ <Son :money="money" @change-money="updateMoney" />
</div>
</template>
<script>
import { ref } from 'vue'
import Son from './Son.vue'
export default {
name: 'App',
components: {
Son
},
setup () {
const money = ref(100)
+ const updateMoney = (newMoney) => {
+ money.value = newMoney
+ }
+ return { money , updateMoney}
}
}
</script>
<template>
<div class="container">
<h1>子组件</h1>
<p>{{money}}</p>
+ <button @click="changeMoney">花50元</button>
</div>
</template>
<script>
import { onMounted } from 'vue'
export default {
name: 'Son',
props: {
money: {
type: Number,
default: 0
}
},
+ setup (props, {emit}) {
console.log(props.money)
+ const changeMoney = () => {
+ emit('change-money', 50)
+ }
+ return {changeMoney}
}
}
</script>
-
依赖注入 provide和inject 使用场景:有一个父组件,里头有子组件,有孙组件,有很多后代组件,共享父组件数据。 <template>
<div class="container">
<h1>父组件 {{money}} <button @click="money=1000">发钱</button></h1>
<hr>
<Son />
</div>
</template>
<script>
import { provide, ref } from 'vue'
import Son from './Son.vue'
export default {
name: 'App',
components: {
Son
},
setup () {
const money = ref(100)
const changeMoney = (saleMoney) => {
console.log('changeMoney',saleMoney)
money.value = money.value - saleMoney
}
provide('money', money)
provide('changeMoney', changeMoney)
return { money }
}
}
</script>
<style scoped lang="less"></style>
<template>
<div class="container">
<h2>子组件 {{money}}</h2>
<hr>
<GrandSon />
</div>
</template>
<script>
import { inject } from 'vue'
import GrandSon from './GrandSon.vue'
export default {
name: 'Son',
components: {
GrandSon
},
setup () {
const money = inject('money')
return { money }
}
}
</script>
<style scoped lang="less"></style>
<template>
<div class="container">
<h3>孙组件 {{money}} <button @click="fn">消费20</button></h3>
</div>
</template>
<script>
import { inject } from 'vue'
export default {
name: 'GrandSon',
setup () {
const money = inject('money')
const changeMoney = inject('changeMoney')
const fn = () => {
changeMoney(20)
}
return {money, fn}
}
}
</script>
<style scoped lang="less"></style>
3. inheritAttrs
官方文档,如果你不希望组件的根元素继承 attribute,你可以在组件的选项中设置 inheritAttrs: false 。 what ???
可以这样说,当 inheritAttrs 为false时,在渲染出的dom上,不会有写在 父组件中的 子组件标签上的 属性
如果为默认true, 在渲染出的dom上,就会有这个属性
可以参考 https://www.cnblogs.com/luyuefeng/p/11106172.html
4. getCurrentInstance
? getCurrentInstance 支持访问内部组件实例
? 只能在setup 或生命周期钩子中调用
? 官网文档中给出一个warning
getCurrentInstance 只暴露给高阶使用场景,典型的比如在库中。强烈反对在应用的代码中使用 getCurrentInstance 。请不要把 它当作在组合式 API 中获取 this 的替代方案来使用。
可以参考 https://my.oschina.net/u/4355717/blog/4767509
|