WordPress博客项目改用react前端展示

之前自己的主打技术栈是vue全家桶,所以将自己的wordpress博客改成了vue版本服务端渲染,现在因为公司需要将我的项目从vue转到react,本人后面可能也就要主打eact技术栈了。 我记得这个网站还是在清明节假期三天改造完成的,当时还写了一篇《道招网终于完成改版了》,想不到这么快又要改了,当然这次我是不准备额外增加功能,主要以迁移技术栈为主,虽然自己最开始学习框架的时候是使用的react了,但是长期使用vue,对react还是有些手生了,最近会抽时间补齐这个短板,目前我也在进行简单的开发了。 这个换成react决定尝试些react的新功能,比如hooks,我之前只知道有useState、useEffect,想不到其实还要很多哦,比如useReducer、useMemo等,不得不说react就是相对好玩些。 我个人也比较偏爱函数式编程,所以很自然会喜欢函数式组件多一些,刚好现在可以多用用了。 react也不是说什么都香的,比如react的jsx在写“html”时是再次把我恶心到了,vue那种更清晰些。 言归正传,目前道招网的react改造之旅已经正式开始了,目前还剩下的主要工作是 组件还剩70%,有列表、详情、分类、标签、翻页等 redux 服务端渲染

富文本编辑器wangEditor多语言、工具栏体验改造

支持多语言 首页wangEditro本身是支持使用多语言的,通过源码可以看到里面有个replaceLang方法,虽然这种写法有点非主流,但是是有效的,里面部分地方在支持多语言方面有些遗漏。 以“加粗”功能为例 // 构造函数 function Bold(editor) { this.editor = editor; this.title = '加粗'; const title = replaceLang(editor, this.title); this.$elem = $( '<div class="w-e-menu">\n <i class="w-e-icon-bold" title="' + title + '"></i>\n </div>', ); this.type = 'click'; // 当前是否 active 状态 this._active = false; } 看下replaceLang方法干了什么 /* 替换多语言 */ var replaceLang Read more…

命令式组件Message、Dialog的主流写法分析

这里还是以element-ui为例,那我们就看看里面的Message。 它的dom结构什么的就写在node-modules/element-ui/packages/notification/src/main.vue里面 <template> <transition name="el-notification-fade"> <div :class="['el-notification', customClass, horizontalClass]" v-show="visible" :style="positionStyle" @mouseenter="clearTimer()" @mouseleave="startTimer()" @click="click" role="alert" > <i class="el-notification__icon" :class="[ typeClass, iconClass ]" v-if="type || iconClass"> </i> <div class="el-notification__group" :class="{ 'is-with-icon': typeClass || iconClass }"> <h2 class="el-notification__title" v-text="title"></h2> <div class="el-notification__content" v-show="message"> <slot> <p v-if="!dangerouslyUseHTMLString">{{ message }}</p> <p v-else v-html="message"></p> </slot> </div> Read more…

已购一年多macbook换电池 touchbar维修记录

本人的macbook pro是2018年8月从官网购入,走的教育优惠(淘宝搞定),春节疫情在家期间发现电脑底座盖不严,整体跟以前比差太多了。 前几天打电话给苹果客服了,说换电池要3000多,我的电脑过了保修期一年了,不能免费换。 我就想着要不干脆自己换了啊,淘宝买个电池自己换,对,没错,就这么干。 换到一半发现买电池送的苹果笔记本维修起子不够用,有两个特别点的螺丝没有对应的起子。 这里我简单介绍下苹果笔记本的常见螺丝 开后盖的是个五角螺丝1.3mm,等开完后盖里面的螺丝一般都是六角的了, 其中有几个螺丝是T5,我在买电池里面的就是上述两个起子,但是图中的两个六角起子刚好没有,拆到最后两个螺丝没法弄了,你说气人不气人。 就是图上的两个螺丝,型号是T3 最后在网上搜了下,才知道有个叫南旗的品牌有个,最后听说小米有套电动起子,也有这个型号,一般专业的叫法叫批头。 拆卸电池过程中,用起子撬了撬,竟然还起火了,着实吓了我一跳。 换完开机,没反应,怀疑是那个电池插线没有插紧,因为自己没有专门的镊子,为了保险起见,自己想办法弄了弄。再次开机,还是没反应,冒着笔记本可能爆炸的风险,插上电源开机,终于开机成功了。 最后想了想,自己的touchbar想换有段时间了,干脆去苹果自营店试试,如果不要钱我就在那修,要我掏钱就不修了。 等预约到了苹果自营店,天才吧的工作人员说这个保修,我说那就帮我换下键盘,他就说你这是打擦边球啊。笔记本的主要部件在中国是保修两年的,这不是苹果政策,这是中国的消费者保护法的权益,感觉在中国这特权不错,对吧。我一听有戏啊,因为我知道我的笔记本是可以免费换键盘的,依据在此。 适用于 MacBook、MacBook Air 和 MacBook Pro 的键盘服务计划 等他查完序列号后说可以换,发现我的笔记本是美式键盘,不是中国式的,等有货了再通知我来换。 等我换回来了发现C面,电池,键盘,touchbar一并换了,如果根据上面的清单,换这些东西没有想象中那么贵。是我太天真? MD,早知道我不换电池了,LZ刚自己换的电池又被换了,逗我呢。 苹果电话客服和部分网上看的消息不靠谱,早知道自己亲自去苹果问了。

