Vue3.3新特新和Vue3-Pinia

1.Vue3.3新特性 - defineOptions

背景说明
<script setup>之前,如果要定义 props, emits 可以轻而易举地添加一个与setup平级的属性,但是用了script setup后,就没法这么干了,setup属性已经没有了,自然无法添加与其平级的属性

为了解决这一问题,引入了defineProps 与 defineEmits这两个宏。但这只解决了props与emits这两个属性。如果我们要定义组件的name或其他自定义的属性,还是得回到最原始的用法 – 再添加一个普通的<script>标签。这样就会存在两个<script>标签。让人无法接受。

在这里插入图片描述

一定要另建一个script给组件起一个名字

所以在Vue3.3中新引入了defineOptions宏.顾名思义,主要是用来定义 Option API 的选项. 可以用defineOptions 定义任意的选项, props,emits,expose,slots除外(应为这些可以使用defineXXX来做到)

<script setup>
defineOptions({
	name: 'Foo',
	inheritAttrs: false,
	// ...更多自定义属性
})
<script>

Vue3.3新特性 - defineModel

Vue3中的V-model 和 defineModel

在Vue3中,自定义组件上使用v-model,相当于传递一个modelValue属性, 同时触发 updata:modelValue 事件

<Child v-model="isVisible">
// 相当于
<Child :modelValue="isVisible" @updata:modelValue="isVisible=$event">

我们需要先定义 props, 再定义 emits. 其中有许多重复的代码. 如果需要修改此值, 还需要手动调用 emit 函数

ps:页面中有一个小的输入框,想要实现的效果是:封装一个输入框组件,并且v-model跟现在的数据做一个绑定

App.vue

<script setup>
import MyInput from '@/components/my-input.vue'
import { ref } from 'vue'
const txt = ref('123456')
</script>

<template>
<div>
	<MyInput v- model="txt"></MyInput>
	{{ txt }}
</div>
</template>

my-input.vue

<script setup>
defineProps({
	modelValue: String
})
const emit = defineEmits(['updata:modelValue'])
</script>

<template>
<div>
	<input	
		type="text"
		:value="modelValue"
		@input="e => emit('updata:modelValue', e.target.value)"
	>
</div>
</template>

新写法

<script setup>
const modelValue = defineModel()
modelValue.value++
</script>
<script setup>
import { defineModel } from 'vue'
const modelValue = defineModel()
</script>

<template>
<div>
	<input	
		type="text"
		:value="modelValue"
		@input="e => modelValue = e.target.value
	>
</div>
</template>

然后往vite.config.js中加配置
在这里插入图片描述

3.Pinia快速入门

什么是Pinia

Pinia 是 Vue 的最新状态管理工具, 是Vuex的 替代品

在这里插入图片描述

  1. 提供了更加简单的API(去掉了mutation)
  2. 提供符合组合式风格的API(和Vue3新语法统一)
  3. 弃掉了modules的概念, 每一个store都是一个独立的模块
  4. 配合 TypeScript 更加友好,提供可靠的类型推断

在这里插入图片描述

4.手动添加Pinia到Vue项目

在实际开发项目的时候,关于Pinia的配置,可以在创建项目时自动添加

  1. 使用Vite创建一个空的项目Vue3项目:npm create vue@latest
  2. 按照官方文档 安装 pinia 到项目中(官网:cn.vuejs.org)
  3. vue3官网中有个生态系统,其中有pinia
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述
main.js

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const pinia = createPinia() // 创建Pinia实例
const app = createApp(App) // 创建根实例
app.use(pinia).mount('#app') //这个可以拆分成下面的这两个
app.use(pinia)// pinia插件的安装配置
app.mount('#app')// 视图的挂载

5.Vue3 - Pinia的基本语法

定义Store

在深入研究核心概念之前,我们得知道 Store 是用 defineStore() 定义的,它的第一个参数要求是一个独一无二的名字:

import { defineStore } from 'pinia'

// 你可以对 `defineStore()` 的返回值进行任意命名,但最好使用 store 的名字,同时以 `use` 开头且以 `Store` 结尾。(比如 `useUserStore`,`useCartStore`,`useProductStore`)
// 第一个参数是你的应用中 Store 的唯一 ID。
export const useAlertsStore = defineStore('alerts', {
  // 其他配置...
})

这个名字 ,也被用作 id ,是必须传入的, Pinia 将用它来连接 store 和 devtools。为了养成习惯性的用法,将返回的函数命名为 use… 是一个符合组合式函数风格的约定。

defineStore() 的第二个参数可接受两类值:Setup 函数或 Option 对象。

Option Store
与 Vue 的选项式 API 类似,我们也可以传入一个带有 state、actions 与 getters 属性的 Option 对象

export const useCounterStore = defineStore('counter', {
  state: () => ({ count: 0 }),
  getters: {
    double: (state) => state.count * 2,
  },
  actions: {
    increment() {
      this.count++
    },
  },
})

