Pinia 中文文档
pinia原理
上次写vue项目的时候,问别人还在用vuex。别人说不用了,改pinia。于是了解了一下pinia。它是一种全局状态管理工具,vue2/3都适用,api比vuex更精简,使用更舒服。了解完就找资料摹写一个pinia。膜拜大神,链接贴上面了。现在说一下体会。主要按渐进式完善、注册、挂载、使用方式、逻辑理解、vue踩坑、对比react的useModel这几方面讲。
-
上面的原理博客是渐进式写法逐渐完善的,降低了不少理解难度,配合边写边读很快就能撸一个出来,然后再做内容输出,做知识整理~。
-
这种插件的注册方式是通过install安装,通过symbol判断是否安装。install里面做几件事,1挂在对象,2依赖注入,3挂原型链上。也因此,它这个对象有一些_a、_e、_s来分别保存当前实例、作用域、和所有store(不得不说考虑得就是完善)
-
使用方式emmm和原来一模一样,就是createPinia一个pinia对象给vue use,然后调defineStore传个id和函数式写法或传统state-getters-actions写法定义一个store,然后页面执行这个store返回的函数就能拿返回值及函数来使用了。
-
其原理的大概逻辑是这样:
createPinia:用了一些专门写插件的api------effectScope, markRaw(我也不太懂这几个api)来构建个内部自动销毁型作用域,然后声明install方法,在vue.use(xxx)的时候vue会去调用这个install安装,install做几件事,1挂在对象,2依赖注入,3挂原型链上。
defineStore:接收id,判断是函数式还是传统写法,然后返回个useStore函数。useStore里面通过symbol得到pinia实例,如果在_s里面有这个id,就返回它;没有就进行函数式注册或者传统注册。
函数式注册:用reactive声明个响应式变量,用_e搞个作用域出来,执行传入的函数式获取到一个对象,然后遍历这个对象里面的方法改变this和参数指向到开头声明的变量上------action.apply(store, arguments),这样调用方法就能通过传参来改这个变量,最后合并变量和对象,返回它。
传统注册:核心思想就是解析state, getters, actions这三个变量,然后一一支持它。取巧的是只是多了个自己定义的setup函数,在函数里面支持这三个变量。外面套的壳跟函数式支持一模一样哈哈哈哈。在setup里面,state的支持是先获取(兼容函数和对象两种传值方式),然后调用toRefs转成响应式,就支持了;gettter的支持是先遍历(它用reduce遍历对象的写法好简洁第一次见!),然后用computed计算一下里面依然还是要改变this指向到变量上,然后跟state合并一起返回就支持啦;action的支持是遍历为函数的属性然后改变this指向到变量上就好了,最后合并返回。 -
我认为其中的关键点在于 它通过Object.assign绕过vue合并对象不响应的坑、通过symbol注册得到实例、函数返函数的形式、改变this指向、以及一些取巧之处。
-
最后,对比react的useModel,pinia需要注册才能使用,这是因为antd pro框架帮我们封装了这个useModel,让我们开箱即用。同时两者开发思路不同,antd pro做这件事的原理大概是通过读文件操作,将特定目录特定开头的文件给实例化做成单例模式,并可以通过useModel获得实例,就算是全局数据了(猜测,不过js貌似不能主动读文件来着?)。
感谢阅读