怎么便宜价格付费看O’Reilly(原safaribooksonline)动物出版社的电子书

2018年10月的时候看到有网友发广告说可以以99RMB/年的价格程看O’Reilly,立刻就心动了,作为搞编程技术相关的,应该都知道O’Reilly吧,很多知名书都是里面英文原著的中文版。比如《你不知道的Javascript》上中下版其实就是6本小册子的合集。 99RMB的价格着实让人心动,但是我更希望的是这个渠道稳定,及时涨价一下,只要在接受范围内都可以,我最怕的是一年到期了无法续费,或者续费价格高的接受不了,那样我在看书的时候都不知道怎么做笔记,如果账号废了,笔记很可能也就没了。这个渠道其实是通过注册成acm的会员,acm的会员可以通过SSO登录O’Reilly免费看里面的电子书的。 看到了2019年10月份小伙伴提醒续费了,我很快付费了,当时小伙伴告诉我其实现在涨价了,是199RMB,但是我是老用户,不涨价。其实199我也是能接受的,可是在2020年2月左右我发现登录有些问题了,经常登录不上O’Reilly,我在acm上登录,发现其实我的会员已经月2019年10月份过期了,我当时怀疑难道是小伙伴没有给我续费?骗我这个99月也搁不着啊。给小伙伴发微信了,因为没什么交情,回微信很慢的那种,可能是小号吧。 我写信给O’Reilly官方了,证实确实是因为过期了,凉凉了,99RMB到无所谓,我的笔记啊,我在O’Reilly可是看了一年多的书啊。我最近又给小伙伴反馈这个问题了,但是听说其他人貌似没有问题,也不知道其他人还在不在用,小伙伴很爽快的主打把99RMB退还给我。 我在百度搜O’Reilly的过程中发现可以通过注册中国计算机学会CCF的方式来成为acm会员,那样理论上我也就可以继续通过新的acm账号看O’Reilly,当然,换了账号笔记肯定没了,我的老帐号现在登都登不进去,O’Reilly貌似也没有导出笔记的功能(我提过意见,没有见改进)。 并且最近前几个月ccf和acm的会员费貌似也涨了,但是还是能接受的。 其中ccf的会员是到2021年12月31日,acm的付费信息会在25日推送给acm,次月10日应该能收到注册和付费反馈。坐等。。。 –以下是2020年6月13日更新— 今天没事看了看邮箱,发现acm会员这个早就好了 5月28号就收到acm发的续费邮件了 登录acm也能看到 之前在acm交了133RMB,按照人民币美元7:1的话,就是19美元,价格不算贵。 在acm的收据里面可以很明显的看到是通过ccf这个渠道续费的,里面有ccf的会员号。 我以后就长期稳定的通过这个渠道看OReilly了,不错。

邮箱收件人组件(vue版)成长历程(一)

