VUE3浅析---pinia和proxy

这篇具有很好参考价值的文章主要介绍了VUE3浅析---pinia和proxy。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、pinia:仓库

1、概念:

Pinia 是 Vue3 的存储库,代替 Vuex 成为VUE3的状态管理工具。相比于 Vuex 它有以下优势:
- 不存在mutations,存储数据的方式更加简化。
- 在组件上可以直接做存储库中的数据的修改,并且都是响应式的。
- 贴合ts。

2、安装并使用

2.1、安装
yarn add pinia 或者 npm install pinia
2.2、使用:在src目录下定义stores/store.ts文件,使用如下代码初始化pinia仓库并在main.ts中启用pinia

pinia常用的模块有三个:

  • state:存储数据的仓库
  • action:用来定义处理state的方法操作,在组件中可以直接调用actions里面定义好的方法处理state中的值,但是注意,如果使用箭头函数那么this指向就会发成变化。
  • getters:相当于computed,可以用来监听state中值的变化的。
import { defineStore } from "pinia";

const useUserStore = defineStore({
    // 当前存储库的唯一键
    id: "user",

    // 存储库,他必须以一个函数的形式存在,在函数里面返回具体要存储的数据或者对象
    state: () => ({
        name: "Jerry",
        age: 20,
        userInfo: "",
    }),

    // 相当于计算属性 computed
    getters: {
        userInfo: (state) => "姓名:" + state.name + "--年龄:" + state.age,
    },

    // 可以处理异步或者同步方法逻辑
    actions: {},
});

const useGoodsStore = defineStore({
    // 当前存储库的唯一键
    id: "goods",

    // 存储库,他必须以一个函数的形式存在,在函数里面返回具体要存储的数据或者对象
    state: () => ({
        name: "衣服",
        price: 100,
        goodsInfo: "",
    }),

    // 相当于计算属性 computed
    getters: {
        goodsInfo: (state) => "名称:" + state.name + "--价格:" + state.price,
    },

    // 可以处理异步或者同步方法逻辑
    actions: {},
});

export { useGoodsStore, useUserStore };

// 在main.ts中启用pinia
import { createPinia } from 'pinia'
app.use(createPinia())

2.3、在组件中改变仓库中的数据
  • 直接赋值
  • 使用$patch使用对象改变值
  • 使用$patch使用函数改变值,使用函数的好处就是能增减逻辑判断
  • 直接使用goodsStore.$state直接改变值,但是要写全定义的所有的变量
  • 直接调用actions中定义的方法:goodsStore.setGoodName()
<script setup lang="ts">
import { useGoodsStore, useUserStore } from './stores/store'
import { ref } from 'vue'

// 定义两个v-mode的变量,用于接受输入值
const goodsName = ref<string>('')
const userName = ref<string>('')

// 调用store里面定义的两个钩子函数,初始化仓库
const userStore = useUserStore()
const goodsStore = useGoodsStore()

const changeGoodsInfo = () => {
  console.log('changeGoodsInfo')
  // goodsStore.name = goodsName.value // a、直接赋值
  // goodsStore.$patch({ // b、使用`$patch`使用对象改变值
  //   name: goodsName.value
  // })

  // goodsStore.$patch((store) => { // c、 使用`$patch`使用函数改变值,使用函数的好处就是能增减逻辑判断
  //   if (goodsName.value != '') {
  //     store.name = goodsName.value
  //   }
  // })

  // goodsStore.$state = { // d、直接使用`goodsStore.$state`直接改变值,但是要写全定义的所有的变量
  //   name: goodsName.value,
  //   price: 1.2,
  //   goodsInfo: '姓名:' + goodsName.value + '--年龄:' + 1.2
  // }

  goodsStore.setGoodName() // e、直接调用`actions`中定义的方法:`goodsStore.setGoodName()`
}

const changeUserInfo = () => {
  console.log('changed')
  userStore.name = userName.value
}
</script>

<template>
    <div>
        <p>用户信息:{{ userStore.userInfo }}</p>
        <p>商品信息:{{ goodsStore.goodsInfo }}</p>

        <br />
        <hr />
        姓名:<input type="text" v-model="userName" />
        <button @click="changeUserInfo">提交用户信息</button>
        <br />
        <hr />
        名称:<input type="text" v-model="goodsName" />
        <button @click="changeGoodsInfo">提交商品信息</button>
    </div>
