阅读 109

create-vue 与 Pinia 上手试玩

导言

不得不说前端是真的卷,Vue-cli 的核心开发者这又出了一个新的 cli,create-vue,基于 Vite2 和 Vue3 的脚手架工具。目前虽然还只是在开发中,很多功能都不太完善,但可以想象到未来 create-vue 大概率会逐渐替代掉 vue-cli 的...

一、create-vue

1. 安装

安装很简单,只需要一行 npm 语句,不过需要注意下,create-vue 只能安装在非中文路径、中文名称的文件夹下。

npm init vue@next

一些配置:

  • 项目名称

  • 是否安装 TS

  • 是否安装 JSX

  • 是否安装 router

  • 是否安装 vuex

  • 是否安装 Cypress 测试

image.png
文件目录配置也没有太大区别
image.png
进入文件夹后首先安装配置文件

npm install

运行

npm run dev

首页:
image.png

2. 简单体验

其实使用上与 Vue-cli+Vue3 没区别,只是这个脚手架组件页面的 template、script、style 三者标签顺序有改变。
App.vue
image.png
嵌套路由
image.png
页面展示
image.png

二、Pinia

官网:

pinia.esm.dev/

Pinia 是 Vuex 团队成员新开发的一个 Vue 的状态管理方案。
在 Pinia 中减去了 mutations 以及 module 两个概念,转而使用 actions 代替 mutations 完成同异步方法。
同时 Pinia 中的每个 store 都拥有自己的 id,是互相独立的状态库,且在 store 中可以通过 id 直接导入其它的 store 使用。
其优点:

  • 完整的 TypeScript 支持。

  • 及其轻巧(体积大约 1kb)

  • Store 中的 Actions 配置项既可以直行同步方法也可以支持异步方法。

  • 模块不需要嵌套,可以声明多个 Store。

  • 支持 Vue DevTools、SSR 和 Webpack 代码拆分。

**Tips:**Pinia 不是用来代替 Vuex 的,它们的应用场景不同。

Pinia 该什么时候使用?

  1. Pinia 是轻量级的,体积小,更加适合中小型项目,如果是大型项目还是更加适合 Vuex。

  2. Pinia 中无论同步还是异步改变 state,都用 Actions,如果在 Vuex 中分辨不清 mutations 和 Actions 的概念可以使用 Pinia。

  3. Pinia 中完整支持 TypeScript,不会给 Vuex 添加 TypeScript,就用 Pinia。

1. 安装和配置 Pinia

  1. 安装:

npm i pinia@next

  1. 在入口文件中挂载 Pinia

import { createApp } from 'vue' import App from './App.vue' import router from './router' // 引入 Pinia import { createPinia } from 'Pinia' const app = createApp(App) // 使用 Pinia  app.use(createPinia()) app.use(router) app.mount('#app') 复制代码

  1. 在 src/stores/index.js 文件夹中声明 store。

Pinia 通过 defineStore 定义 store,这个 API 拥有两个参数,第一个参数是它的唯一性 id,通过这个唯一性 id,我们可以在其它仓库去引用它。
第二个参数就是常规的 store、getters、actions 可选项。

defineStore('id', {options})

// 引入 Pinia 定义 import { defineStore } from 'pinia' // 定义  export const useUserStore = defineStore('user', {     state: () => {         return {             name: 'achens'         }     } }) 复制代码

  1. 在组件页面引入并使用

<script setup> // 引入 useUserStore import { useUserStore } from './stores'; // 使用 useUserStore const store = useUserStore() // 输出:achens console.log(store.name) </script> 复制代码

2. state 与 getters 的使用

1.使用 storeToRefs 引入 state

使用 Pinia 中的 storeToRefs 去解构引入的 store。
storeToRefs 会将 store 中的 state、getters、actions 转换为 ref 响应式对象。

// 引入 storeToRefs import { storeToRefs } from 'pinia' // 引入 useUserStore import { useUserStore } from './stores'; // 使用 storeToRefs 解构式拿出 useUserStore 中的 state const { name } = storeToRefs(useUserStore()) // 输出: ref 对象 console.log(name) // 输出:张三 console.log(name.value) 复制代码

将其放到页面中也是直接使用

<template>   <h1>Hello achens!</h1>   <!-- <p>直接使用 store:{{ store.name }}</p> -->   <p>使用 storeToRefs:{{ name }}</p>   <router-link to="/home">首页</router-link>   <router-link to="/about">关于页</router-link>   <router-view></router-view> </template> 复制代码

页面呈现
image.png

2. Pinia 中的 Getters

1. 简单使用 Getters

定义 getters 与 Vuex 没有什么太大的区别。