前期项目中需要优化原始的收件人、抄送、密送部分,换成更加现代化的样式和用户,当时将这部分抽象成一个组件了,最近的需求是发件人也要使用该组件,鉴于发件人比收件人等需要校验的地方和交互习惯变动点较多,进行了重构,在此过程中发现自己当初思维还是比较局限,特发文记录下。 先看看发件人组件的样式吧 很显然,这里的收件人支持最少两种写法,一种是纯粹的只有收件地址,比如第一个test@qq.com,同时也支持第二种写法是带收件人和收件人地址另一个测试<anthortest @qq.com>,毕竟在可读性上第二个比第一个要好。 以下为了方便描述,我们把第二图中的第一个收件人状态称为预览态,第二个收件人状态称为编辑态。 当时产品是参考网易邮箱大师(万恶之源)来实现功能的 总共需要支持以下功能 test@qq.com和另一个测试</anthortest><anthortest @qq.com>两种格式 在预览态校验邮箱合法性并进行对应的标识 预览态双击进入编辑态,失去焦点或者回车后回到预览态 支持搜索,搜索候选项能用键盘上下键实现选择,能够用回车上屏 预览态时支持鼠标单击后高亮,图一中第一个就是被点击选中的,颜色与第二个稍微有点不同,再删除键时删除,删除后光标在前一个内容后面,并且可以一直向左删除 点击两个收件人预览态(如果有的话)中间空白处插入新的,然后再按删除键可以一直向左删除 兼容Outlook、网易邮箱大师的收件人的复制、粘贴 当时主要参考网易邮箱大师客户端和gmail邮箱网页版 当然要看代码实现的话,只能看到gmail邮箱的,它的交互不太符合产品要求,但是那都是不是技术难点。 首先需要支持这些样式,原来的input是肯定不行了,那只能div了,怎么让它可编辑呢?我发现gmail在输入还是用的input,预览态时是用的div实现,当时出于挑战自己和青铜的倔强,想试着换个方案,完全使用可编辑div来实现。。。这个小小的倔强为后续很多功能瓶颈埋下了隐患。。。 整体逻辑 我们知道这个组件里面的内容其实是一个数组,数组个每个元素都是一个收件人对象。比如: { label: '另一个测试', value: 'anthortest@qq.com', editable: true, } 我们可以用一个属性editable,来控制当时是否是编辑态还是预览态,数组里面最多只会有一个是编辑态,让里面任何一个收件人失去焦点后或者被外部赋值后进行校验并更新预览态。在整个组件空白区域内点击时就网数组里面的合适位置插入一个收件人对象,并将其editable属性置为true,然后显示对应的光标。 我们可以把整个组件分成三个部分,一个是主组件main,一个是显示/输入组件inputItem,一个是候选词列表组件candidateBox 控制鼠标光标 这个应该是最先要考虑的问题,在contenteditable的div里面是点击到哪哪里就有光标,比如在预览态双击进入编辑态后,如果含有收件人信息的化,编辑态的需要展示的内容明显要比预览多的,这时怎么控制好光标到最后面呢? 此时光标默认在它的最后面,其中光标的实现可以用Range实现 const blank = document.createTextNode(''); const range = document.createRange(); range.selectNodeContents(blank); // 让光标聚焦在最后面 getSelection().removeAllRanges(); getSelection().addRange(range); 校验 在任何一个收件人信息输入失去焦点的校验,并更新预览态 响应点击 这个需要布局配合 Read more…

加个分享印象笔记收藏内容的功能?

自己长期是印象笔记的会员,在最终决定使用印象笔记的前使用过一段时间的evernote,最终还是因为印象笔记的本地化做的好,会员价格没那么贵而选择使用印象笔记了,数据放在国内就国内吧,国外也不一定没人审查。 自己比较早的使用用过印象笔记的api,可以实现访问自己访问印象笔记内容的功能,当时就想着可以做个网站,但是里面使用的是印象笔记收藏的文章,这样自己就不用自己写了,东西全存在印象笔记,这也不是不可。但是最后还是因为拖延症没有实施这个计划,下步有时间就一定把这个事情办了。 最近发现印象笔记的沙盒地址进行测试时老是超时,有碰到这样的朋友吗 可别凉凉了啊,虽然我一直感觉印象笔记现在貌似没有更新甚至维护开发这一块了。 我的开发项目还没有正式上线了,可别让我到时候想上也上不了啊。 顺便提一下,在使用印象笔记开发的时候链接沙盒环境http://sanbox.yinxiang.com/ 默认是有问题的,那是因为evernote官方的npm包就是有问题的(印象笔记照抄了,所以这个问题也抄过来了),我看早就有网友提PR了,但是evernote官方并没有采取任何措施,这样是我怀疑这个开发功能没人维护的原因。 在node_modules/evernote/lib/client.js里面默认没有针对印象笔记的沙盒环境做判断,所以这个问题也就只有使用印象笔记开发的时候会遇到。。。 if (this.sandbox) { defaultServiceHost = 'sandbox.evernote.com'; } else if (this.china) { defaultServiceHost = 'app.yinxiang.com'; } else { defaultServiceHost = 'www.evernote.com'; } 很简单,我们应该改成 if (this.sandbox) { defaultServiceHost = 'sandbox.evernote.com'; if (this.china) { defaultServiceHost = 'sanbox.yinxiang.com'; } } else if (this.china) { defaultServiceHost = Read more…

