你好获取登录信息中




首页 主站 文章列表 分类列表
文章列表更多

vue组件库开发踩坑记

2021-07-30 17:28:12

为了之后网站的更新,我着手做了一个自己的ui库。再之前测试打包上传到NPM然后再从其他项目中安装引入时,它似乎运行良好,所以我也就没太在意了。

可是,最近我更新了vue3版本之后,并且在另一个项目中实际使用时,它开始报错了,初步一看,似乎是因为我外面没有包提供Provide告知组件显示成什么样子的组件导致的,可是我有设置默认值啊。难道是vue-property-decorator的锅导致默认值没有拿到?于是回组件开发那边去掉外面包裹的组件进行尝试,发现是可以获取默认值的。

实在是没想到是怎么回事,于是我想既然你就是要有个Provide,那我这边也给你写那个组件好了。可是,当我自信的按下ctrl+s然后在浏览器上按下F5之后,页面彻底没了显示,同时控制台显示了一个这样的警告:

  1. Invalid VNode type: Symbol()

对于这个问题,我毫无头绪,只能上网去找,可是找到的几个情况都跟我这个不一样,所以并不能解决问题。于是我把代码恢复到了之前的状态,准备详细查看,然后我从一大堆error中找到了这样一条不起眼的警告:

  1. inject() can only be used inside setup() or functional components.

好家伙,这就去看vue-property-decorator那边Inject的实现:

  1. export function Inject(
  2. options: InjectOptions = Object.create(null),
  3. ): VueDecorator {
  4. return createDecorator((componentOptions, key) => {
  5. const originalSetup = componentOptions.setup
  6. componentOptions.setup = (props, ctx) => {
  7. const result = originalSetup?.(props, ctx)
  8. const injectedValue = inject(options.from || key, options.default)
  9. return {
  10. ...result,
  11. [key]: injectedValue,
  12. }
  13. }
  14. })
  15. }

嗯,确实是用setup做的啊,并没有什么问题。思来想去老久,没有想到啥答案。唯一能想到的是文档中提到了一句:


如果使用字符串 key 或非类型化 symbols,则需要显式声明注入值的类型:

  1. const foo = inject<string>('foo') // string | undefined`

但是我这样修改之后,问题仍然没法解决。

过了一天之后,想到那么vue是怎么判断我是否是在setup中调用的呢,会不会因为是因为vue3现在还不完善的bug?正好整个警告的点上是有堆栈信息的,所以我也就直接点击进去打了个断点一看,它的代码如下:

  1. function inject(key, defaultValue, treatDefaultAsFactory = false) {
  2. // fallback to `currentRenderingInstance` so that this can be called in
  3. // a functional component
  4. const instance = currentInstance || currentRenderingInstance;
  5. if (instance) {
  6. //...
  7. }
  8. else if ((process.env.NODE_ENV !== 'production')) {
  9. warn(`inject() can only be used inside setup() or functional components.`);
  10. }
  11. }

好了,首先确定了这个判断肯定是在vue调用setup时对currentInstance赋值,调用render时对currentRenderingInstance赋值,然后通过这两个变量可以获取到当前从属的是哪个组件。可是问题来了啊,为什么这个值会变成空的呢?回前几步继续调试看看。似乎没啥问题,每个组件都正常赋值了,包括这个组件也一样。那好,我多跟踪几步看是啥时候丢的。

可是跟踪了一圈好像没有其他地方会导致currentInstance变为空啊。似乎又没头绪你,然后我再调试了一次。嗯,等等,怎么还跳了个文件呢?再一看上面打开的文件才发现,好家伙,我们的组件创建都是在项目所属的文件夹下的node_modules中,[email protected]/ui/node_modules中,去看了下,这个文件真实存在。

