编程式路由导航
import { useRouter } from 'vue-router'
const router = useRouter()
function handleClick(item: any) {
router.push({
path: '/news/details',
query: {
id: item.id,
title: item.title
},
})
}
pinia存储与读取数据
存储:
import { defineStore } from "pinia"
export const useTagsStore = defineStore('tags',{
state: ()=>{
return {
dynamicTags : ['Tag 1', 'Tag 2', 'Tag 3', '213']
}
}
})
读取:
import { useTagsStore } from '@/store/tags'
const tagsStore = useTagsStore()
const dynamicTags = tagsStore.dynamicTags
pinia修改数据的2种方式
第一种直接修改:
tagsStore.dynamicTags.splice(tagsStore.dynamicTags.indexOf(tag),1)
第二种(actions)
import { defineStore } from "pinia"
export const useTagsStore = defineStore('tags',{
state: ()=>{
return {
dynamicTags : ['Tag 1', 'Tag 2', 'Tag 3']
}
},
actions: {
changeTags(index){
this.dynamicTags.splice(index,1)
}
}
})
tagsStore.changeTags(tagsStore.dynamicTags.indexOf(tag))
getters与storeToRefs
getters类似于计算属性,在store中的写法:
import { defineStore } from "pinia"
export const useTagsStore = defineStore('tags',{
state: ()=>{
return {
dynamicTags : ['Tag 1', 'Tag 2', 'Tag 3'],
}
},
actions: {
changeTags(index){
this.dynamicTags.splice(index,1)
}
},
getters: {
countTags(){
return this.dynamicTags.length + ''
}
}
})
storeToRefs的使用:
import { useTagsStore } from '@/store/tags'
import { storeToRefs } from 'pinia'
const tagsStore = useTagsStore()
// 这种方式不可取,因为他会把tagsStore中所有的东西都变成ref
// let { dynamicTags, countTags } = toRefs(tagsStore)
// 推荐这种
let { dynamicTags, countTags } = storeToRefs(tagsStore)
pinia中的$subscribe
$subscribe可以监听数据的更改:
import { useTagsStore } from '@/store/tags'
const tagsStore = useTagsStore()
tagsStore.$subscribe(()=>{
console.log("tagsStore数据发生改变")
})
组件通信的方式
1. props
父:
<template>
<div>
{{ name }}
我的好朋友是{{ a }}
</div>
<Compo1 :name1 = 'name' :getName = "handleName"></Compo1>
</template>
<script setup lang="ts">
import {ref} from 'vue'
import Compo1 from '@/components/Compo1.vue'
const name = ref("索隆")
let a = ref('')
function handleName(data){
a.value = data.value
}
</script>
子:
<template>
<div>
{{ name }}
我的好朋友{{ name1 }}
</div>
</template>
<script setup lang="ts">
import {ref} from 'vue'
const name = ref("路飞")
let props = defineProps(['name1','getName'])
props.getName(name)
</script>
2. $refs+$parent
父:
<template>
<div>
<Compo1 ref="a"></Compo1>
<Compo2 ref="b"></Compo2>
</div>
<button @click="handleClick($refs)">点击</button>
</template>
<script lang="ts" setup>
import Compo1 from '@/components/Compo1.vue'
import Compo2 from '@/components/Compo2.vue'
import {ref, onMounted} from 'vue'
const a = ref()
const b = ref()
let x = ref(2)
let y = ref(10)
function handleClick(refs){
console.log(refs.a.title)
}
onMounted(()=>{
console.log(a.value.title)
})
defineExpose({x,y})
</script>
<style lang="scss" scoped></style>
子:
<template>
<h2>
子组件1
</h2>
<div>
{{ title }}
</div>
<button @click="handClick($parent)">获取父组件信息</button>
</template>
<script setup lang="ts">
import {ref} from 'vue'
let title = ref("哈哈哈哈")
let ppp = ref(2)
function handClick(parent){
console.log(parent.y)
}
defineExpose({title, ppp})
</script>
<style scoped>
</style>
3. $attrs
父:
<template>
<div>
<Compo2 a="111" b="222"></Compo2>
</div>
</template>
<script lang="ts" setup>
import Compo2 from '@/components/Compo2.vue'
</script>
<style lang="scss" scoped></style>
子:
<template>
<div>
{{ name }}
{{ $attrs }} // { "a": "111", "b": "222" }
</div>
<Compo1 v-bind="$attrs"></Compo1>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import Compo1 from './Compo1.vue';
const name = ref("索隆")
</script>
4. defineEmits自定义事件
父:
<template>
<div>
<Compo2 @custom-event="send"></Compo2>
{{ name }}
</div>
</template>
<script lang="ts" setup>
import Compo2 from '@/components/Compo2.vue'
import {ref} from 'vue'
let name = ref('????')
function send(data){
// console.log(data)
name.value = data
}
</script>
子:
<template>
<div>
{{ name }}
</div>
<button @click="emit('custom-event', name)">发送</button>
</template>
<script setup lang="ts">
import {ref} from 'vue'
const name = ref("索隆")
// 自定义事件
const emit = defineEmits(['custom-event'])
</script>
5. mitt事件总线
安装mitt:
npm install --save mitt
在文件夹utils中新建文件emitter.ts
import mitt from 'mitt'
const emitter = mitt()
export default emitter
父:
<template>
<div>
<Compo2></Compo2>
</div>
<span>{{ name }}</span>
</template>
<script lang="ts" setup>
import Compo2 from '@/components/Compo2.vue'
import emitter from '@/utils/emitter'
import { ref } from 'vue'
let name = ref('???')
emitter.on('send', (data: any) => {
// console.log(data.value)
name.value = data.value
})
</script>
子:
<template>
<div>
{{ name }}
</div>
<button @click="send">发送</button>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import emitter from '@/utils/emitter'
const name = ref("索隆")
function send() {
emitter.emit('send', name)
}
</script>
6. provide+inject
父:
<template>
<div>
<Compo1></Compo1>
</div>
</template>
<script lang="ts" setup>
import Compo1 from '@/components/Compo1.vue'
import {ref,provide} from 'vue'
let x = ref(2)
let y = ref(10)
// 向后代提供数据
provide('x',x)
provide('y',y)
</script>
子:
<template>
<h2>
子组件1
</h2>
<div>
{{ title }}
</div>
</template>
<script setup lang="ts">
import {ref,inject} from 'vue'
let title = ref("哈哈哈哈")
let m = ref(1)
// 接收数据
let x = inject('x',m)
let y = inject('y',m)
console.log(x.value,y.value)
</script>
7. v-model
我们都知道在input标签上使用v-model,那么如果要想用在组件上,该怎么做呢?
父:
<template>
<div>
<Compo2 v-model="text"></Compo2>
{{ text }}
</div>
</template>
<script lang="ts" setup>
import Compo2 from '@/components/Compo2.vue'
import { ref } from 'vue'
let text = ref('asd')
</script>
子:
<template>
<div>
{{ name }}
</div>
<!-- 传统写法 -->
<!-- <input type="text" :value="modelValue" @input="emit('update:modelValue', (<HTMLInputElement>$event.target).value)"> -->
<!-- 新型写法 -->
<input type="text" :value="modelValue" @input="change">
</template>
<script setup lang="ts">
import { ref } from 'vue'
const name = ref("索隆")
// 传统写法
// defineProps(['modelValue'])
// const emit = defineEmits(['update:modelValue'])
// 3.4+推荐写法
const model = defineModel()
function change(e){
model.value = e.target.value
}
</script>