首页
Search
1
解决visual studio code (vscode)安装时没有选择安装路径问题
138 阅读
2
Linux 下 Bash 脚本 bad interpreter 报错的解决方法
131 阅读
3
Arch Linux 下解决 KDE Plasma Discover 的 Unable to load applications 错误
107 阅读
4
如何在 Clash for Windows 上配置服务
77 阅读
5
Uniapp如何引入自定义样式文件
75 阅读
clash
服务器
javascript
全部
游戏资讯
登录
Search
加速器之家
累计撰写
1,061
篇文章
累计收到
0
条评论
首页
栏目
clash
服务器
javascript
全部
游戏资讯
页面
搜索到
624
篇与
的结果
2024-10-21
实现了几个基于腾讯新闻客户端的h5前端基础组件
在平时工作中做了不少基于新闻客户端的需求,在这些工作中,对其进行汇总提取,形成了这些npm基础组件。有什么不足的地方也希望大家能多多提意见。 tencent-downapp 在微信、QQ、浏览器等中打开或者下载指定APP tencent-share 设置h5在微信、QQ、腾讯新闻客户端、腾讯视频的分享信息(标题、描述、图片和链接); tencent-update 可用户上报一些前端用户数据; tencent-qqnews-user 在腾讯新闻客户端中进行登录、获取用户信息和提交请求等操作 tencent-downapp # npm install tencent-downapp --save-dev 该模块主要用于在外部呼起app时使用,配置好参数后,执行run()方法即可执行打开或者下载操作:import AppDownload from 'tencent-downapp'; var downapp = new AppDownload({ openUrl: 'qqnews://article_9527?nm=RSS2018061501588400', packageName: 'com.tencent.news', downloadUrl: 'http://dldir1.qq.com/dlomg/inews/channel/TencentNews_3932.apk', wxhash: '1cbd02bbed81c8a5b990044e9f844eda', // 微信中下载完成时是需要进行hash校验的,并且每次发版,hash值都会变动 appleStoreId: '399363156', appName: '腾讯新闻--百万现金红包派发中...', downLogo: 'http://mat1.gtimg.com/news/news/logo.png' }); // 获取APP的安装状态 downapp.checkAppIsInstalled(function(status){ if( status ){ alert( '已安装' ); }else{ alert( '未安装' ); } }); document.querySelector('.btn').addEventListener('click', function(){ downapp.run(true); // 无视wifi }) 更详细介绍,请查看: https://www.npmjs.com/package/tencent-downapp; tencent-share # 该模块集成了微信、QQ、腾讯新闻客户端、腾讯视频客户端的分享API,可以设置分享的标题、描述、图片和链接。npm地址: https://www.npmjs.com/package/tencent-share;npm install tencent-share --save-dev 使用方式:import Share from 'tencent-share'; // 分享信息 var shareData = { title: '读腾讯新闻,助力公益事业,让你的时间更有意义', desc: '上腾讯新闻,捐阅读时长做公益,一起为爱聚力', img: 'http://mat1.gtimg.com/news/qqnews/qqspring/img/logo.png', link: window.location.href }; Share.setShareInfo(shareData); Share.setShareInWx(shareData, 'friends'); setShareInfo为总方法,调用该方法后,开发者无需关心当前处于什么环境,模块会自动根据UA设置微信、QQ、腾讯新闻客户端、腾讯视频客户端的分享信息。如果想在不同的环境里设置的信息,下面的这几个方法可以调用: setShareInWx(shareData, type) : 设置页面在微信中的分享信息,type字段稍后讲解; setShareInQQ(shareData) : 设置页面在QQ中的分享信息; setShareInNews(shareData) : 设置页面在新闻客户端中的分享信息; setShareInVideo(shareData) : 设置页面在腾讯视频中的分享信息; 在设置页面在微信中的分享信息的方法里,有个type字段,这个type字段能设置在微信中分别分享给好友、朋友圈、QQ和QQ空间的信息。setShareInWx(shareData, 'friends')表示分享给好友时的分享信息,type字段有: friends : 分享给好友 timeline : 分享到朋友圈 qq : 分享给QQ好友 qzone : 分享到QQ空间 如果没有分别设置分享信息的需求,直接调用Share.setShareInfo(shareData);即可。在新闻客户端内设置分享信息后,还可以调用show()方法来主动呼起分享面板:Share.show(); // 该方法只在新闻客户度内有效 同时,还可以在 Android版的新闻客户端 内,禁止该页面的分享功能:Share.forbidShareInNews(); tencent-updata # 该模块是前端上报数据时使用,封装了几个方法,上传数据时调用即可。npm地址: https://www.npmjs.com/package/tencent-updatanpm install tencent-updata --save-dev 简单的使用样例:import wzPing from 'tencent-updata'; var wzp = new wzPing({ user: 123456, pwd: 123456 }); wzp.ready([ function(callback){ setTimeout(function(){ callback({ now: Date.now() }) }, 400); } ]); wzp.send({act: 'PV'}) 上面的代码基本上展示出所有的功能了。 注意: 在当前模块中,是创建一个img图片,通过请求img图片的链接,来上报PV请求等。请在使用时修改为您自己的上报地址,修改方法在文章的最后有说明。 1. 初始化 # 可以把经常要上报的字段或者数据不需要变动的字段,在初始化时就传入进去。这样在后续上报行为中,都会带上这些字段。代码内部是用data来存储这些数据的,因此初始化完成后,可以用对象直接访问该属性,并对data属性进行修改:console.log( wzp.data ); 2. ready # 在数据上报前,有些字段是需要异步获取的,在上报时需要等待该字段获取到数据后,才能上传,因此,这里设置了一个ready方法,在send()方法前先调用下ready()方法,这样在ready里获取到数据后,自动执行后面的send方法。调用方式,ready方法接收一个数组,数组的每一项都是一个函数,这个函数都需要传入一个回调方法callback,回调方法里传入异步执行完毕获取到的值,这个值需要用json格式的方式:wzp.ready([ fn(callback); ]) 使用样例:wzp.ready([ function(callback){ setTimeout(function(){ callback({ now: Date.now() }) }, 400); } ]); wzp.ready([ function(callback){ setTimeout(function(){ callback({ random: (Math.random()+'').substr(-6); }) }, 600); } ]); wzp.send({act: 'PV'}) 上面的代码中,字段now和random都是异步获取到的,代码里的send会等待这两个字段都获取到后才会执行。 3. send # 调用send()方法后就会发送数据上报请求,同时send还能接受一个json格式的参数,用户当前发送时的额外数据,不同的send上报请求之间互不影响。wzp.send({act: 'PV'}); wzp.send({page: 'main'}); // 当前请求中不存在act字段 4. sendData # 最终的数据上报请求是通过这个方法发送的,我们也可以修改这个sendData方法,来修改数据上报的方式。不过记得在send()发送请求之前进行修改:/** * @param data {key1: value1, key2: value2, key3: value3} 上报的字段与对应的数据 */ wzp.sendData = function(data){ let s = '', item; for(let key in data){ item = data[key]; if( typeof item==='object' ){ // 若上传的数据为array或者json格式的,则转换为字符串 item = JSON.stringify(item); } s += '&' + key + '=' + encodeURIComponent( data[key] ); } let img = new Image(1, 1); img.src = 'xxxx.com/updata?v=1'+s+'&_t='+Math.random(); } tencent-qqnews-user # 因新闻客户端存在iOS与Android的系统差异,导致调用客户端提供的jsapi非常不方便,这里就进行了下封装,直接调用即可。用于在腾讯新闻客户端中进行登录、获取用户信息和提交请求等操作。npm地址: https://www.npmjs.com/package/tencent-qqnews-usernpm install tencent-qqnews-user 然后在代码中引用即可:import User from 'tencent-qqnews-user'; 接下来是几个方法的使用方式。 1. 登录 # 登录的方法是login(string logintype, function callback),这里接收两个参数。第1个参数登录的方式有: qq :只有QQ登录按钮 ; weixin : 只有微信登录按钮; qqorweixin; QQ和微信按钮都有,用户可以任意选择 第2个参数是登录后的回调, true表示登录成功; false表示登录失败,比如中断登录等。样例:User.login('qqorweixin', result=>{ if(result){ alert('登录成功'); }else{ console.log( '取消登录' ); } }); 注意: 在iOS的新闻客户端中,不论用户是否已经登录,都可以使用User.login再次呼起登录;在Android的新闻客户端中,若呼起的登录方式与当前的登录态相同,则直接回调为false,不会弹出登录窗口,比如当前为QQ登录,那么再次使用qq或者qqorweixin呼起登录时,都会直接回调为false。 同时,在这两个系统的新闻客户端内,若再次呼起登录的方式,与当前的登录状态不一样,则后登录的账户会作为副账户存在,不会顶掉当前主账户的信息。 2. 退出登录 # 退出登录的方法是: User.logout(),没有参数User.logout(); // 退出登录 在iOS里则会直接退出账户,而在Android的客户端里,则会弹窗让用户确认是否退出。 3. 切换账号 # 在上面我们已经说过User.login会存在两个问题: Android下若呼起的登录方式与当前的登录态相同,则无法重新登录; iOS和Android下,若呼起的登录方式与当前的登录态不同是,则后登录的账号作为副账户存在 为了解决这两个问题,客户端还提供了切换账号的功能,其实就是: 退出当前账号(logout)+重新登录(login)。若我们使用上面两个方式的组合来让用户重新登录,iOS下没问题,但在Android下,退出账号时会首先弹窗确认,而这个弹窗确认是不会阻止后面的login进程的,login就会进入到自己的判断流程,导致login失败。这里我们使用User.changeLogin(string logintype, function callback)来切换账号,切换账号的方法是客户端提供的,虽然流程还是 退出当前账号(logout)+重新登录(login),但能正常切换。传递的参数与login相同:第1个参数登录的方式有: qq :只有QQ登录按钮 ; weixin : 只有微信登录按钮; qqorweixin; QQ和微信按钮都有,用户可以任意选择 第2个参数是登录后的回调, true表示登录成功; false表示登录失败,比如中断登录等。User.changeLogin('qq', result=>{ if( result ){ alert( '切换账号成功' ); }else{ console.log( '中断切换' ); } }); 4. 获取用户信息 # 如果想要展示用户的昵称、头像等信息,可以用User.getUserInfo接口来获取,回调的字段里包含了当前用户的登录方式、昵称、头像和openid(QQ方式登录时为其qq号):/* result = { logintype: 'qq', // 'weixin',当前的登录方式;若为空,则表示未登录;以下字段均在登录后才存在 nickname: '', // 昵称 avatar: '', // 头像 openid: '' // 微信账号的openid或者QQ账号的qq号,均以openid字段返回 }; */ User.getUserInfo(result=>{ alert( JSON.stringify(result) ); }) 5. 请求接口 # 客户端里也有提供请求接口的方法,不用额外引入ajax等模块:User.post({ url: url, // 请求地址,必传,必须明确协议 data: {a:1, b:2}, // 参数,可以为空 success: function(result){ // 请求成功时 }, error: function(error, url){ // 请求失败时 }, complete: function(error, url, result){ // 成功或失败都会执行的方法 } }) 这里内部调用的是客户端提供的方法,虽说名字是post,但在实际使用中发现,get请求和post请求都会接收到。这个方法通过客户端发起调用接口时,会自动带上客户端的信息和用户的信息(如果他已登录的话)。因此后端在接收到前端通过这种方式发送过来的请求时,可以拿到相应的设备信息和用户信息,前端无需显式的带上当前设备和当前用户的信息。这里有几个要注意的点: 请求的url必须明确是http://还是https://协议,不能自动适应页面协议;不过您可以用location.prototal来获取当前页面的协议,拼接到URL上,然后再通过post进行请求; complete方法是无论请求成功还是失败都会执行,第1个参数在请求success时为null,在请求error时有数据 同时,这里还是提供两个额外的方法,记得在post之前定义:User.postSuccess(url, result): 所有通过post请求成功的都会执行这个方法,那么可以通过这个方法来进行接口数据上报的操作;User.postError(error, url): 所有通过post请求失败的都会执行这个方法
2024年10月21日
8 阅读
0 评论
0 点赞
2024-10-21
Vue中的嵌套组件中数据无法实时更新的问题
我们在工作经常会有组件嵌套的情况,内部组件通过props获取传递进来的数据。不过在实际应用中发现,外部组件的数据更新后,内部组件的数据不会实时更新:子组件: 姓名: {{user.name}} 年龄: {{user.age}} export default { props: { user: Object } } 父级组件: import unit from './unit'; export default { components: { unit }, data(){ return { users: [ { name: 'wenzi', age: 27 }, { name: '蚊子', age: 26 } ] }; } } 这么个组件运行是没有问题的,能够正确渲染出一个列表。可是如果list.vue中的users发生变化时,unit.vue里的数据是不会再次更新的。这样的情况怎么解决呢? 解决方案1: 将两个组件合并成一个组件 # 最简单、最粗糙的方式,将两个组件合并成一个组件,在一个组件内进行数据更新,就不会出现组件之间数据不同步的问题了。不过这样的的问题就是,当前组件会很大,本来我们就是为了解耦功能,才要拆分组件的,不能再次回到过去吧。 解决方案2: watch # 在unit.vue组件中,使用watch监听某个属性的变化,这样外部的数据发生变化时,watch就能监听到:watch: { 'user.age': function(val, oldVal){ this.render(); // user中的age属性发生变化时,调用render方法 } }
2024年10月21日
5 阅读
0 评论
0 点赞
2024-10-21
单页面切换路由时的倒计时和Vue倒计时组件
我的项目是用Vue写的单页面应用,然后首页上的每个商品都有一个倒计时,计算当前商品距离结束的剩余时间,而且还使用了keep-alive缓存首页中的数据,可是切换到别的路由再切换回首页时,倒计时就出现错乱了: 有多个倒计时交叉进行,出现倒计时混乱。排查后得到的原因是: 在单页面应用中,无论怎么切换hash路由,定时器都是存在的,因此在单页面中切换路由时,应当在组件的deactivated或destroyed中进行销毁;回到这个页面时,再重新启动!分享一个我项目中正在使用的倒计时: vue-countdown。页面中可以多次调用,且相互之前独立倒计时! import iCountdown from '@/ui/i-countdown'; export default { components: { iCountdown }, }
2024年10月21日
9 阅读
0 评论
0 点赞
2024-10-21
在红包活动中如何保障账户的安全
我们经常在做一些福利活动来拉动用户的活跃度,提升APP的拉新和拉活。不过总会有些人在寻找我们活动中的漏洞,以此牟利。那么我们是如何预防这些别有用心的人的恶意攻击呢?这里我们就来聊聊是如何防范的。首先我们复原下我们活动的玩法: 用户A从客户端内分享自己的专属链接到朋友圈,或者分享到其他地方,分享链接里带有当前用户A的标识、头像、昵称等信息,他的好友B访问这个分享链接时,会读取URL中的参数,然后填充到页面中;用户B点击分享页面中的按钮时,也会将分享者A的标识带入到客户端内,则用户A邀请B成功!用户A和用户B均可获得现金奖励,现金可以进行提现。首先我们应该知道前端中的攻击都有哪些方式,然后才能针对项目特点进行防范。 1. XSS攻击 # 百科中这样写道: XSS是一种经常出现在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中。其实在web前端方面,可以简单的理解为一种javascript代码注入。 就是说XSS利用的是用户对指定网站的信任,访问了被注入的恶意代码,造成XSS攻击。在我们整个活动中,用户可能会修改URL参数的地方有2个: 用户A分享出来他的专属分享链接后,在微信、QQ等地方传播时,用户A可以修改他自己的分享链接参数后,再让别人访问; 用户B点击分享链接中的按钮跳转到客户端前,修改URL中的参数,即可修改传递到端内的参数; 在这2种情况里,URL的参数主要有3种: sopenid: 用来让其他用户重新带入到客户端内,分享页里不做处理; nickname: 展示分享者的用户名,这里作为纯文本处理; avatar: 展示分享者的头像,这里对其进行字符串转义; 1.1 节点内容字符串的处理 # nickname是要直接填充到页面中的,如果没有过滤,就直接对其进行html字符填充,就会造成程序的混乱,或者被填充恶意的链接,用户可能会无意中跳转到第三方的链接中。比如恶意者在url中使用了一段这样的代码:http://news.qq.com?nickname=while(1){alert('hello world')} 那么用户打开这个链接时,就会无限弹窗;如果恶意者在url中使用了这样的代码:http://news.qq.com?nickname= 用户可能就会不小心跳转到第三方的页面;因此这里,要么把参数作为纯文本处理,要么对参数里的字符进行转义后再填充:var escapeHtml = function(str) { return str.replace(//g,'>'); } 1.2 节点属性的处理 # 我们也会获取URL参数里的avatar作为用户的头像,若用户使用了这样的代码:http://news.qq.com?avatar=1"%20onerror="alert(%hello world%27) 那么填充到页面后,就会变成这样: chrome会自动防御这种XSS攻击,不过如果在没有自动防御的浏览器上,还是会被弹窗警告,因此这样可以对引号进行转移:var escapeHtmlProperty = function (str) { if(!str) return ''; return str.replace(/"/g,'&quto;').replace(/'/g,''').replace(/ /g,' '); } 2. CSRF攻击 # 跨站请求攻击,简单地说,是攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并运行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去运行。这利用了web中用户身份验证的一个漏洞:简单的身份验证只能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。CSRF攻击,我们前端能做的工作很少,需要后端进行防御工作。 refer限制: 所有非白名单中的refer请求,全部拒绝; token验证: 客户端发起的请求中带有token,接口验证token的合法性,若token不合法,则认为请求是伪造的; 客户端时间的校验: 若客户端的本地时间与北京标准时间相差较多时,拒绝; 当然后端接口还有更多的防御工作,我们这里也是简单的举几个例子。 3. https协议 # 在服务器支持https协议时,我们最好把页面按照https的方式开发,要么显式的使用https://或者使用//来让浏览器自己选择。https协议提供了三个强大的功能来对抗上述的劫持行为: 内容加密。浏览器到腾讯服务器的内容都是以加密形式传输,中间者无法直接查看原始内容。 身份认证。保证用户访问的是腾讯服务,即使被 DNS 劫持到了第三方站点,也会提醒用户没有访问百度服务,有可能被劫持 数据完整性。防止内容被第三方冒充或者篡改。 不过在使用https的过程中,踩了个坑。我在页面中把接口的链接都写成//这种隐式的协议,可是在使用客户端的方法请求接口时发现,客户端的方法不会自动根据页面的协议补全请求接口的协议,需要开发者手动补全协议:// 通过 window.location.protocol 获取当前页面的协议 let url = window.location.protocol + '//api.qq.com'; 3. 验证码 # 验证码的作用不必多说,就是为了区分人/机,确定接下来的行为确实是真实用户发起的,而不是机器模拟产生的。为了防止提现接口被恶意爆刷,我们在用户在提现前,也添加了验证码的功能,验证用户的合法性,确定请求确实是用户主动发起的提现行为。 4. 账户验证 # 在客户端中的登录过程,是拉起微信登录或QQ登录,然后登录微信账号或QQ账号,用户全部的操作都需要验证微信账号和QQ账号的合法性和危险登录,若判定当前账号是危险账号,则阻止其进一步的操作。 5. 客户端的验证 # 客户端的验证,是为了保证请求一定是从客户端发起的,而不是从外部某个地方发起的请求。这块在第2部分里也有说明,就是token的验证,客户端发起的任何请求都是带有token的,然后接口验证token的合法性!写的这么多措施和方法,大部分也是常见的攻击和防御,但是我们依然不能掉以轻心,稍微有点疏忽,就会给用户和我们活动方造成不可挽回 的损失。
2024年10月21日
4 阅读
0 评论
0 点赞
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日
8 阅读
0 评论
0 点赞
1
...
29
30
31
...
125