你可以认为 state 是 store 的数据 (data),getters 是 store 的计算属性 (computed),而 actions 则是方法 (methods)。
为方便上手使用,Option Store 应尽可能直观简单。

Setup Store

也存在另一种定义 store 的可用语法。与 Vue 组合式 API 的 setup 函数 相似,我们可以传入一个函数,该函数定义了一些响应式属性和方法,并且返回一个带有我们想暴露出去的属性和方法的对象。

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

Setup store 比 Option Store 带来了更多的灵活性,因为你可以在一个 store 内创建侦听器,并自由地使用任何组合式函数。不过,请记住,使用组合式函数会让 SSR 变得更加复杂。

新建store/counter.js

import { defineStore } from 'pinia'
import { ref } from 'vue'

// 定义store
// defineStore(仓库唯一的标识, () => { ... })
export const useCounterStore = defineStore('counter', () => {
    // 声明数据 state - count
    const count = ref(0)
    // 声明操作数据的方法 action
	const addCount = () => count.value++
	const subCount = () => count.value--

    // 声明基于数据派生的计算属性 getters
	const double = computed(() => count.value * 2)    

    // 声明数据 state - msg
    const msg = ref('hello pinia')

    return {
        count,
		addCount,
		subCount,

        msg
    }
})

Son1Count.vue

<script setup>
import { useCounterStore } from '@/store/counte
const counterStore = useCounterStore()
</script>

<template>
	<div>
		我是Son1.vue - {{ counterStore.count }} - {{ counterStore.double }}
		<button @click="counterStore.addCount">+</button>
	</div>
</template>

<style scoped>

</style>

Son2Count.vue

<script setup>
import { useCounterStore } from '@/store/counte
const counterStore = useCounterStore()
</script>

<template>
	<div>
		我是Son1.vue - {{ counterStore.count }}
		<button @click="counterStore.subCount">-</button>
	</div>
</template>

<style scoped>

</style>

在这里插入图片描述

6.action的异步实现

在action里面不需要考虑同步还是异步,它都可以写,函数里面既可以直接修改数据,也可以先发个请求,拿到数据回来之后再去修改上面的数据

编写方式: 异步action函数的写法和组件中获取异步数据的写法完全一致
接口地址: http://geek.itheima.net/v1_0/channels
需求: 在Pinia中获取频道列表数据并把数据渲染App组件的模板中

在这里插入图片描述
channel.js

import { defineStore } from 'pinia'
import { ref } from 'vue'
import axios from 'axios'

export const useChannelStore = defineStore('channel', () => {
    // 声明数据
    const channelList = ref([])
    //声明操作数据的方法
    const getList = async () => {
    //支持异步
    const { data: { data }} = await axios.get('http://geek.itheima.net/v1_0/channels')
    channelList.value = data.channels
    console.log(data.channels)

    }

    // 声明getters相关
    return {
    channelList,
    getList
    }
})
<script setup>
import Son1Com from '@/components/Son1Com.vue'
import Son2Com from '@/components/Son2Com.vue'
import { useCounterStore } from '@/store/counter'
import { useChannelStore } from './store/channel'👈
const counterStore = useCounterStore ()
const channelStore = useChannelStore ()👈
console.log(counterStore)
</script>

<template>
    <div>
      <h3>
        App.vue根组件
        - {{ counterStore.count }}
        - {{ counterStore.msg }}
      </h3>
      <Son1Com></Son1Com>
      <Son2Com></Son2Com>
      <hr>
      <button @click="channelStore.getList">获取频道数据</button>👈
      <ul>
        <li v-for="item in channelStore.channelList" :key="item.id">{{ item.name }}</li>👈
      </ul>
    </div>
</template>

<style scoped>

</style>

7.Vue3-Pinia-storeToRefs方法

第六点中,如果直接进行解构,不进行处理,数据会丢失响应式,所以可以用到storeToRefs
在这里插入图片描述
在这里插入图片描述

8.Pinia持久化插件

官方文档:https://prazdevs.github.io/pinia-plugin-persistedstate/zh/

1.安装插件 pinia-plugin-persistedstate

npm i pinia-plugin-persistedstate

2.main.js 使用

import persist from 'pinia-plugin-persistedstate'

app.use(createPinia().use(persist))

3.store仓库中,persist:true开启

安装

npm

npm i pinia-plugin-persistedstate

将插件添加到 pinia 实例上

import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'

const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)

用法

创建 Store 时,将 persist 选项设置为 true。

  • 选项式语法
import { defineStore } from 'pinia'

export const useStore = defineStore('main', {
  state: () => {
    return {
      someState: '你好 pinia',
    }
  },
  persist: true,
})               
  • 组合式语法
import { defineStore } from 'pinia'

export const useStore = defineStore(
  'main',
  () => {
    const someState = ref('你好 pinia')
    return { someState }
  },
  {
    persist: true,
  },
)

在这里插入图片描述
在这里插入图片描述

  • 12
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值