编程式路由导航

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>