</template>

<style scoped></style>
2.4、结构store:结构之后,不具有哦响应式,要想保留响应式,就必须使用pinia提供的storeToRefs进行转化
import { storeToRefs } from 'pinia'

const goodsStore = useGoodsStore()
// let { name, price } = goodsStore
let { name, price } = storeToRefs(goodsStore)
const changeGoodsInfo = () => {
	console.log('changeGoodsInfo', name, price)
	price.value += 1
}

// storeToRefs的源码解析
function storeToRefs(store) {
	// 判断当前是Vue2的直接使用toRefs进行包裹处理
    if (isVue2) {
        return toRefs(store);
    }
    else {
	    // 拿到store的原始对象,实际上处理之后就是一个Object对象
        store = toRaw(store);
        // 最终返回的就是refs集合,下边如果发现store中的ref或者reactive对象之后,就会被放到refs集合中
        const refs = {};
        for (const key in store) {
            const value = store[key];
            if (isRef(value) || isReactive(value)) {
                // 将store中的ref或者reactive对象放到refs集合中
                refs[key] =
                    // ---
                    toRef(store, key);
            }
        }
        return refs;
    }
}
2.5、getters和actions:用于操作state中的属性
  // 相当于计算属性 computed:getters中的方法当state中的任何一个属性变化时,就会给监听到
  getters: {
    goodsInfo: state => { 
      console.log('goodsInfo', '=====')
      return '名称:' + state.name + '--价格:' + state.price
    },
    getGoodsInfo(): string {
      console.log('getGoodsInfo', '=====')
      return '名称:' + this.name + '--价格:' + this.getGoodsPrice + '元' // 这里使用箭头函数的话,this指向就会出现问题,无法使用this调用getGoodsPrice
    },
    getGoodsPrice: state => {
      console.log('getGoodsPrice', '=====')
      state.price *= 100
      return state.price
    }
  },

// 定义Goods类型
type Goods = {
    name: string;
    price: number;
};

// 模拟一个异步方法:3秒后返回数据
const setGoodsInfo = (): Promise<Goods> => {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve({
                name: "iPad Pro",
                price: 29.96,
            });
        }, 3000);
    });
};

// 可以处理异步或者同步方法逻辑
  actions: {
    setGoodsName() {
      this.name = 'Zara'
      this.setGoodsPrice() // 普通防范中调用普通方法
    },
    setGoodsPrice() {
      this.price = 200
    },

// 在actions中可以使用异步和同步方法,
    async getGoodsInfo1() {
      const result = await setGoodsInfo() // 同步调用setGoodsInfo获取数据,3秒后返回数据
      this.name = result.name
      this.price = result.price
      this.setGoodsName() // 异步方法中调用普通方法
    }
  },

3、实例API

3.1、$patch:可以直接操作state里面的值
  // goodsStore.$patch({ // b、使用`$patch`使用对象改变值
  //   name: goodsName.value
  // })

  // goodsStore.$patch((store) => { // c、 使用`$patch`使用函数改变值,使用函数的好处就是能增减逻辑判断
  //   if (goodsName.value != '') {
  //     store.name = goodsName.value
  //   }
  // })

  // goodsStore.$state = { // d、直接使用`goodsStore.$state`直接改变值,但是要写全定义的所有的变量
  //   name: goodsName.value,
  //   price: 1.2,
  //   goodsInfo: '姓名:' + goodsName.value + '--年龄:' + 1.2
  // }
3.2、$reset:将state中的值还原成最近一次改变的值
const changeGoodsInfo = () => {
    console.log("changeGoodsInfo", name, price);

    goodsStore.getGoodsInfo1();
    setTimeout(() => {
        goodsStore.$reset(); // 还原成最近一次改变的值
    }, 5000);
};