WordPress项目做vue的后台管理系统

鉴于最近很多朋友想利用手上的wordpress博客来做后台系统,前端页面想使用自己更加上手的vue或者react来开发。 这个想法和我当时差不多啊,我当时就是不想继续使用自己的WordPress做前端界面,但是又不能不用WordPress,毕竟自己又不想开发后台系统,WordPress本身的插件、设置等功能自己还是想继续利用的。 现在道招网就是这样的一个混搭系统了,自2020年4月6日《道招网终于完成改版了》以来,也运行了差不多一个月了。 我就来说说目前的一些感受吧。 接口需要自己重新封装下,及时是使用WordPress的restful接口的话也是需要二次封装的,具体可以参见我之前写的《wordpress的restfulAPI接口返回数据的几点分析与处理》。 2.WordPress的前端显示用的plugin、widget、友情链接等就用不了了,比如存档、联合登录、推荐文章、热门文章等。 建议自己开发些WordPress插件,最基本的是需要有一个类似webhook的插件,这样我们在发布或者更新文章的时候就可以有更大的发挥空间。 页面显示的title、SEO相关的keywods等信息要自己想办法动态设置下,毕竟SPA的通病。 个人建议利用现成的数据库ORM(比如sequelize),来处理数据查询相关的,毕竟想自己重新做前端部分,有时没有接口支持也不行,推荐使用个WordPress插件debug-queries,这个可以参考下WordPress页面使用了哪些SQL语句的。只要自己熟悉数据库会写SQL,写出对应的接口供前端使用还是很方便的,想尝试GraphQL的这是个不错的机会。 天高任鸟飞,海阔凭鱼跃。

Javascript去除内容格式并匹配目标格式粘贴

先说下需求: 支持将复制的文本内容粘贴(包括覆盖)contenteditable为true的目标div里面 复制内容的文本如果有多行,粘贴后需要保留它们直接的换行效果 如果覆盖的目标div有多行文字,粘贴内容需要匹配第一处文字的格式(样式都是以内联形式写入style中) 比如我们想将复制的文字,覆盖粘贴下面的目标div中,文字保留换行后,格式(字体、字号、颜色等)应该跟第一行加粗的保持一致 下面我们举例说明 我们需要复制的文字 我们准备覆盖粘贴的目标 很显然,需求要的效果是这三行文字保留换行效果,并且格式跟“伙伴”一致,即也是strong效果。 应该是如下: 下面看看这个需求的解决思路 我们很自然的会想到下面两个场景 不干预,直接用浏览器默认行为 使用document.execCommand(‘insertHtml’, false, ‘粘贴内容’)的方式 不干预效果 内容是进来了,但是保留了复制源的格式,不符合需求。 document.execCommand(‘insertHtml’, false, ‘粘贴内容’)效果 没有复制源的格式了,但是粘贴后格式不匹配,不是想要的strong效果,并且字体还变小了。 看来我们想偷懒,利用浏览器自带功能是不行了,我们继续拆解问题。 复制的文字需要分成‘三段’,每一段之间有换行,其中这里面就有很大一个难点,怎么换行? 在图中我们看到的换行,其实是由于有换行符的效果,我们肉眼看不到它而已。 如果你的需求是一定要保留这个换行效果,那我们只能使用<br />了。 const getPastePlainText = (win, e) => { const clipboardData = e.clipboardData || e.originalEvent && e.originalEvent.clipboardData; let pasteText = ''; if (!clipboardData) { pasteText Read more…

vue内置组件keep-alive源码解析

很简单,我们直接看vue的源码即可。 keep-alive组件支持三个属性。 props: { include: patternTypes, exclude: patternTypes, max: [String, Number] }, 其中patternTypes = [String, RegExp, Array]; 组件在created周期时初始化自己的记录集合 created: function created () { this.cache = Object.create(null); // 以组件实例的 key和vnode作为key-value存入其中 this.keys = []; // 存储组件实例的 key }, 在mounted周期里面开始注册自己的watch,watch自己的include和exclude属性进行pruneCache。 mounted: function mounted () { var this$1 = this; this.$watch('include', function (val) { Read more…