嗯,破案了。同一个模块在不同的文件中,因为闭包,或者说模块独立性的问题,他们的变量当然是独立的。那怎么解呢?为什么npm会给我安装两个同样的模块呢。个人觉得npm可能是为了防止冲突,特别是版本冲突,所以,每个模块的运行依赖都会独立安装(这也是个麻烦事,所以cnpm在这里会用很多的快捷方式,而不是完全独立安装一份新的,但是我用的还是npm装的,不是说cnpm不好,而是这样可能会把问题掩盖过去,然后就一直没修复)。那么我要怎么操作才能告诉npm,安装我这个库就必须安装vue,并且这个vue跟项目还是得共享同一个呢?那就找找现成的别人的写法咯,比如ElementUI的package.json文件,然后就会发现有peerDependencies这么一个东西,它就是告诉npm,依赖这个包的项目必须要包含的依赖,并且这个依赖会在项目一级。这样就完事了?提交代码,github-action开始自动给我打包发布,然后我收到了运行出错的邮件,显示错误内容如下:

  1. Error: node_modules/vue-class-component/dist/vue-class-component.d.ts(1,39): error TS2307: Cannot find module 'vue' or its corresponding type declarations.

peerDependencies的依赖并不会主动安装啊,那么的话,就只能在devDependencies中也加入这个依赖,这样这个依赖就必定会安装了,ElementUI也是这么做的。虽然感觉还是有点怪怪的,但是至少,现在我这个库终于是真实可用的了。

再见珠海

2021-07-01 20:58:05

因为堂姐提起珠海的事情,毕业也有机会,于是我到了珠海。原本有同学跟我报了同一家企业的,但是最后还是选择了其他地方。于是最终,我独自来了珠海。因为种种原因我没有从事本专业的工作,而是被安排做前端,但是显然我能做。

那个公司在金湾区,说实话,在来之前我从未想过我根本就不是在珠海工作一样。从城轨下车,然后打个的?一看费油100+实在是打扰了,于是老老实实坐上公交,经历一个半小时多以后,我到达换成地点,看着地图上资深一小段了 于是我打算步行前往,然后发现这一小端是在前面一大段的映衬下才显得短的,实际上它是非常长的。换上下一趟公交大约20分钟之后,我终于到了。之后说到市区玩的,也感觉我根本就不是在珠海,而是在珠海附近的一个县。

在那之后,基本上就是过得不好不坏,想着过完3年再说。可是很不巧,公司上任一个新领导,想搞点政绩,先动了一波绩效标准,然后又来一手请假的限制。于是开始有人离职,不过一次也就一两个。我当时也只是先这领导也太**了吧,然后想着准备是要做3年内就走的准备,可是年底问题就全部暴露出来了。在公司上班的,有相当一部分是外地的,过年总得回家啊,可是回家不仅票难买 并且由于公司位置的原因,可以赶得上的车又少了,不请假是不可能的,于是开始集体离职了,自然,我也走了。当然了,听说现在那边也意识到问题重新调整了政策。

当然,我这中间留了一些时间。出来之后,毕竟是过年前,找个更好的岂不是一件美事?然后注册招聘软件把意向地址改到了珠海市中心。然后很快就有公司联系我了。因为疫情原因,我这边面试之后就匆匆离开珠海也没做更多的考察了。回去之后有几个好机会,但是最后还是来了这边。

这边说实话,在技术上进步的空间不是很大,但是看在公司提供的住宿上还是留了下来(注:这里已经折掉了一段我的工资,本来我要求更多的工资的)。可是转正后没多久公司就安排宿舍调整,而原本的那套被作为女生宿舍了。而这边的宿舍,顶楼,面北,没装修。甚至很多小事都解决不好。而老总给出的方案是要我们自己可以出钱添置东西或者出去租房。对于这个结果,正常来说没啥问题,但是问题就在于这里已经相当于抵了我一定的工资了,而公司也不打算把这部分还给我,那么也就双是到这里就只能走人了。

我挺喜欢珠海这边的环境的,但是珠海市区的房价实在是跟工资不成比例。也只能就此告别了。

React初遇 对比vue

2021-03-09 14:37:28