3.3、$subscribe:当state中的值任意一个发生变化的时候,就会触发该函数
/**
 * 当state中的值任意一个发生变化的时候,就会触发该函数
 * 
 * args: 里面会记录新旧值
 * state:就是当前操作的state的实例
 * options: 是一个对象,比如detached,这是一个boolean参数,当这个参数为true时,表明即使当前组件销毁后,也继续监控state里面值的变化,可选
 */
 goodsStore.$subscribe((args, state) => {
  console.log('args', args)
  console.log('state', state)
},{
  detached: true
})
3.4、$onAction:当调用actions里面的函数的时候,就会触发该函数
/**
 * 当调用actions里面的函数的时候,就会触发改函数
 *
 * args:接收参数,里面封装了多个api:
 *      args.after:当$onAction里面的逻辑执行完成之后才会执行args.after函数逻辑,所以args.after放置的位置于执行顺序无关
 *      args.onError:当调用actions里面的函数发生错误时,args.onError函数也会执行
 *      args.args:接收调用actions里面的函数传递的参数,是一个数组
 *      args.name:执行的actions里面的函数的名称
 * detached: 这是一个boolean参数,当这个参数为true时,表明即使当前组件销毁时,也继续监控actions里面的函数调用,可选
 */
goodsStore.$onAction((args) => {
    args.after(() => console.log("args.after", "===="));
    console.log("args", args);
}, true);

4、pinia持久化

当我们刷新页面或者跳转到下一个组件的时候,组件中展示的pinia中的值会被丢失,即还原成默认值,所以要实现将pinia中更改过的值持久化,这里采用localstore。文章来源地址https://www.toymoban.com/news/detail-500800.html

import { PiniaPluginContext } from "pinia";
import { toRaw } from "vue";

/**
 * 存储localStorage
 *
 * @param key 给定的key
 * @param value 给定的值
 */
const setLocalStorage = (key: string, value: string) => {
    try {
        localStorage.setItem(key, value);
    } catch (err) {
        console.log(err);
    }
};

/**
 * 获取localStorage
 *
 * @param key 给定的key
 * @returns 返回对应的key的值
 */
const getLocalFromStorage = (key: string) => {
    try {
        return localStorage.getItem(key)
            ? JSON.parse(localStorage.getItem(key) as string)
            : {};
    } catch (err) {
        console.log(err);
    }
    return undefined;
};

// 定义一个数据类型
type Options = {
    plugin?: string;
    key?: string;
};

/**
 * pinia插件定义,函数里面包裹函数,主要是为了实现用户自定义参数,外层函数,主要在交给store注册的时候,
 * 可以由用户自定参数,而真正被store调用执行的参数是return出去的函数,该函数才会接收store返回的context,里面有state的所有信息
 *
 * @param optons 用户自定的参数
 * @returns 从localStorage存储的state中值
 */
const PiniaPersistencePluggin = (optons: Options) => {
    return (context: PiniaPluginContext) => {
        const key = optons.key ?? "__PINIA__";
        const plugin = optons.plugin ?? "localStorage";
        const { store } = context;
        const data = getLocalFromStorage(key + `${store.$id}`);
        console.log("data===get", data);
        store.$subscribe(() => {
            if (plugin && plugin == "localStorage") {
                setLocalStorage(
                    key + `${store.$id}`,
                    JSON.stringify(toRaw(store.$state))
                );
            }
        });

        return { ...data };
    };
};

// 向外暴漏插件
export { PiniaPersistencePluggin };

// mian.ts中注册使用插件
import { PiniaPersistencePluggin } from './stores/piniaplugin'

const store = createPinia()
store.use(PiniaPersistencePluggin({ plugin: 'localStorage', key: '__PINIA__' })) // 在注册使用插件的时候,可以指定state的数据存储在localStorage获取cookie获取其他,还至指定默认的key

二、proxy:代理

// 在vite.config.ts中加入如下代码,可解决dev过程时的跨域问题,实际生产环境下,用的是ngigx
  server: {
    port: 8082,
    /**
     * 这里设置的是是否启用网络地址,如果为false,启动后就不会出现ip的访问地址:
     *   ➜  Local:   http://localhost:8082/
     *   ➜  Network: http://192.168.217.240:8082/ // 如果该参数为false,就不会出现改地址
     */
    host: true,
    /**
     * 为开发服务器配置CORS。设置为true以允许来自任何源的所有方法,或者使用一个对象单独配置。
     */
    cors: true,
    // 是否使用https进行访问
    https: true,
    // 跨域设置
    proxy: {
      '/api': { // 设置前端在访问后台地址的时候,要以/api开始
        target: 'http://localhost:8989', // 访问的目标地址
        changeOrigin: true, // 允许将源地址更改为目标地址
        rewrite: (path: string) => path.replace(/^\/api/, '') // 将前端请求时候加的/api替换为'',应为/api是前端为了解决跨域问题而加的,真正的后台地址是上是没有这个的
      },
    }
  },

