1.入口:setup
setup中的数据和方法必须return出去,模板才能使用
<script>
export default {setup () {console.log('setup');const message = 'this is a message'const logMessage = () => {console.log(message);}return {message,logMessage}},beforeCreate() {console.log('beforecreate');}
}
</script><template><div>This is div{{ message }}<button @click="logMessage">log</button></div>
</template>
但是定义一个数据就要手动导出一次,未免太麻烦了。因此vue3加入语法糖
下面是简化后的代码:
<script setup>
const message = 'this is a message'
const logMessage = () => {console.log(message)
}
</script>
2.reactive 和 ref函数
都用于生成响应式数据,但是reactive只能接收对象类型,ref可以接受对象或者简单类型
//导入函数
import { reactive } from 'vue';//传入一个对象类型的参数 变量接收
const state = reactive ({count:0
})
在模板中调用:
<button>{{ state.count }}</button>
ref用法相同,但是在计数器案例上,对自增的操作不太一样
const setCount = () => {state.count++,count1.value++
}
对象.属性是reactive的操作,变量.value是ref的操作(本质还是把变量当做对象来处理的)
3.computed
计算属性,基本思想和vue2一样,不过是在组合式API下写法变化了。
import { computed } from 'vue';const list = ref([1,2,3,4,5,6,7,8])
const computedList = computed(()=>{return list.value.filter(item => item>2)
})
<div>原始响应式数组-{{ list }}计算属性数组-{{ computedList }}</div>
小案例是使用filter函数计算出大于2的元素。
为了验证其是响应式,再添加一个定时器
setTimeout(()=>{list.value.push(9,10)
},3000)
4.watch
侦听器,作用:侦听数据变化,数据变化时执行回调函数
import { watch } from 'vue';
const count2 = ref(0)watch(count2,(newValue,oldValue)=> {console.log(`count2发生变化,旧值为${oldValue},新值为${newValue}`);})
模板中配合计数器使用
侦听多个数据:
const count2 = ref(0)
const count3 = ref(0)watch([count2,count3],([newCount2,newCount3],[oldCount2,oldCount3])=> {console.log('count2 or count3 变化了',[newCount2,newCount3],[oldCount2,oldCount3]);})
immediate
在侦听器创建时立即执行回调,响应式数据变化时也执行回调
比如光标聚焦到搜索框时就出现下拉列表,输入东西后就会变化
const count = ref(0)
const setCount = () => {count.value++
}watch(count,()=> {console.log('count变化了');
},{immediate:true
})
这个demo执行时,还没有点击count,控制台会先打印出count变化了
deep
深度侦听。首先,watch的默认机制:通过watch监听的ref对象默认是浅层侦听,直接修改嵌套的对象属性不会出发回调函数执行,需要开启deep。
比如直接在控制台修改上面count的值:
给count赋值为3时,不会触发count变化了,点击按钮让count++才会触发.
const state = ref({ count:0 })watch(state,()=> {console.log('count变化了');
},{deep:true
})const changeStateByCount = () => {state.value.count++
}
刚开始不加deep时,点击按钮控制台不会打印,加上后就可以打印了,这就是用了deep监听
缺点就是deep开启后会侦听整个对象,就是比如state有两个属性,一个是count,一个是age,但是我只想侦听age,不管count变化情况。
这时候我想到把watch的第一个属性改成state.value.age
接着就给我报错了,它说 接受的参数不符合要求,只能接受一个方法 ,整个ref对象,一个reactive对象或者元素是这几个类型的数组。所以不能接收对象里面的一个属性。但是vue有解决办法:
watch(()=>state.value.age,()=>console.log('count变化了')
)
第一个参数不能是对象的属性,但他可以是函数的返回值,让函数返回 对象的属性不就行了吗
这样就可以侦听某个属性了。
5.vue3的生命周期函数API
选项式API | 组合式API |
beforeCreate/created | setup |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeUnmount | onBeforeUnmount |
unmounted | onUnmounted |
import { onMounted } from 'vue'
onMounted(()=> {console.log('组件挂载完毕,mounted执行了');
})
6.父子通信
父传子
1.父组件中给子组件绑定属性
2.子组件内部通过props选项接收
下面是son的vue文件:
这是father的:
就是import引入son的组件。通过在标签里面赋值来传给儿子,儿子在defineProps中定义这么一个变量来接收父亲传过来的数据。
如何传入响应式数据:
<SonCom message="666666666" :count = "count"/>
在响应式数据前面加冒号。
子传父
1.父组件中给子组件标签通过@绑定事件
2.子组件内部通过$emit方法触发事件
son:
father:
7.模板引用
通过ref标识获取真实的DOM对象或者组件实例对象
defineExpose()
默认情况下语法糖<script setup>不会把组件内部的属性和方法给父最组件访问,可以通过defineExpose()暴露子组件的属性和方法。
获取模板引用的时机是:组件挂载完毕后
8.provide和inject
作用:顶层组件向任意的底层组件传递数据和方法,实现跨层组件通信
跨层传递普通数据:
1.顶层组件通过provide提供数据
2.底层组件通过inject获取数据