最近开始在学习React,在此之前只对vue有一定研究,虽然说框架的思路是相近的,但是实际上还是有一些差异的,所以在这记录一下。

既然要学习React,那么首先是打开它的官网看文档咯。打开React的文档之后,首先看到的是熟悉jsx的写法。想之前刚刚工作第一次接触vue的时候,看到jsx的时候就封蒙——为啥这样的东西还能在浏览器中执行?vue虽然平时都是通过模板,但是同样可以使用render函数,实际上在vue的项目中会把模板语法编译成render函数,并且在render中通过Babel插件可以实现jsx的写法。这个jsx实际上并不是js的东西,只不过会在打包过程中被相关插件(目前普遍用的Babel)转换成浏览器可以自行的代码,类似于createElement这种方式。而在浏览器中之所以能调试并且看到jsx的写法运行,那也是在source map的帮助下找到了执行语句被编译之前的样子。以前无论是js还是css等文件,在网络传输的时候,都可以删掉空格和换行符来减少体积,到后来甚至直接将长长的变量名字替换成只有一个字符的名字。但是这样一来,这份js代码虽然执行起来没有任何区别,甚至可能有更高的执行效率,但是对人来说已经完全不具备可读性了,这就如同被编译成二进制的C语言程序一样。庆幸的是出现了source map,通过它可以将这份被压缩的代码与原始的代码联系起来,这样就可以调试了。虽然不是所有浏览器都支持,但是万幸的是,这个标准是不影响在浏览器中执行的情况的,仅仅是在调试的时候才会需要这个东西,并且如今哪个开发人员会没有谷歌浏览器呢?随着前端技术的迅速发展,打包技术的出现,这一切几乎是翻天覆地的变化。这甚至意味着,可以甚至可以通过c的语法写一段代码,并将其打包成一段实现相同功能的js代码,然后浏览器执行的还是js代码,但是通过source map可以看到c的那段程序在执行,对付一个小小jsx当然也不是什么难事。

接下来的部分似乎没有啥问题,一直往下走,组件这里,可以看到React的组件可以是函数声明,也可以是类声明。函数声明的方式非常简洁,虽然vue没有,但是这并不难理解。类的声明方式是ES6语法,并且类从React.Component继承,使用构造函数的时候,记得调用父类构造函数。相比之下,vue的组件是一个对象,里面分类存储着参数信息(props)、数据(data)、方法(methods)和生命周期钩子等,当生成组件的时候,vue会对应处理各个部分,比如根据参数信息读取参数或设置默认值、方法使用bind(this)进行绑定,并添加到this上,用的时候都是通过this访问。而在React中参数会被作为类的参数传入,由React.Component的构造函数处理到this.props上,而自身状态可以根据实际情况放在this或者this.state上。但是vue中更新自身状态直接设置就好了,而React则需要调用setState才能追踪数据变化。原因在于vue使用了Object.defineProperty做数据劫持(vue3中将会使用反射,这更方便,不过其实我有点担心反射的性能),给data中字段的数据设置值的时候,会调用对应的set方法实现检测,同时,也正是如此,vue可以做到更加精细的更新。

vue与React生命周期对比

接下来就是声明周期了,vue的生命周期钩子特别多,创建时会依次调用beforeCreatecreatedbeforeMountmounted四个钩子,分别在组件创建和挂载前后触发。销毁时则有beforeDestroydestroyed的两个钩子,更新时beforeUpdateupdated两个钩子,这些都是在几个关键的事件前后的钩子。此外,还有几个其他类型的钩子。而在React中,构造函数本身是一个很好的声明周期钩子,他对应着vue的beforeCreatecreated。一般在组件挂在前的事情可以在组件创建做完,所以React中只有componentDidMount与vue的mounted对应(实际上是存在componentWillMount的,但是大概是没啥用所以准备取消了)。同样,销毁完的组件也没有任何可以访问的数据,所以React也只提供了componentWillUnmount与vue的beforeDestroy对应。在组件更新时,钩子有shouldComponentUpdatecomponentDidUpdate,其中shouldComponentUpdate主要用于判断组件是否需要更新(虽然也有componentWillUpdate,但是同样即将过时。。。)。

