1.组合式API,在单文件组件中(spa) single page application , 通常会与搭配使用,这个setup attribute 是一个标识,告诉vue在编译时进行一些处理,让我们更简洁的使用组合式API
<script setup >
import {ref,onMounted} from 'vue'
2.组合式API的核心思想是直接在函数作用域内定义响应式状态变量,并将从多个函数中得到的状态组合起来处理复杂问题.
1.npm init vue@latest
2.cd 到项目 npm i 安装依赖
3.启动项目 npm run dev
应用实例会暴露一个.config对象,允许我们配置一些应用级的选项.
import { reactive } from "vue"
export default {
setup(){ //setup是一个专门用于组合式API的特殊钩子函数
const state = reactive({count:0})
function increment(){ //方法 也需要return 暴露
state.count++
}
return { //暴露响应式对象到模板中
state,
increment
}
}
}
响应式对象其实是JavaScript Proxy ,代理,他可以自由的定义变量是否是响应式.vue会跟踪响应式对象的属性的访问和更改操作
<script setup>
setup钩子函数使用很频繁,可以使用构建工具来简化代码
<script setup>
import { reactive } from "vue"
const state = reactive({count:1})
function increment(){
state.count++
}
</script>
<template>
<button @click='increment'>{{state.count}}</button>
</template>
如果一个响应式对象再次被reactive 所代理,则该对象会失去响应式连接
let state = reactive({count:0})
state = reactive({count:1}) //该响应式对象会失去响应式连接,并且在脚手架环境下会报错
const obj = reactive({})
const obj1 = {}
obj === obj1 ? // false
const obj = {}
const obj1 = reactive({})
obj1.name = obj
obj1.name === obj ? //false
1.reactive 仅对对象类型的有效,对简单数据类型无效
2.对一个变量多次是用reactive替换响应式,会使该响应式是去连接.
3.ref 适用于所有的类型的响应式,但是读取值的时候会多一个value,例如:
const num = ref(3)
console.log(num) // {value:3}
console.log(num.value) // 3
1.计算属性的值会基于其响应式依赖被缓存,只有当响应式依赖发生了改变才会重新计算,而方法不用,例如
const now = computed(()=>Date.now()) //永远不会更新,以为Date.now并不是一个响应式依赖
2.不要再计算属性中做异步请求和更新dom,他的义务和职责仅为计算和返回该值
3.计算属性的返回值应该被视为只读的,并且永远不应该被更改,应该更新它所依赖的源(响应式依赖)来触发新的计算
push()
unshift()
pop()
reverse()
sort()
splice()
shift()
const obj = reactive({
name:"前端",
nickName:"hulk",
soulmate:{
name:"薛之谦",
nickName:"世界和平"
}
})
const num = ref(1)
1.侦听整个对象,对象中任意一个值发生改变都会触发,无论是子属性还是孙属性
watch(obj,(newValue,oldValue)=>{
console.log(newValue,oldValue)
})
2.监听对象中某个值的变化,仅当obj中的name发生改变才触发
watch(()=>>obj.name,(newV,oldV)=>{
console.log(newV,oldV)
})
3.监听对象的子属性发生变化时触发,孙属性发生变化不会触发
watch(()=>({...obj}),(newV,oldV)=>{
console.log(newV,oldV)
})
4.组合式监听,同时监听两个
watch([()=>obj.name,num],([newV1,oldV1],[newV2,oldV2])=>{
})
watchEffect会在同步执行中立即执行一次回调函数,并且会自动追踪响应式的依赖源,如果响应式的依赖源再次发生改变,回调函数会再次触发.
const str = ref('')
watchEffect(async()=>{
const res = await axios('http:...')
str.value = await res.data.json()
}) //在使用异步回调时,只有在第一个await正常工作前访问到的属性才会被跟踪
1.默认用户创建的监听器都是在vue组件更新前触发的,如果想要在回调中访问vue更新后的dom,需要指明flush:“post”
watch(source,callback,{flush:"post"})
warchEffect(callback,{flush:"post"})
2.停止侦听器
setTimeout(()=>{
watchEffect(()=>{})
},100) //无法停止
const unWatch = watchEffect(()=>{})
unWatch() //正常停止
<button ref='cusButton'></button>
<script setup>
import { ref,onMounted } from "vue"
const cusButton = ref(null) //声明一个跟ref同名的,ref响应式变量,来存放该元素的引用
onMounted(()=>{
console.log(cusButton.value) //在页面挂载后访问该元素
})
</script>
vue2 和 vue3 生命周期的区别
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pfjZBCAC-1661324098046)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20220823092939647.png)]
如果子组件没有使用<script setup,使用的是选项式API,并且被引用的组件实例和子组件的this保持一致,那么父组件可以完全访问子组件中的任意一个属性和方法.但是大多数情况下还是推荐使用标准的props和emit来实现父子间的交互.<script setup中,每个组件的属性和方法默认是私有的,父组件无法访问到子组件的任何东西,除非子组件通过defineExpose宏显示暴露.
<script setup>
import {ref} from "vue"
const num = ref(3)
defineExpose({
num
})
</script>
1.defineProps接收一个对象.对象的格式如下
{
type:String //接收的数据类型
default:"你好" //接收的默认值
required:true //是否必传
}
//例如:
<script setup>
const allProps = defineProps({
title:{
type:String,
default:"你好"
},
numArr:{
type:Array,
required:true
}
})
</script>
2.defineEmits 接收一个数组,数组里面的内容为触发事件的名称,并非方法名称
<template>
<button @click='emitFn'></button>
</template>
<script setup>
const emit = defineEmits('cusClick')
function emitFn(){
emit('cusClick',1)
}
</script>
3.在setup(){}函数中的接收pros和emit
<script>
export default {
props:{
msg:{
type:String,
default:"nihao"
}
},
emits:['cusText'],
setup(props,ctx){
const cusFn = ()=>{
ctx.emit('cusText',props.msg)
}
return {
cusFn
}
}
}
</script>
所有的props都遵循单向绑定的原则,props因父组件的更新而变化,自然地将新的状态向下流往子组件,而不会逆向传递.另外.每次父组件更新后,所有的子组件中的props都会被更新到最新值,这意味着不应该在子组件中去更改一个prop.若想更改一个prop,通常来源于以下两种场景:
1.prop被用于初始传入值,而子组件想再之后将其作为一个局部数据属性
const props = defineProps({
title:[String]
})
const subTitle = ref(props.title) //这样做就和后续的props没有任何关系了
2.需要对传入的props进一步处理
const arr= defineProps(["array"])
const computedArr = computed(()=>arr.map(item=>item))
1.provide 提供数据,可以多次调用,以提供不同的依赖值
<script setup>
import { provide,ref } from "vue"
const num = ref(3)
provide('key',num)
// provide(/*注入名*/'msg',/*注入值*/'你好,世界')
</script>
2.inject 注入接收数据.为防止祖先没有提供注入名而导致的报错,可以在inject时提供默认值
<script setup>
import { inject } from "vue"
const num = inject('key')
//提供inject 默认值
const num1 = inject('key',2)
</script>
3.尽可能的将对任何响应式属性变更的方法保存在提供方中,不要在接收方直接更改提供方响应书的属性
//接收方
<template>
<button @click='increment'>{{num}}</button>
</template>
<script setup>
import {inject} from "vue"
const {num,increment} = inject('numAdd')
</script>
//提供方
<script setup>
import {provide,ref} from "vue"
const num = ref(3)
function increment(){
num.value++
}
provide('numAdd',{
num,
increment
})
</script>
lick=‘increment’>{{num}}
//提供方
###