到了这里,关于VUE3浅析---pinia和proxy的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Vue3中使用pinia

    目录 1、安装:npm install pinia 2、创建store文件并配置内部的index.js文件 3、main.js文件中配置 4、组件使用 4-1、 store.$reset()    4-2 store.$patch  5.订阅修改 6.Getter 7、Actions 效果图  点击按钮,界面变化  说明成功修改了pinia里面的数据,且界面刷新证明这种直接修该pinia数据的方式

    2024年02月07日
    浏览(39)
  • vue3项目中使用pinia

    前言: 官网地址 https://pinia.vuejs.org/zh/ 中文文档 https://pinia.web3doc.top/ pinia    作为Vue.js 状态管理库 类型安全、可扩展性以及模块化设计。 甚至让你忘记正在使用的是一个状态库。 优点:   优点 dev-tools 支持 跟踪动作、突变的时间线 Store 出现在使用它们的组件中 time travel

    2023年04月26日
    浏览(45)
  • vue3组件通信之pinia

      在vue3,vue的状态管理也迎来了新的变更,在vue3使用新的组件pinia来代理原有的vuex。pinia相比vuex,功能收敛了不少,比如不直接暴露setter方式,外部直接修改数据 vuex:集中式管理状态容器,可以实现任意组件之间通信 核心概念:state、mutations、actions、getters、modules pinia:集中式

    2024年02月11日
    浏览(40)
  • Vue3---Pinia优化重复请求

    若两个组件请求的数据是相同的,避免请求两次,可以使用Pinia集中管理数据,再由父组件请求,子组件使用 1.  2. 3.

    2024年02月12日
    浏览(33)
  • vue3的pinia(大菠萝)

    一:Pinia简介和五大优势 Pinia是vue生态里Vuex的替代者,一个全新的vue状态管理库。在Vue3成为正式版以后,尤雨溪强势推荐的项目就是Pinia。 那先来看看Pinia比Vuex好的地方,也就是Pinia的五大优势。 可以对Vue2和Vue3做到很好的支持,也就是老项目也可以使用Pinia。 抛弃了Mutati

    2024年02月16日
    浏览(32)
  • vue3学习-Pinia状态管理

    定义一个Store 这个 name ,也称为 id ,是必要的,Pinia 使用它来将 store 连接到 devtools。 将返回的函数命名为 use… 是跨可组合项的约定,以使其符合你的使用习惯。 使用 store 一旦 store 被实例化,你就可以直接在 store 上访问 state 、 getters 和 actions 中定义的任何属性 store 是一

    2024年02月14日
    浏览(39)
  • vue3探索——pinia高阶使用

    以下是一些 Pinia 的其他高阶功能: storeToRefs() :响应式解构仓库,保证解构出来的数据是响应式的数据。 状态持久化 :Pinia 并没有内置的状态持久化功能,但你可以使用第三方库或自定义插件来实现状态的持久化。例如,你可以使用  localStorage  或  sessionStorage  来将状态

    2024年02月08日
    浏览(34)
  • pinia在vue3中的使用

    总结: 在store文件夹中建一个pinia的文件userStore.js 1.要想使用pinia必须先引入defineStore  这里我们使用es6的模块化语法导出的   import { defineStore } from \\\'pinia\\\' 2.然后使用export const useUserStore = defineStore(\\\'user\\\',{})   defineStore 方法有两个参数,第一个参数是模块化名字(也就相当于身份

    2024年02月15日
    浏览(36)
  • Vue3 store+pinia 基本使用

    pinia是一个 状态管理的库 ,用于 跨组件、页面进行状态共享 (这和Vuex、Redux一样),用起来像组合式API Pinia和Vuex有什么区别 1、PInia的最初是为了探索Vuex的下一次迭代会是什么样子,结合了Vuex核心团队讨论中的许多想法; 2、最终,团队意识到Pinia已经实现了Vuex5中大部分内

    2024年02月07日
    浏览(51)
  • Vue3中的pinia使用(收藏版)

    💂 个人网站:【紫陌】【笔记分享网】 💅 想寻找共同学习交流、共同成长的伙伴,请点击【前端学习交流群】 pinia 是 Vue 的存储库,它允许您跨组件/页面共享状态。就是和vuex一样的实现数据共享。 依据Pinia官方文档,Pinia是2019年由vue.js官方成员重新设计的新一代状态管理

    2024年01月25日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包