import { defineStore } from 'pinia' export const useUserStore = defineStore('user', {     state: () => {         return {             name: '张三',             count: 5         }     },     getters:{         // 以箭头函数的方式声明一个 getters,使 state.count 的值永远乘以2。         // getters 的第一个参数永远是 state,这点与 Vuex 相比没有区别。         doubleCount: state => state.count * 2     } }) 复制代码

<template>   <h1>Hello achens!</h1>   <!-- <p>直接使用 store:{{ store.name }}</p> -->   <p>使用 storeToRefs:{{ name }}</p> // 使用 getters   <p>{{ count }} -- {{ doubleCount }}</p>   <router-link to="/home">首页</router-link>   <router-link to="/about">关于页</router-link>   <router-view></router-view> </template> 复制代码

页面呈现
image.png

2.  访问自己 store 中的其它 Getters

如果想要在 getters 中互相访问,就必须得将箭头函数改为普通函数的形式,在通过 this 调用相同 store 中的其它 getters。

import { defineStore } from 'pinia' export const useUserStore = defineStore('user', {     state: () => {         return {             name: '张三',             count: 5         }     },     getters:{       doubleCount(state){           return state.count * 2       },       // 在 getters 中使用其它 getters       doubleCountPlus(state){           return this.doubleCount + 1 } }) 复制代码

<template>   <h1>Hello achens!</h1>   <!-- <p>直接使用 store:{{ store.name }}</p> -->   <p>使用 storeToRefs:{{ name }}</p>   <p>{{ count }} -- {{ doubleCount }} -- {{ doubleCountPlus }}</p>   <router-link to="/home">首页</router-link>   <router-link to="/about">关于页</router-link>   <router-view></router-view> </template> 复制代码

页面呈现
image.png

3.  给 Getters 传递参数

想要给 getters 传参,稍微有那么点麻烦,如果传了参数,则必须在其内部用箭头函数接收并使用它,最后将其返回出去。

// ...多余代码不粘贴了 doubleCountPlus(state, a){    // 使用箭头函数拿到这个参数并在使用完后返回     return a => {         return this.doubleCount + a     } } 复制代码

<!-- 多余代码不粘贴了 --> <p>{{ count }} -- {{ doubleCount }} -- {{ doubleCountPlus(5) }}</p> 复制代码

页面呈现
image.png

4. 访问其它 store 中的 Getters

在 src/store 下新建 default.js 文件夹声明一个新的 store。

import { defineStore } from 'pinia' export const useDefaultStore = defineStore('default', {     state: () => {         return {             time: 2         }     },     getters:{         calcTime(state){             return state.time + 2         }     }, }) 复制代码

在 index.js 中引用 default.js 中的 useDefaultStore。

import { defineStore } from 'pinia' // 引入同文件夹下的 useDefaultStore import { useDefaultStore } from './default' export const useUserStore = defineStore('user', {     state: () => {         return {             name: '张三',             count: 5         }     },     getters:{         doubleCount(state){             return state.count * 2         },         doubleCountPlus(state, a){             return a => {                 return this.doubleCount + a             }         },         addDefault(state){             // 拿到 useDefaultStore             const defaultStore = useDefaultStore()             return state.count + defaultStore.calcTime         }     } }) 复制代码

<p>{{ count }} -- {{ doubleCount }} -- {{ doubleCountPlus(5) }}</p> <p>{{ addDefault }}</p> 复制代码

页面呈现:
image.png

3. 使用 actions 处理同异步任务

1. 处理同步任务

在 actions 中如果要修改 state 中的值的话,得使用 this.xxx 来获取 state 中的数据并进行修改。

// ... 其它代码省略 actions:{     addCount(num){         this.count += num     } } 复制代码

而且不能使用 storeToRefs 引用 actions 方法。

// 在 useUserStore 中拿出方法 const { addCount } = useUserStore() 复制代码

页面中也如正常方式一样使用就可以。

<p>{{ count }}</p> <button @click="addCount(2)">点击</button> 复制代码

每次点击 count 加 2.
image.png

2. 处理异步任务

添加定时器设置为异步任务也没有任何问题。

actions:{     addCount(num){         setTimeout(() => {             this.count += num         }, 1000)     } } 复制代码

现在页面会在延迟一秒再去更新数据。
image.png

4. 品牌管理案例

这里只提供思路。

1. 渲染数据

v-for 渲染使用 storeToRefs 结构出来的 state(brandList)。

2. 添加数据

v-model 双向绑定 state 中的数据对象(brand)。 v-on 绑定 actions 点击事件 addBrand(),将 brand 值加入(使用 push) brandList 中。并清空 brand 的值。

3. 删除数据

v-on 绑定 actions 点击事件 delBrand(id),并在点击时将本行 brand 的 id 传入。然后通过 id 删除(filter)指定 brand。 this.brandList = this.brandList.filter(item => itme.id ! == id)

  • id 不等于就返回

  • id 等于就不返回

4. 搜索数据

在 state 中添加一个 keywords 搜索字段,并使用 v-model 与其对应的 input 进行双向绑定。 在之后定义一个 searchResult 计算属性,并对 brandList 中的每一项品牌名称都进行一遍过滤,返回包好关键字的每一项。 state.brandList.filter(item => item.name.includes(state.keywords)) 最后将 v-for 中的 brandLIst 替换成 searchResult。

三、结语

总的来说 create-vue 与 Vue-cli 使用并无大异,只是说一个是用 Webpack5 作为打包工具,一个则是使用 Vite2 打包工具。且 Vue-cli 可选 Vue2、3 的版本,而 Create-vue 则是默认 Vite2 + Vue3 +

四、坑

1. 坑一,create-vue 安装路径不能有中文。

2. 坑二,项目配置名称中不能带加号

如图必须是:create-vue-pinia。
而不能是:create-vue+pinia。
image.png
否则就会报错:
image.png


作者:achens
链接:https://juejin.cn/post/7066061740257214472


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