1.setup
<script>
export default {
setup () {
console.log('setup',this)
const message = 'this is message'
const logMessage = () => {
console.log(message)
}
return{
message,
logMessage
}
}
}
</script>
<template>
<div>
{{ message }}
<button @click="logMessage">log</button>
</div>
</template>
上面是script原始复杂写法
下面是
<script setup>
const message = 'this is message'
const logMessage = () => {
console.log(message)
}
</script>
问题:
1.setup选项执行的时机
beforeCreate钩子之前,自动执行
2.setup写代码的特点
定义数据+函数,以对象的方式return
3.
经过语法糖的封装更简单的使用组合式API
4.setup中this还执行组件实例码
指向undefined
2.reactive() ref()
reactive():接受对象类型数据的参数传入并返回一个响应式对象
ref():接受简单类型或者对象类型数据的参数传入并返回一个响应式对象
<script setup>
import { reactive } from 'vue'
//响应式对象:会引起视图的更新
const state = reactive({
count:0
})
const setCount = () => {
state.count++
}
</script>
<template>
<div>
<button @click="setCount">{{ state.count }}</button>
</div>
</template>
<script setup>
import { ref } from 'vue'
//响应式对象:对引起视图的更新
const count = ref(0)
const setCount = () => {
//脚本区域修改ref的额响应式对象数据,必须通过.value属性
count.value++
}
</script>
<template>
<div>
<button @click="setCount">{{ count }}</button>
</div>
</template>
步骤:
1.从vue包中导入reactive函数(ref函数)
2.在
问题
1.reactive和ref函数的共同作用?
用函数调用的方式产生响应式数据
2.reactive vs ref
1.reactive不能处理简单类型的数据
2.ref参数类型支持更好,但必须通过.value修改访问
3.ref函数依赖于reactive函数
3.实际中推荐?
推荐ref,更加灵活
computed计算属性函数
<script setup>
import { ref } from 'vue'
import { computed } from 'vue'
const list = ref([1,2,3,4,5,6,7,8])
//filter筛选数据
const computedList = computed(() => {
return list.value.filter(item => item > 2)
})
//定时器,3秒后执行 push加入数据
setTimeout(() => {
list.value.push(9,10)
},3000)
</script>
<template>
<div>
原始数据:{{ list }}
</div>
<div>
计算数据:{{ computedList }}
</div>
</template>
步骤:
1.导入computed函数
2.执行函数在回调参数中return基于响应式数据做计算的值,用变量接收
注意事项
1.计算属性中不应该有“副作用” (用watch)
比如异步请求、修改dom
2.避免直接修改计算属性的值
计算属性应该是只读的
watch函数
作用:侦听一个或多个数据的变化,变化时执行回调函数
参数:1.immediate(立即执行)2.deep(深度侦听)
<!--侦听单个数据-->
<script setup>
import { ref,watch } from 'vue'
const count = ref(0)
const setCount = () => {
count.value++
}
watch(count,(newVal,oldVal)=>{
console.log('count变化了',newVal,oldVal)
})
</script>
<template>
<div>
<button @click="setCount">+{{ count }} </button>
</div>
</template>
<!--侦听多个数据,无论谁变化,都执行回调函数-->
<script setup>
import { ref,watch } from 'vue'
const count = ref(0)
const setCount = () => {
count.value++
}
const name = ref('cp')
const setName = () => {
name.value = 'pc'
}
watch([count,name],([newCount,newName],[oldCount,oldName]) => {
console.log('count/name变化了',[newCount,newName],[oldCount,oldName])
})
</script>
<template>
<div>
<button @click="setCount">+{{ count }} </button>
<button @click="setName">+{{ name }} </button>
</div>
</template>
<!--immediate,在创建时就执行一次回调函数-->
<script setup>
import { ref,watch } from 'vue'
const count = ref(0)
const setCount = () => {
count.value++
}
watch(count,() => {
console.log('count变化了')
},{
immediate:true
})
</script>
<template>
<div>
<button @click="setCount">+{{ count }} </button>
</div>
</template>
<!--deep,默认是浅层监听,该例子若没有deep:true就不会执行watch-->
<!--把ref换成reactive也可以执行watch,因为reactive默认开启了deep-->
<script setup>
import { ref,watch } from 'vue'
const state = ref({count:0})
const setCount = () => {
state.value.count++
}
watch(state,() => {
console.log('count变化了')
},{
deep:true
})
</script>
<template>
<div>
<button @click="setCount">+{{ state.count }} </button>
</div>
</template>
<!--在不开启deep的情况下,精确侦听对象的某个属性-->
<script setup>
import { ref,watch } from 'vue'
const state = ref({
name:'maying',
age:18
})
const changeName = () => {
state.value.name = 'maying-student'
}
const changeAge = () => {
state.value.age = 20
}
watch(
()=> state.value.age,
()=> {
console.log('age变化了')
}
)
//deep性能损耗,尽量不开启deep
</script>
<template>
<div>
<button @click="changeName">{{ state.name }} </button>
<button @click="changeAge">{{ state.age }} </button>
</div>
</template>
步骤:
1.导入watch函数
2.执行watch函数传入要侦听的响应式数据(ref对象)和回调函数
问题
1.watch的第一个参数,ref对象需要添加.value吗
不需要,watch会自动读取
2.watch只能侦听单个数据吗
单个或多个
3.不开启deep,直接修改嵌套属性能触发回调?
不能,默认是浅层侦听
4.不开启deep,侦听层次比较深的属性?
把一个参数写成函数的写法,返回要监听的具体属性(精确侦听)
生命周期函数 (组合式API)
选项式API | 组合式API | |
---|---|---|
beforeCreate / created | setup | 创建 |
beforeMount | onBeforeMount | 挂载 |
mounted | onMounted | |
beforeUpdate | onBeforeUpdate | 更新 |
updated | onUpdated | |
beforeUnmount | onBeforeUnmount | 卸载 |
unmounted | onUnmounted |
<!--生命周期函数可以执行多次,在时机成熟时依次执行-->
<script setup>
import { onMounted } from 'vue';
onMounted(() => {
console.log('组件挂载完毕mounted执行了1')
})
onMounted(() => {
console.log('组件挂载完毕mounted执行了2')
})
</script>
<template>
<div>
</div>
</template>
步骤:
1.导入生命周期函数
2.执行生命周期函数,传入回调
问题
1.组合式API中生命周期函数的格式
on+生命周期名字
2.组合式API可以用onCreated吗
不能,应该是setup中
3.组合式API中组件卸载完毕执行哪个?
onUnmounted
父子通信(组合式API)
父传子
基本思想:
1.父组件中给子组件绑定属性
2.子组件内部通过props选项接收
<!--父组件-->
<script setup>
//setup语法糖下,局部组件无需注册就可以用
import SonCom from './son.vue'
import { ref } from 'vue';
//响应式数据
const count = ref(100)
setTimeout(()=>{
count.value = 200
},3000)
</script>
<template>
<div class="father">
<h3>父组件App</h3>
<SonCom :count="count" message="father message"/>
</div>
</template>
<!--子组件-->
<script setup>
//通过 defineProps “编译器宏” 接收
const props = defineProps({
message: String,
count: Number
})
console.log(props)
</script>
<template>
<div class="son">
<h3>子组件Son</h3>
<div>
父组件传入的数据:{{ message }}-{{ count }}
</div>
</div>
</template>
<style>
</style>
子传父
基本思想:
1.父组件中给子组件标签通过@绑定事件
2.子组件内部通过$emit方法触发事件
<!--父组件-->
<script setup>
//setup语法糖下,局部组件无需注册就可以用
import SonCom from './son.vue'
const getMessage = (msg) => {
console.log(msg)
}
</script>
<template>
<div class="father">
<h3>父组件App</h3>
<SonCom @get-message="getMessage"/>
</div>
</template>
<!--子组件-->
<script setup>
const emit = defineEmits(['get-message'])
const sendMsg = () => {
emit('get-message','this is son message')
}
</script>
<template>
<div class="son">
<h3>子组件Son</h3>
<button @click="sendMsg">触发事件</button>
</div>
</template>
<style>
</style>
问题
1.父传子用什么接收props
defineProps({属性名:类型})
2.setup中怎么使用父组件传来的数据
const props = defineProps({属性名:类型})
3.子传父用什么得到emit方法
defineEmits([‘事件名称’])
模板引用 defineExpose()
获取真实的dom对象或者组件实例对象
<!--父组件-->
<script setup>
import { onMounted,ref } from 'vue';
import SonCom from './son.vue'
const h1Ref = ref(null)
const comRef = ref(null)
//组件挂载完毕后才能获取
onMounted(() => {
console.log(h1Ref.value)
console.log(comRef.value)
})
</script>
<template>
<h1 ref="h1Ref">这是dom标签h1</h1>
<SonCom ref="comRef"/>
</template>
<!--子组件-->
<script setup>
import { ref } from 'vue'
const name = ref('test name')
const setName = () => {
name.value = 'test new name'
}
defineExpose({
name,setName
})
</script>
<template>
<div class="son">
<h3>子组件Son</h3>
</div>
</template>
结果:
defineExpose 编译宏方法
默认情况下,
问题
1.获取模板引用的时机
组件挂载完毕
2.defineExpose编译宏的作用
显示暴露组件内部的属性和方法
provide和inject(跨层组件通信)
作用与场景:顶层组件向任意底层组件传递数据和方法,实现跨层组件通信
传递普通数据
1.顶层组件通过provide提供数据
2.底层组件通过inject获取数据
<!--顶层组件-->
provide('data-key','this is room data')
<!--底层组件-->
const roomData = inject('data-key')
传递响应式数据
<!--顶层组件-->
const count = ref(0)
provide('count-key',count)
<!--底层组件-->
const countData = inject('count-key')
跨层传递方法
<!--顶层组件-->
const count = ref(0)
const setCount = () => {
count.value++
}
provide('setCount-key',setCount)
<!--底层组件-->
const setCount = inject('setCount-key')
<button @click="setCount">修改顶层组件数据coount</button>
问题
1.provide和inject作用
跨层组件通信
2,在传递中怎么保持响应式
第二个参数传递ref对象
3.底层组件想通知顶层组件做修改,怎么做(底层向顶层传)
传递方法,底层组件调用方法
4.只有一个顶层组件或底层组件吗
相对概念,存在多个关系
pinia
符合直觉的 Vue.js 状态管理库
Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态。
可以认为 state
是 store 的数据 (data
),getters
是 store 的计算属性 (computed
),而 actions
则是方法 (methods
)。
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
}
return { count, doubleCount, increment }
})
在 Setup Store 中:
ref()
就是state
属性computed()
就是getters
function()
就是actions
<script setup>
import { useCounterStore } from '@/stores/counter'
// 可以在组件中的任意位置访问 `store` 变量 ✨
const store = useCounterStore()
</script>
为了从 store 中提取属性时保持其响应性,你需要使用 storeToRefs()
。它将为每一个响应式属性创建引用。当你只使用 store 的状态而不调用任何 action 时,它会非常有用。请注意,你可以直接从 store 中解构 action,因为它们也被绑定到 store 上:
storeToRefs保持数据的响应式解构
<script setup>
import { storeToRefs } from 'pinia'
const store = useCounterStore()
// `name` 和 `doubleCount` 是响应式的 ref
// 同时通过插件添加的属性也会被提取为 ref
// 并且会跳过所有的 action 或非响应式 (不是 ref 或 reactive) 的属性
//const { name, doubleCount } = store 响应式丢失
const { name, doubleCount } = storeToRefs(store)
// 作为 action 的 increment 可以直接解构
const { increment } = store
</script>
r’
// 可以在组件中的任意位置访问 store
变量 ✨
const store = useCounterStore()
为了从 store 中提取属性时保持其响应性,你需要使用 `storeToRefs()`。它将为每一个响应式属性创建引用。当你只使用 store 的状态而不调用任何 action 时,它会非常有用。请注意,你可以直接从 store 中解构 action,因为它们也被绑定到 store 上:
storeToRefs保持数据的响应式解构
```vue
<script setup>
import { storeToRefs } from 'pinia'
const store = useCounterStore()
// `name` 和 `doubleCount` 是响应式的 ref
// 同时通过插件添加的属性也会被提取为 ref
// 并且会跳过所有的 action 或非响应式 (不是 ref 或 reactive) 的属性
//const { name, doubleCount } = store 响应式丢失
const { name, doubleCount } = storeToRefs(store)
// 作为 action 的 increment 可以直接解构
const { increment } = store
</script>