然后再说说插槽,React支持插槽,但是在使用的时候还是有些区别的:不像vue插槽有专门的$solt,React中的插槽会被作为参数children传入,使用时使用this.props.children访问。匿名插槽在传入子组件的时候和vue一样处理,对于需要使用具名插槽的时候,则需要以js对象的格式写在子元素内部,同时用对象的方式访问this.props.children

ref引用在React中也有很大区别。首先,ref引用需要React.createRef()来创建,同时,他是给原生dom组件用的。如果要访问子组件,React通常使用参数传入一个方法,然后子组件通过这个方法传入自身或相关方法给父组件保存后才可使用了。

好了,文档里面看到需要注意的基本都看了,接下来就是看实际项目了,不难发现ui用的是antd,然后查下它的文档,当然这些ui库都是差不多的,没有特别需要留意的地方,不过表格跟之前用的库还是有些区别,但是也不难。

然后看到了另一个东西——mobx,这个初一看是个状态管理,那就类似vuex。当然它确实是个状态管理,但是由于React本身是没有做数据劫持,mobx却是可以实现这一点,所以,在这里面可以实现诸如计算属性之类的操作。当然,,mobx通常配合装饰器语法使用,这又是个新概念,但是这显然是在java中的注解语法中获得了灵感(之前碰到的箭头函数,虽然有点像PHP中数组键值对的写法,但是显然灵感来自lambda表达式,格式和C#的lambda表达式完全一致,且java中也引入了非常相似的lambda表达式语法)。当然,有看到mobx做了一些顺序上的优化和其他处理,使得mobx性能更好,但是可能会带来一些问题,目前暂时没看明白具体有啥影响,但是碰到问题的话,这可能会是一个排查的点。

除了mobx,React还有个状态管理叫做Redux,因为暂时用不上没细看是否是有做数据劫持,不过这个状态管理的理念上,存储的状态是个快照,所以不应该直接改变状态,如果需要改变状态,就需要action。这类似于vuex的Mutation操作state,所有操作全部对应一个方法,通过参数进行区分。当然这是一个大致的使用,实际使用是可能会发现更多问题并需要注意更多细节。

参考链接

  1. React文档:https://zh-hans.reactjs.org/docs/
  2. 具名插槽(React):https://blog.csdn.net/u013611033/article/details/105566201

宝藏世界视频文案

2020-12-09 17:11:35

在11月国服被关之后就有了做个工程量大点的纪念视频的想法,毕竟玩了3年多的游戏就这么没了。但是那时候缺少具体想法,缺少素材等因素一直搁置。随后国服暂时重新开服,考虑到单个视频时间不宜太长,所以先录了一段工会纪念的,毕竟这是个多人游戏,工会最能体现这个特点。之后翻自己存的素材,有想对整个游戏和我自己一路的发展做时间线来做个纪念视频的想法。

在工会道别视频之后就开始了这个视频的素材整理和收集。因为最开始玩这游戏的时候也没想过会花这么多时间,也就随便玩玩,所以早期的素材都挺少的,不得不重新补录了一段,补录的那段肯定不会是当初的效果,再比如开头打本那段,我当时是用的骑士的,但是骑士已经改版了,前期打不出那么高的伤害了,所以用小号枪械打的,不要去在意那些细节了,然后从网上找了几段素材。

因为我手上多人的素材其实挺少的(应该说啥素材都少,一个是当时配置不行,另一个是当时也没想着录制),特别是多人部分的。作为一个社交游戏,很大程度上能坚持玩下来,一方面是自己号玩了那么久,另一方面也是认识的人在,或者认识更多的人了。所以决定在结尾插入一点多人素材和感谢名单。

接下来花了两个晚上处理bgm衔接。虽然最后效果还是不尽人意,毕竟水平有限,实在是不会弄。

然后就是把手上的素材串起来了,这里花了好几天的时间。中途发现还是缺少很多素材,所以这一段补的素材都没问原作者了。

所用bgm:

第一段:游戏开局原声录制,祖传游戏bgm,也是萌新时候本着尽量使用游戏原本bgm玩游戏的想法一直听着的。

第二段:《没有什么不同》,这时候也象征着我听腻了游戏原祖传的bgm,已经关掉游戏bgm自己放音乐了。同时也算是纪念那时候花的时间和精力。

第三段:《红尘客栈》,这时候其实我玩游戏的时候已经没有放bgm了。不过这歌也是那个时期听到的所以拿过来试了下,好像能接上就用了(之前还试了点别的)

第四段:《好好》,这算是规划时预定就用的结尾了。3年,我们不仅要好好的开始还要好好的结束。

使用的他人素材:

冰法究无畏那段素材:。来自羯大佬。也是我最早去问着要的素材,毕竟这也算是一段珍藏的回忆了,谁能料到有一天冰法的技能会有这么大的改动呢?当初也正是看这个视频开始初次拉究无畏的尝试

4.1s究月:。来自大笨笛。国服记录,我也参与了肯定要的。看不到我可以参考这个视角

宏无头究月:。来自铃音。不知道那时候玩过的还有没有人记得铃音的宏呢?(虽然我一直用的自己做的。。)当时系统资源实在有限 仅仅找到几个刚出无头时候的视频。那时候我还在弄枪呢。不过根据视频时间来算的话,我那时候也2w5+650总了。

小丑任务:

碎掉的宝石:。找遍了找不到升宝石碎掉的视频,虽然我还存着一个碎了的宝石,但是没有这个真实。

2020-08-22 11:34:10

有个小孩,在父母的陪伴下,在迷宫中探索着。迷宫中有些台阶,小孩每次通过都会摔跟头,长此以往,小孩开始对这些台阶有了厌恶的心里。但是小孩对这个迷宫仍然充满好奇,仍然在孜孜不倦的探索着。小孩在慢慢长大,父母逐渐跟不上小孩的步伐。小孩开始有了一个人探索的时间,在这些时间里,小孩只要有其他路可以选择,就绝对不会碰有台阶的路。甚至他会避开陡坡。

时间飞逝,转眼小孩已是少年。父母已经完全不能跟上他的步伐了,他也在路上认识了许多小伙伴。能跟着这些小伙伴一起探索迷宫,一起休息,少年感觉十分愉快。但是并不是每个人对这个事情那么愉快,他们不希望那些走的慢的影响到走的快的人的步伐。于是在某个月黑风高的夜晚,他和他的小伙伴被分隔开了,在黑暗之中,少年或许是因为过台阶时不利又或许是因为根本就绕过台了台阶但走了一条更远的路,他终究没能和他曾经的伙伴走在一起,现在在他身边的几乎都是未曾相识的人。当然,也还是有曾经那群伙伴中的也出现在这了,但是,曾经他那些有说有笑的伙伴却都在篱笆另一侧。每当附近没人时,他就会伤心的哭,但是他并没有意识到这场分别意味着啥。他渐渐发现偶尔在篱笆矮下去的拐角,他偶尔还能和曾经的那些小伙伴见面;但是他也发现新的小伙伴前进的速度都挺慢的,甚至有许多放弃前进的。少年不愿和他们为伍,但是他也不愿意孤身前进。于是当看到拐角时,少年就会跑过去试着和曾经的小伙伴谈笑;而其他时间,或许是因为奔跑得太累亦或是想等个人一同前进,也或许因为他不想通过哪些台阶和陡坡,感觉要长期跟上以前的小伙伴已经很难了,虽然他还在向前走着,但是脚步却慢了不少。终于,他跟后面那些走的比较快一点的到了一起。

但是这样的日子持续不了太久,他们在一个路口再一次分别,他们已经错过了更近的路,只能选择自己更愿意去走的路了。于是,在新的道路上,少年认识了许多跟他一样不愿走台阶或是陡坡的人,尽管大家嘴上互相勉励着,但是真正碰到台阶或是陡坡的时候,通过的人总是那么少,大家实际上仍然更多的时候在通过自己更熟练的地形。与此同时,少年也已经成为青年,他对迷宫本身的兴趣已经开始逐渐减退,他已经知道,这个迷宫是永远也走不出去的,他要做的收集迷宫中的吃的,至少有一天自己走不动路了也不会饿死。他所看中的是一块较大的饼和一块中等大小的饼。那块较大的饼在迷宫更深的地方,距离是如此遥远,并且路线也更为复杂。他并不想,让自己太累,何况边上和后面还有那么多人,他们甚至可能连更小的饼都吃不到,于是他选择了那块中等大小的饼,倘若有可能,就再去拿那个更大的饼。当然,这段路对他来说,虽不是触手可及,但也并非那么遥远,只是他不走台阶不爬坡的习惯让他绕了一大段路。不过考虑其他人也同样在绕路,因此他似乎仍然走在前面。于是他在一边向前走着,一边探索着迷宫中其他花花草草,或许有一天,这些花花草草能做成调料——枯燥的迷宫还是需要有点调节。

终于有一天,他拿到了这个饼,虽然不是更大的那个,甚至还撒了一点,但是他至少还算愉快的拿到了这个饼。他等这一天很久了,虽然他也眼馋更大的饼,但是他实在是等不及了。他拿着这块饼,沾着自制的调料美美的吃了起来,一切看上去都是十分美好的。可是日复一日的吃着相同的口味总有一天会腻,他需要去换一些其他调料来解决问题。而这时他才发现,自己材料并不都能转化成调料或者食品,而能做出来的那些,虽然味道不错,但是比起市场上那些调料却又缺少包装,这导致他要换更多更好的调料变得非常艰难。长此以往,他开始有点厌倦了眼下的生活。

有一天,他遇到了一个已经吃到更大的蛋糕的人,但是那个人仍然在向前探索着。他拿手中的饼换了一些蛋糕来品尝,但可惜,饼实在太小,换不来更多的蛋糕,而别人还要继续前进。见过真实存在的蛋糕之后,他便觉得空气中偶尔飘来的山珍海味的气息也来自迷宫之中,只是在某个角落等着人去发现,手中的饼已是味同爵蜡。于是他想,他为啥就不能为了更好的目标继续前进呢?细细想来,他曾经也不是拿不到那张更大的饼,这或许需要一点运气,但是他曾经也有这个能力。而那些冲在更前面的,却也未必走得比他快,也未必休息得比他少多少。诚然,这中间不乏一些出生就在更前面的,但是如果不肯跨越陡坡和台阶,或是其他情况而绕路的话,这便会比别人慢很多,如果过多的贪恋休息的话,更是只会停滞不前。于是他便想继续探索,而他前进的动力已经不再是为了探索本身,而是寻找更好的食物。虽然他对那块更大的饼有了些怨念,但是他已经不需要更大的饼了,也来不及去拿了。他只能转身走边上的小路去探索其他东西。这边的地形更为复杂,也不像之前有人或者路标能指明方向,即使偶尔能见到一处路牌,几乎也都是在灌木或草丛之中,这中间,既有真正的方向,也有纯属而作剧的玩笑。而他探索迷宫的能力也已经随着时间流逝消退了不少——即使是以前能轻松通过的平路也让他气喘吁吁。而路线上更是一次又一次拐进同一个死胡同,而这种试错的成本却又随着时间推移逐渐增加。他不敢贸然前进,独自向前可真不是那么容易的。他希望能有个灯来照亮前进的路,可是他没有;他希望有束光能指出其他食物的位置,可是这些食物的位置本就是随机的;他希望有个人能一同前进,一起面对路上的困难,可是大家却不得不各自选择自己的路。或许有一天……,也或许……。

分类列表更多
杂项
。。。