首页
Search
1
解决visual studio code (vscode)安装时没有选择安装路径问题
321 阅读
2
如何在 Clash for Windows 上配置服务
216 阅读
3
Linux 下 Bash 脚本 bad interpreter 报错的解决方法
150 阅读
4
Arch Linux 下解决 KDE Plasma Discover 的 Unable to load applications 错误
149 阅读
5
uniapp打包app提示通讯录权限问题,如何取消通讯录权限
113 阅读
clash
服务器
javascript
全部
游戏资讯
登录
Search
加速器之家
累计撰写
1,202
篇文章
累计收到
0
条评论
首页
栏目
clash
服务器
javascript
全部
游戏资讯
页面
搜索到
1202
篇与
的结果
2024-10-21
博客,就是一个折腾
前几天,即使工作很忙,也从鲁迅的海绵里挤出了点水,来给自己的博客小小的改造了一番。样式上没什么大的改动,主要的改动是集中在以下几点: 1. 评论系统前端部分的改造 # 目前是去掉了每篇文章里的分页设置,毕竟,文章也没什么人评论,还要费劲设置个分页,没什么必要,也就给去掉了。同时,对评论功能进行了组件化的开发,方便以后的开发和维护,按照功能拆分出了几个单独的组件: 发布组件、列表组件、按钮组件、Toast 提示组件、弹窗组件等等。以前没有拆分开的时候,这些功能全部都耦合在一起,有需要改动的时候,特别不方便;现在假如还有什么改动时,就方便多了。再一个就是样式上的调整,把发表的时间和回复按钮放在了左侧。虽然评论列表里的右侧显得稍微有点空,不过按照大众习惯靠左侧浏览的习惯,就把发表的时间与回复按钮与用户的昵称放在了一起。 2. 去掉了 jQuery 类库 # 在改造的过程中才发现,在每个页面里都引用的 jQuery 库,原来只是在文章页的侧边导航里用到了,其他的地方都没有用到。如果这么小的一个功能,还要每次都要加载 jQuery,那确实是太不值当了。因此这里就彻底用原生的 ES6 重写了侧边导航,顺带还搭建一个基于 webpack 的脚手架,关于这个脚手架的搭建和使用,我会后面的文章里详细描述(虽然已经有很多人搭建过了)。 3. demo 页面 # 博客最开始是用 jekyll 生成的静态博客,那时候的 demo 页面都是直接写静态页面,然后git push就能直接发表了。后来博客改造成基于 php 的动态博客后,托管在服务器上,如果要上传文件的话,是需要使用 ftp 的,那么直接上传 demo 页面就不方便了。于是就在管理员后台添加了一个直接上传 markdown 代码和 html 代码的管理页面,这样就实现了左侧代码、右侧功能的 demo 页面。可以点击后面的链接查看下效果,不过样式确实有点辣眼睛: 测试 demo。 4. 文章页里图片大小的限制 # 之前插入在文章页里的图片,是只限制了图片的最大宽度不能超过文章页的宽度,高度并没有限制,那么如果有图片很高的话,就会占据很大的版面,图片很宽的话,就会压缩图片,导致无法看清图片上面的内容,于是这里就添加了一个点击图片放大的功能。这里用到了一个小小的知识点: cursor。在 CSS3 里,cursor 的值为zoom-in时,鼠标就会变成+号,表示放大的意思;cursor 的值为zoom-out时,鼠标就会变成-号,表示缩小的意思,然后我们再添加上相关的事件即可;不用再像以前那样还得先生成两张放大和缩小的.cur图片了。比如目前网页版微博,考虑到浏览器的兼容性,依然还用的 cur 图片。点击图片查看下效果:总结: 自从有这个博客后,真正有价值的文章没发表多少,净瞎折腾这个博客了[手动捂脸哭]。
2024年10月21日
14 阅读
0 评论
0 点赞
2024-10-21
Vue: 单页面应用如何保持登录状态
在单页面应用中,若刷新页面后,登录态是保存不了的。比如我在首页获取到了登录信息,然后存储到vuex中,进入到某个路由中,若当前路由刷新后,vuex中的数据就会被清空,以此也会导致当前路由中依赖登录态的接口都会失效。那么,若当前路由需要刷新,或者当前路由存在第三方的跳转链接时,该怎么办呢?目前是有两种思路,可以供大家参考一下: 1. router与vuex的结合 # 如果您的登录态是通过vuex管理的话,那么一般是首页获取到登录信息,然后存储到vuex中,然后其他路由直接使用即可。但是这样存在的问题,就是刷新页面后,vuex的数据就会消失。这里我们需要借助router中的一个方法。在router中有一个beforeEach方法,这个方法在路由发生变化时就会触发,当然,在当前路由刷新时也会触发,那么就可以在这里监听登录状态的变化。首先是在router/index.js中明确哪些路由是需要登录后才能访问的,哪些是可以直接访问的,下面的代码中可以看到我的奖励页面是需要登录才能访问的,而且奖励中有可能会存在第三方的跳转链接:// router/index.js Vue.use(Router); export default new Router({ routes: [ { path: '/', // shouye name: 'home', components: { Home } }, { path: '/myprize', // 我的奖励 name: 'myprize', components: { MyPrize }, meta: { requiresAuth: true } } ] }) 那么我们在router/auth.js这样判断:// router/auth.js import router from './index.js'; // 获取到路由列表 import store from '../store'; // 获取vuex中的store router.beforeEach((to, from, next)=>{ if(to.meta.requiresAuth){ // 若当前页面需要登录 if(store.state.user.nickname){ // 若vuex中存在用户的昵称,则说明当前有登录态 next(); } else { // 通过检测接口检验用户的登录态, // 然后将获取到的信息再次存储到vuex中 User.getUserInfo(result=> { if(result.nickname){ store.commit('setUserInfo', result); next(); } else { // 去登录 } }) } } else { next(); } }) 若vuex中不存在用户的数据,则说明当前页面肯定是刷新后的,或者从别的页面回退回来导致刷新的。那只能从接口中判断登录态了,若检测到存在登录态,则将用户信息重新存储到vuex中,方便下次的使用;若接口里依然没有登录态,则说明用户真的没有登录,只能让用户去登录了。 2. sessionStorage # 我看有的同学说可以用seesionStorage存储登录信息,不过既然已经使用sessionStorage来存储信息后,感觉也就没必要再通过vuex转换一遍了,不过两者结合起来倒是也可以。而且现在sessionStorage在移动端的兼容性也非常好,基本不用考虑是否可以用的问题。// store import Vuex from 'vuex'; Vue.use(Vuex); const store = new Vuex.Store({ state: { user: JSON.parse( sessionStorage.getItem('user') || '{}' ) } actions: { setUserInfo(state, userinfo){ state.user = Object.assign({}, state.user, userinfo); if(userinfo.nickname){ sessesionStorage.setItem('user', JSON.stringify(user)); } } } }) 这里也只是个简单的样例代码,具体中可以要判断的东西也会更多。 3. 总结 # 在客户端内放置的单页面应用,虽然能让用户操作的比PC上更少,但刷新页面和跳转到第三方链接的情况,还是存在的,因此这个登录问题还是要解决的。目前我正在使用的就是第一种方案,不过我的项目是在客户端里的,可以通过客户端暴露的jsapi来检测登录态。
2024年10月21日
14 阅读
0 评论
0 点赞
2024-10-21
js:如何截取含有表情的字符串
在以QQ和微信作为第三方登录的系统中,用户的昵称里经常会有表情等字符,比如这样的:非拉🍒非拉。如果项目中正好有个需要将用户昵称强行按照字符个数进行截断的需求,你会发现截取的字符串中会有乱码的现象。以上面的用户昵称 非拉🍒非拉 为例,我们算下这个字符串的长度。因html编码的原因,在以下字符串和代码中,无法正常的显示出樱桃的图像,全部使用Y进行代替,测试时,请将Y替换为具体的樱桃符号let nickname = '非拉Y非拉'; nickname.length; // 6 说明中间的表情字符占了2个字符的长度,如果单独输出nickname[2]或者nickname[3]时,均会输出乱码字符。 JavaScript 内部,字符以 UTF-16 的格式储存,每个字符固定为2个字节。对于那些需要4个字节储存的字符,JavaScript 会认为它们是两个字符。 如果针对所有的昵称都要截取前3个字符时,该怎么截取呢?如果是中文、英文、数字、标点符号等常见字符,那么直接从3开始截取就行了,如果上面的那种有特殊符号的怎么办呢? 1. Array.from方法 # Array.from这个方法能够将类数组转换为真实的数组,比如NodeList, argument等,同样,也包括字符串。Array.from(nickname); // ["非", "拉", "Y", "非", "拉"] nickname.split(''); // ["非", "拉", "?", "?", "非", "拉"] 使用Array.from把nickname转换后,可以看到转换成一个真实的数组了,樱桃字符占了数组中的一个位置,然后按照数组中的方法截取再进行拼接即可,而使用split方法拆分,则还是乱码:function truncated(str, num){ return Array.from(str).slice(0, num).join(''); } truncated(nickname, 3); // 非拉Y 2. codePointAt()方法 # 在ES6之前, JS 的字符串以 16 位字符编码(UTF-16)为基础。每个 16 位序列(相当于2个字节)是一个编码单元(code unit),可简称为码元,用于表示一个字符。字符串所有的属性与方法(如length属性与charAt() 方法等)都是基于16位序列。 比如length方法、nickname[2]、split方法等操作,都会产生异常。为此在ES6中,加强了对 Unicode 的支持,并且扩展了字符串对象。对于 Unicode 码点大于0xFFFF的字符,是使用4个字节进行存储。ES6 提供了codePointAt方法,能够正确处理 4 个字节储存的字符,返回一个字符的码点。// 获取樱桃的码点 "Y".codePointAt(0).toString(16); // 1f352 // 输出码点对应的字符 "\u{1f352}"; // Y 请注意: 在之前Unicode编码,均在[\u000-\uFFFF]之间,因此可以使用类似\u0047这样的编码;但是现在码点超过\uFFFF的界限,若再这样使用,则获取不到对应的字符。因此在ES6中,码点的字符放在中括号内,类似上面的格式(所有的码点均可以使用这种格式):"\u{1f352}"; // Y "\u{47}" // G "\u{0047}" // G 那么就容易了:判断需要截取的位置是否正好是4字节的字符,如果是则延长一位截取,否则正常截取:function truncated(str, num){ let index = Array.from(str)[num-1].codePointAt(0)>0xFFFF ? num+1 : num; return str.slice(0, index); } truncated(nickname, 3); // 非拉Y 3. for-of # for-in方法是遍历key值,for-of是遍历value值:let arr = ['a', 'b', 'c']; for(let k in arr){ console.log(k); // 0 1 2 } for(let v of arr){ console.log(v); // a b c } for(let v of nickname){ console.log(v); // 非 拉 Y 非 拉 } 因此利用这个功能,我们也能进行截取:function truncated(str, num){ let s = ''; for(let v of nickname){ s += v; num--; if(num
2024年10月21日
14 阅读
0 评论
0 点赞
2024-10-21
Vue单页面中进行业务数据的上报
为什么要在标题里加上一个业务数据的上报呢,因为在咱们前端项目中,可上报的数据维度太多,比如还有性能数据、页面错误数据、console捕获等。这里我们只讲解业务数据的埋点。业务数据的上报主要分为: 各个路由的PV上报; 用户的点击行为上报; 用户操作结果(分享是否成功)的数据上报等; 通用和必须上报的数据,均在上报的代码中进行固定,比如设备信息、用户信息、cookie等都需要上报的数据,在上报前处理完成,需要异步获取且数据固定的,做好存储,防止每次都要重新获取;其他额外的数据,通过对外暴露的send方法进行传递。比如获取信息这块,客户端给到的jsapi,有可能只能异步调用,那么我们就可以这么处理:function getAppInfo() { let appInfo = {}; return ()=> { if (appInfo.deviceId) { return Promise.resolve(appInfo); } else { return new Promise((resolve, reject) => { ABB.getAppInfo(info => { if (info.deviceId) { appInfo = info; resolve(appInfo); } else { reject(new Error('get AppInfo error')); } }) }) } } } const AppInfo = getAppInfo(); console.log( AppInfo() ); 1. 各个路由的PV上报 # 各个路由的PV上报可以通过vue router的afterEach来实现,每次路由刷新时,afterEach方法都会执行,那么我们在这里进行PV的上报:// 每个hash路由的PV上报 router.afterEach((to)=>{ // to为当前已打开的页面,to.name为在router/index.ts中设定的name dataBoss.sendPV(to.name); }) 2. 用户点击行为的上报 # 用户点击行为的上报,之前是在每个点击的业务代码最后,进行一次点击上报。不过这样一个不好的地方是,必须为每个需要上报的点击元素添加一段业务代码,同时,如果多个点击行为共享某个业务片段时,需要进行点击区分:methods: { myClick(value, prarams, act) { // ... 业务逻辑的处理 // 数据的上报 wzp.send({ act: act, pageSource: 'MainPage' }) } } 现在,我们利用Vue中的自定义指令来实现点击行为的上报,上报的处理与业务代码进行分割:// 自定义指令的官方文档: https://cn.vuejs.org/v2/guide/custom-directive.html // 自定义boss指令 // bind: 只对该元素绑定一次 // el: 触发时的DOM元素 // binding.value: 传入的值 // 使用 v-boss="{page: 'MainPage', sop: 'donate'}" Vue.directive('boss', { // bind: function (el: HTMLElement, binding: any) { el.addEventListener('click', ()=>{ // 绑定click事件,触发后进行数据上报 Vue.prototype.$dataBoss.send(binding.value) }) } }) 自定义v-boss指令后,我们就可以在元素上使用这个指令后: 3. 用户操作结果的数据上报 # 这里的数据上报是用户点击行为之后的结果上报,比如用户点击了分享按钮,那么最终他是真的分享成功了,还是中途又取消了。这种数据的上报,可以分析出用户从意图操作到最终实现的一个流失情况。操作结果的数据上报,依赖于客户端或者接口给反馈的结果,这就需要在业务代码中实现了,定义一个全局变量$dataBoss,通过这个来上报数据:比如分享是否成功的监控:// 发起分享 handleShare() { share.show(); share.on('shareResult', res => { this.$dataBoss.send({ sop: 'share_success' }); }) } 根据接口中的数据进行上报:handleUser() { jsonp(url).then(result => { this.$dataBoss.send({ kv: { money: 20 } }); }) } 总结 # 前端数据上报的维度很多,都是为了方便我们更加的了解用户、了解产品,方便以后的功能迭代。
2024年10月21日
6 阅读
0 评论
0 点赞
2024-10-21
基于webview的前端页面优化指南
导航 # 页面性能规范 分享规范 页面要求 交互规范 容灾规范 其他异常处理 技术规范 测试标准 我们的业务主要是在移动端中使用和推广的,在移动端中,网络环境和内存都有不确定性,网络环境好的终端,不一定有好的内存;同样,有好内存的终端,也不一定都实时处在良好的网络环境下。因此,我们在针对移动端中应该有哪些优化呢? 1. 页面性能规范 # 从loading到呈现页面元素的时间,wifi下
2024年10月21日
7 阅读
0 评论
0 点赞
1
...
58
59
60
...
241