vue3知识总结-5
文章目录
在之前的内容中有很多的,是关于Vue2的配置,组合式和选择式api需要都会,下面主要的就是一些新特性的总结,总体看完之后,就是基本上,可以理解清楚,是怎么样的,然后后面底层的肯定是需要深度剖析的。基本的基础知识就到这里。
Setup
<!--<script>-->
<!--export default {-->
<!-- setup(){-->
<!-- console.log("setup",this)-->
<!-- const message = " this is a div"-->
<!-- const logMessage = ()=>{-->
<!-- console.log(message)-->
<!-- }-->
<!-- return{-->
<!-- message,-->
<!-- logMessage-->
<!-- }-->
<!-- },-->
<!-- beforeCreate() {-->
<!-- console.log('beforeCreate')-->
<!-- }-->
<!--}-->
<script setup>
console.log("setup",this)
const message = " this is a div"
const logMessage = ()=>{
console.log(message)
}
</script>
<template>
<div>
{{ message }}
<button @click="logMessage">log</button>
</div>
</template>
Reactive 和ref函数
reactive
作用:接受对象类型数据的参数传入并返回一个响应式的对象
<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>
Ref
作用:接受简单类型或者对象类型的数据传入并且返回一个响应式的对象
<script setup>
import {ref} from "vue";
const count = ref(0)
const setCount =()=>{
count.value++
}
</script>
<template>
<div>
<button @click="setCount">{{count}}</button>
</div>
</template>
computed计算属性函数
计算属性基本思想和Vue2的完全一致,组合式API的计算属性只是修改了写法
<script setup>
import {computed, ref} from "vue";
const list = ref([1,2,3,4,5,6,7,8])
const computedList = computed(()=>{
return list.value.filter(item => item > 2)
})
setTimeout(()=>{
list.value.push(9,10)
})
</script>
<template>
<div>
原始响应式数组-{{list}}
</div>
<div>
计算属性数组-{{computedList}}
</div>
</template>
watch函数
基本使用和立即执行
作用:侦听一个或者多个数据的变化
导入watch函数
执行watch函数传入要侦听的响应式数据和回调函数
下面是侦听单个数据的
<script setup>
import {ref, watch} from "vue";
const count = ref(0)
const setCount = () =>{
count.value++
}
watch(count, (newVal, oldValue) =>{
console.log('count变化了',newVal, oldValue)
})
</script>
<template>
<div>
<button @click="setCount">+{{count}}</button>
</div>
</template>
多个数据的监听
Immediate: 侦听器创建的时候,立即触发回调,响应式数据变化之后继续执行回调
<script setup>
import {ref, watch} from "vue";
const count = ref(0)
const setCount = () =>{
count.value++
}
const name = ref('cp')
const changeName = () =>{
name.value ='pc'
}
watch(
[count, name],
(
[newCount,newName],
[oldCount, oldName],
)=>{
console.log('count或者name变化了',[newCount,newName],
[oldCount,oldName])
}, {
immediate:true
}
)
</script>
<template>
<div>
<button @click="setCount">+{{count}}</button>
</div>
<div>
<button @click="changeName">+{{name}}</button>
</div>
</template>
Deep深度侦听
watch是ref对象默认是浅层侦听的,直接修改嵌套的对象属性不会触发回调执行,需要开启deep
也可以有精确的侦听。
<script setup>
import {onMounted} from "vue";
onMounted(()=>{
console.log("组件挂载完毕mounted1")
})
onMounted(()=>{
console.log("组件挂载完毕mounted3")
})
onMounted(()=>{
console.log("组件挂载完毕mounted2")
})
</script>
<template>
<div>
</div>
</template>
生命周期函数
<script setup>
import {onMounted} from "vue";
onMounted(()=>{
console.log("组件挂载完毕mounted1")
})
onMounted(()=>{
console.log("组件挂载完毕mounted3")
})
onMounted(()=>{
console.log("组件挂载完毕mounted2")
})
</script>
<template>
<div>
</div>
</template>
父子通信
父传子
- 父组件给子组件绑定属性
- 子组件内部通过props选项接受
<script setup>
import SonCom from "@/components/son-com.vue";
import {ref} from "vue";
//响应式数据
const count = ref(100)
setTimeout(()=>{
count.value = 200
},3000)
</script>
<template>
<div class="father">
<h2>父组件App</h2>
<SonCom :count="count" message="father message "/>
</div>
</template>
<script setup>
//接受数据
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 scoped>
</style>
子传父
- 父组件中给子组件标签通过@绑定事件
- 子组件内部通过$emit方法触发事件
<script setup>
const emit = defineEmits(['get-message'])
const sendMsg=()=>{
emit('get-message', 'this is son msg')
}
</script>
<template>
<div class="son">
<h3>子组件Son</h3>
<div>
<button @click="sendMsg">触发自定义事件</button>
</div>
</div>
</template>
<style scoped>
</style>
<script setup>
import SonCom from "@/components/son-com.vue";
const getMessage=(msg)=>{
console.log(msg)
}
</script>
<template>
<div class="father">
<h2>父组件App</h2>
<SonCom @get-message="getMessage"/>
</div>
</template>
模版引用
通过ref标识获取真实的dom对象或者实例对象
如何使用
- 调用ref函数生成一个ref对象
- 通过ref标识绑定ref对象到标签
defineExpose()
制定那些属性和方法允许访问,然后暴露给父组件
<script setup>
import {ref} from 'vue'
const name = ref('test name')
const setName = () =>{
name.value = 'test new name'
}
defineExpose(
name,
setName
)
</script>
<template>
<div>我是test组件</div>
</template>
<style scoped>
</style>
<script setup>
import TestCom from "@/components/test-com.vue";
import {onMounted, ref} from "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>
<TestCom ref="comRef"/>
</template>
Provide 和inject
作用和场景
顶层组件向任意的底层组件传递数据和方法,实现夸层组件通信
跨层传递普通数据
- 顶层组件通过provide函数提供数据
- 底层组件通过inject函数获取数据
<script setup>
//接收数据
import {inject} from "vue";
const roomData = inject('data-key')
const countData = inject('count-key')
const setCount = inject('setCount-key')
</script>
<template>
<div class="comment">
<div>
来自顶层组件中的数据为:{{roomData}}
</div>
<div>
来自顶层组件的响应式数据:{{countData}}
</div>
<div>
<button @click="setCount">修改顶层组件的数据</button>
</div>
</div>
</template>
<style scoped>
</style>
<script setup>
import {provide, ref} from "vue";
import RootMegItem from "@/components/root-meg-item.vue";
provide('data-key', 'this is room data')
//响应式数据
const count = ref(0)
provide('count-key',count)
provide('up-func',)
setTimeout(()=>{
count.value = 100
}, 5000)
const setCount = ()=>{
count.value++
}
provide('setCount-key', setCount)
</script>
<template>
<div class="page">
<RootMegItem/>
</div>
</template>
Pinia
添加pinia到Vue项目
Pinia是Vue的专属的最新状态管理库,是Vuex状态管理工具的替代品
- 提供更加简单的API
- 提供符合组合式风格的API
- 去掉了modules的概念,每一个store都是一个独立的模块
- 搭配TypeScript一起使用提供可靠的类型推断
import './assets/main.css'
import { createApp } from 'vue'
import App from './App.vue'
// 导入
import {createPinia} from "pinia";
//执行方法得到实例
const pinia = createPinia()
// 实例加入到app应用中
createApp(App).use(pinia).mount('#app')
conter基础使用
定义store和组件使用store
<script setup>
//导入方法
import {userCounterStore} from '@/stores/conter'
// 执行实例
const counterStore = userCounterStore()
console.log(counterStore)
</script>
<template>
<button @click="counterStore.increment()">{{counterStore.count}}</button>
</template>
<style scoped>
header {
line-height: 1.5;
}
.logo {
display: block;
margin: 0 auto 2rem;
}
@media (min-width: 1024px) {
header {
display: flex;
place-items: center;
padding-right: calc(var(--section-gap) / 2);
}
.logo {
margin: 0 2rem 0 0;
}
header .wrapper {
display: flex;
place-items: flex-start;
flex-wrap: wrap;
}
}
</style>
//导入方法
import {defineStore} from "pinia";
import {ref} from "vue";
export const userCounterStore = defineStore('counter', ()=>{
const count = ref(0)
const increment =()=>{
count.value++
}
return {
count,
increment
}
})
getters实现
//导入方法
import {defineStore} from "pinia";
import {computed, ref} from "vue";
import axios from "axios";
const API_URL= 'http://geek.itheima.net/v1_0/channels'
export const userCounterStore = defineStore('counter', ()=>{
const count = ref(0)
const increment =()=>{
count.value++
}
const doubleCount = computed(()=>count.value * 2)
const list = ref([])
const getList =async () => {
const res = axios.get(API_URL)
list.value =res.data.data.channels
}
return {
count,
increment,
doubleCount,
list,
getList
}
})
<script setup>
//导入方法
import {userCounterStore} from '@/stores/conter'
import {onMounted} from "vue";
// 执行实例
const counterStore = userCounterStore()
console.log(counterStore)
onMounted(()=>{
counterStore.getList()
})
</script>
<template>
<button @click="counterStore.increment()">{{counterStore.count}}</button>
{{counterStore.doubleCount}}
<ul>
<li v-for="item in counterStore.list" :key="item.id">{{item.name}}</li>/
</ul>
</template>
<style scoped>
header {
line-height: 1.5;
}
.logo {
display: block;
margin: 0 auto 2rem;
}
@media (min-width: 1024px) {
header {
display: flex;
place-items: center;
padding-right: calc(var(--section-gap) / 2);
}
.logo {
margin: 0 2rem 0 0;
}
header .wrapper {
display: flex;
place-items: flex-start;
flex-wrap: wrap;
}
}
</style>