- 前端XSS攻击
一、前言 随着互联网的高速发展,信息安全问题已经成为企业最为关注的焦点之一,而前端又是引发企业安全问题的高危据点。在移动互联网时代,前端人员除了传统的 XSS、CSRF 等安全问题之外,又时常遭遇网络劫持、非法调用 Hybrid API 等新型安全问题。当然,浏览器自身也在不断在进化和发展,不断引入 CSP、Same-Site Cookies 等新技术来增强安全性,但是仍存在很多潜在的威胁,这需要前端技术人员不断进行“查漏补缺”。 二、XSS定义 在给大家介绍xss前,大家先来看一个例子: [代码]<html> <title>Welcome!</title> Hi <script> var pos=document.URL.indexOf("name=")+5; document.write(document.URL.substring(pos,document.URL.length)); </script> Welcome to you </html> [代码] 这个例子是个欢迎页面,name是截取URL中get过来的name参数 正常操作: http://域名A/welcome.html?name=Joe 非正常操作: http://域名A/welcome.html?name=<script>alert(document.cookie)</script> 当执行非正常操作时: [图片] 完了,我们的cookie数据被截取了,XSS攻击出现了。 为什么会这样呢?我们来看一下: 1、受害者的浏览器接收到这个非正常操作的链接,发送HTTP请求到域名A并且接受到上面的HTML页; 2、受害者的浏览器开始解析这个HTML为DOM,DOM包含一个对象叫document,document里面有个URL属性,这个属性里填充着当前页面的URL; 3、当解析器到达javascript代码,它会执行它并且修改你的HTML页面。倘若代码中引用了document.URL,那么,这部分字符串将会在解析时嵌入到HTML中,然后立即解析,同时,javascript代码会找到(alert(…))并且在同一个页面执行它,这就产生了xss。 那么什么是XSS呢? xss跨站脚本攻击(Cross Site Scripting),指攻击者在网页中嵌入脚本代码(例如js代码), 当用户浏览此网页时,脚本就会在用户的浏览器上执行,从而达到攻击者的目的。比如获取用户的Cookie,导航到恶意网站,携带木马等。 大部分的xss漏洞都是由于没有处理好用户的输入,导致攻击脚本在浏览器中执行,这就是跨站脚本漏洞的根源。 三、XSS攻击类型 XSS攻击分为存储型、反射型和 DOM 型三种。 1、存储型 XSS a: 攻击者将恶意代码提交到目标网站的数据库中。 b: 用户打开目标网站时,网站服务端将恶意代码从数据库取出,拼接在 HTML 中返给浏览器。 c: 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。 d: 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。 简单例子: 表单中填写数据: [代码]<input type=“text” name=“content” value=“这里是用户填写的数据”> [代码] 正常操作: 1、用户是提交相应留言信息; 2、将数据存储到数据库; 3、其他模块要显示保存的数据,从数据库查询出来并显示。 非正常操作: 1、攻击者在value填写<script>alert(‘foolish!’)</script>【或者html其他标签(破坏样式。。。)、一段攻击型代码】; 2、将数据存储到数据库中; 3、其他用户取出数据显示的时候,将会执行这些攻击性代码 这种攻击常见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等。 2、反射型 XSS a: 攻击者构造出特殊的 URL,其中包含恶意代码。 b: 用户打开带有恶意代码的 URL 时,网站服务端将恶意代码从 URL 中取出,拼接在 HTML 中返回给浏览器。 c: 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。 d: 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。 简单例子: 正常发送消息: http://域名A/message.html?message=Hello,World! 接收者将会接收信息并显示Hello,Word 非正常发送消息: http://域名A/message.html?message=<script>alert(document.cookie)</script> 接收者接收消息显示的时候将会弹出警cookie信息 反射型 XSS 跟存储型 XSS 的区别是:存储型 XSS 的恶意代码存在数据库里,反射型 XSS 的恶意代码存在 URL 里。 反射型 XSS 漏洞常见于通过 URL 传递参数的功能,如网站搜索、跳转等。由于需要用户主动打开恶意的 URL 才能生效,攻击者往往会结合多种手段诱导用户点击。POST 的内容也可以触发反射型 XSS,只不过其触发条件比较苛刻(需要构造表单提交页面,并引导用户点击),所以非常少见。 3、DOM 型 XSS a: 攻击者构造出特殊的 URL,其中包含恶意代码。 b: 用户打开带有恶意代码的 URL。 c: 用户浏览器接收到响应后解析执行,前端 JavaScript 取出 URL 中的恶意代码并执行。 d: 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网 站接口执行攻击者指定的操作。 简单例子: [代码]<script> document.body.innerHTML="<div style=visibility:visible;><h1>This is DOM XSS</h1></div>"; </script> [代码] 攻击者可以利用innerHTML来篡改页面 DOM 型 XSS 跟前两种 XSS 的区别:DOM 型 XSS 攻击中,取出和执行恶意代码由浏览器端完成,属于前端 JavaScript 自身的安全漏洞,而其他两种 XSS 都属于服务端的安全漏洞。 四、如何预防XSS攻击 1、输入过滤,对用户提交的数据进行有效性验证,仅接受指定长度范围内并符合我们期望格式的的内容提交,阻止或者忽略除此外的其他任何数据。比如:电话号码必须是数字和中划线组成,而且要设定长度上限。过滤一些些常见的敏感字符,例如:< > ‘ “ & # \ javascript expression “onclick=” “onfocus”;过滤或移除特殊的Html标签, 例如: <script>, <iframe> , < for <, > for >, " for;过滤JavaScript 事件的标签,例如 “onclick=”, “onfocus” 等等。 例子1: [代码]<input v-model="value" type="text" /> [代码] Input输入值带有html标签时,如value=”<b>aaaaaaaa</b>”,调接口提交到后台的没有做HtmlEncode转码,那么面页输出的将会是: aaaaaaaa粗体。原理是因为提交的内容里带有html标签<b></b>。浏览器解析页面源码时把用户提交的内容当成了html代码。所以才会输出粗体的 aaaaaaaa。 解决方案: A:前端提交前转码:encodeHtml(value); B:后端java转码:Encoder.encodeHtml(value);如果是Param类,直接使用.getHtmlString(key)。 例子2: 提交的数据url编码,数据提交时一定要对传参数的数进行URLencode处理,假如提交内容 aaaa&344353中文啊&&&&aaa=bbbb&&&fsdfsdsdf,如果没有通过 URLencode处理的话,那么提交的链接自然是http://www.baidu.com/?val=aaaa&344353中文啊&&&&aaa=bbbb&&&fsdfsdsdf 这样后台取得的val的值会是aaaa。并且还会有一个aaa=bbbb。主要造成这现象的原因是提交的内容包含了"&“和”=",没有对这些特殊的字符做转义处理,所以造成了后台取参错误。 解决方案: A:前端提交参数前:encodeUrl(url); B:后端拿到数据进行编码:Encoder.encodeURL(url); 其他例子解决方案: A:对输入的数据限制长度范围; [代码]<input v-model="value" maxlength="20" type="text" /> [代码] B:对输入的数据进行校验(正则表达式) [代码]var re = /^[a-zA-z]\w{3,15}$/; If(re.test(value)){ return true; }else{ return false; } [代码] 2、输出编码,当需要将一个字符串输出到Web网页时,同时又不确定这个字符串中是否包括XSS特殊字符(如< > &‘”等),为了确保输出内容的完整性和正确性,可以使用编码(HTMLEncode)进行处理。 例子1: 输出js数据时,要先编码,否则有可能因为"等造成截断。如var a = ‘<%=aString %>’;假如aString的值是"aa’;alert();’"。没有encodeJs的页面就会执行alert了。而有encodeJs的页面则会把输出内容里的单引号都替换成:\x22,双引号替换成\x27。这样就不会造成js里的引号截断了。 解决方案: A:前端JS函数:$.toJSON(html); B:后端java函数:Encoder.encodeJson(html);如果是Param类,直接使用.getJsonString(key)。 例子2: <a href=”url”>跳转链接</a> java处理代码时获取url参数并且不做任何处理,直接在html标签的事件中植入攻击代码。 当用户访问的链接是xxx/sigup.jsp?url=");alert(document.cookie)😭"; 点击跳转链接按钮的时候,就会弹出cookie的信息 解决方案: A:前端把href换成onclick方法: Html: [代码]<a onclick=”openUrl(url)”>跳转链接</a> [代码] Js: [代码]Function openUrl(url) { url = encodeUrl(url); Window.location.href = url; } [代码] B:后台调用方法: Encoder.encodeURL(value2); 如果是Param类,直接使用.getUrlString(key)。 其他案例: A:把字符串转换为写在html标签中属性值: 字符串是输出在html标签中的属性里,所以首先要防止字符串里的引号造成属性的引号截断。所以至少字符串里的引号就要转义了。当然,还有额外的一些特殊字符也是要转义的。 解决方案: js函数:encodeHtmlAttr(html); java函数 :Encoder.encodeHtmlAttr(html);如果是Param类,直接使用getHtmlAttrString; 如果是输出在js里初始化的话,尽量使用jquery的attr/val等函数来赋值( encode json 数据 ),降低复杂度。 B: input-text用例 :<s>a&aa</s>'b"c 在页面中直接初始化时,要使用:<input value="<%=Encoder.encodeHtml(str)%>"/> 在JS中初始化时,要使用:$("#xxx").val("<%=Encoder.encode.Json(str)%>"); C: textarea用例 : <textarea><s>a&aa</s>'b"c</textarea>bbb,不在页面中直接初始化textarea。 在JS中初始化:$("#xxx").val("<%=Encoder.encodeJson(str)%>") 3、DOM型的XSS攻击防御,把变量输出到页面时要做好相关的编码转义工作,如要输出到 <script>中,可以进行JS编码;要输出到HTML内容或属性,则进行HTML编码处理。根据不同的语境采用不同的编码处理方式。 例子: 当用户访问路径为xxx/pr.jsp?keywordCond=aaa");alert(document.cookie)😭"时候,直接scripts.append输出:scripts.append(keywordCond),就会弹出cookie的信息。 解决方案: A:在append前,将keywordCond进行编码 [代码]keywordCond = encodeUrlComponent(keywordCond); scripts.append(keywordCond) [代码] B:后台调用方法: [代码]String keywordCond = Encoder.encodeHtmlJs(keywordCond); [代码] 1、将重要的cookie标记为http only, 这样的话当浏览器向Web服务器发起请求的时就会带上cookie字段,但是在脚本中却不能访问这个cookie,这样就避免了XSS攻击利用JavaScript的document.cookie获取cookie。 例子: A:Tomcat服务器,在Tomcat下的conf的web.xml设置如下信息。 [代码]<session-config> <cookie-config> <http-only>true</http-only> </cookie-config> <session-config> [代码] B:resin服务器,在resin.conf下设置session信息。 [代码]<session-config> <enable-cookies>true</enable-cookies> <cookie-config> <http-only>true</http-only> </cookie-config> </session-config> [代码] 五、总结 XSS的攻击五花八门,毕竟那么多情况场景,开发人员无法一一照顾过来,我们前端和后端尽可能对提交数据做好过滤。开发人员要注意在正确的地方使用正确的编码方式,有时为了防御XSS,在一个地方我们需要联合HTMLEncode、JavaScriptEncode、URLEncode进行编码,甚至是叠加,并不是固定一种方式编码,具体情况具体分析。 针对XSS攻击类型,我们日常开发需要做好以下部分: 1.在HTML标签、属性中输出时,用HTMLEncode。 2.在script标签中输出时,用JavaScriptEncode。 3.在地址中输出一般如果变量是整个URL,则用URLEncode。 4.在提交数据前,做一些正则校验,或者在输入框中做一些限制。 六、参考资料 1、http://it.faisco.cn/page/forum/articleDetail.jsp?articleId=1656 2、http://web.jobbole.com/95312
2019-06-10 - 微盟小程序性能优化实践
微盟小程序性能优化要分享的内容分为三部分,启动性能加载、首屏加载的体验建议和渲染性能优化。 先讲启动性能加载的性能优化实践,先看启动加载过程的流程: [图片] · 公共库注入 · 资源准备(基础UI创建,代码包下载) · 业务代码注入和渲染 · 渲染首屏 · 异步请求 优化方案 1、控制代码包大小 · 开启开发者工具中的 “ 上传代码时自动压缩 ” · 及时清理无用代码和资源文件 · 减少代码包中的图片等资源文件的大小和数量 · 将图片等资源文件放到CND中 · 提取公共样式 · 代码压缩,图片格式,压缩,或者外联 · 公共组件提取,代码复用 2、 分包加载 分包加载过程流程 [图片] 在开发小程序分包项目时,会有一个或者多个分包,其中没有分包小程序必须包含一个主包,即放置启动页面或者tabBar页面,以及一些分包都需要用到的公共资源脚本。 在小程序启动时,默认会下载主包并且启动主包内页面,如果用户打开分包内的页面,客户端会把分包下载下来,下载完之后再进行展示。 · 分包加载流程 [图片] 使用分包加载的优点: · 能够增加小程序更大的代码体积,开发更多的功能 · 对于用户,可以更快地打开小程序,同时不影响启动速度 使用分包加载有哪些限制: · 整个小程序所有分包不能超过8M · 单个主包/分包不能超过2M 3、 运行机制优化 · 代码中减少立即执行的代码数量 · 避免高开销和长时间阻塞代码 · 业务代码都写入页面的生命周期中 · 做好缓存策略 4、 数据管理优化 · 首屏请求数量尽量不能超过5个,超过的可以做接口合并(node层,服务端都可以处理) · 对多次提交的数据可以做合并处理 接下来和大家聊一聊首屏加载的体验建议和渲染性能优化。 二、首屏加载的体验建议 · 提前请求 异步数据请求不需要等待页面渲染完成。 · 利用缓存 利用storage API对异步请求数据进行缓存,二次渲染页面,再进行后台更新。 · 避免白屏 先展示页面骨架和基础内容。 三、渲染性能优化 · 每次 setData 的调用都是一次进程间通信过程,通信开销与 setData 的数据量正相关 · setData 会引发视图层页面内容的更新,这一耗时操作一定时间中会阻塞用户交互 · setData 是小程序开发使用最频繁,也是最容易引发性能问题的 · 在页面列表中使用懒加载+动态移除非可视区域范围内的内容,让dom小下去 · 耗时比较长的js做到异步,不要阻塞进程(js属于单线程) · 少使用scroll-view,这个组件对性能的影响太大,单纯的只是需要一块区域滚动,可以使用view+css的方式实现 · 在页面频繁滚动触发回调函数,会导致页面卡顿,这时必须和防抖动函数或者节流函数相结合做一些处理 · 页面中的图片可以使用懒加载的方式(添加lazy-load属性,只针对page与scroll-view下的image有效) · 页面跳转要做一下限制,如果页面快速点击会出现跳转多次的情况 避免不正当的使用setData · 使用data在方法间共享数据,可能增加setData传输的数据量。data 应该仅仅包含与页面渲染相关的数据 · 使用setData 传输大量的数据,通讯耗时与数据量成正比,导致页面更新延迟 可能造成页面更新开销增加。所以setData 仅传输页面需要的数据,使用setData 的特殊Key 实现局部更新 · 短时间内频繁调用setData (操作卡顿、交互延迟 阻塞通信、页面渲染延迟),对连续的setData 调用进行合并 · 后台进行页面setData (抢占前台页面的渲染资源) 例如 活动定时器 再页面切入后台时应该将关闭 避免不正当的使用onPageScroll · 只在必要的时候监听pageScroll 事件 · 避免在onPageScroll 中执行复杂的逻辑 · 避免在onPageScroll 中频繁调用setData · 避免频繁查询节点信息(SelectQuery) 部分场景建议使用节点布局相交状态 · 监听( IntersectionObserver) 替代 使用自定义组件 在需要频繁更新的场景下,自定义组件的更新只在组件内部进行,不受页面部分内容的复杂性的影响。 使用体验评分功能 在开发过程中使用体验评分可以测试出代码中一些需要优化的点,准备定位到影响性能的原因,很大程序提高页面的性能。
2019-03-22 - 【技巧】利用canvas生成朋友圈分享海报
大家好,上次给大家讲了函数防抖和函数节流https://developers.weixin.qq.com/community/develop/doc/0002c892fb80a8326bf70f56d5bc04 今天给大家分享一下利用canvas生成朋友圈分享海报 由于小程序的限制,我们不能很方便地在微信内直接分享小程序到朋友圈,所以普遍的做法是生成一张带有小程序分享码的分享海报,再将海报保存到手机相册,有两种方法可以生成分享海报,第一种是让后台生成然后返回图片链接,这一种方法比较简单,只需要传后台所需要的参数就行了,今天给大家介绍的是第二种方法,用canvas生成分享海报。 首先先来看下效果: [图片] 主要步骤: 1. 把海报样式用标签先写好,方便画图时可以比对 2. 用canvas进行画图,canvas要注意定好宽高 3. canvas利用wx.canvasToTempFilePath这个api将canvas转化为图片 4. 将转化好的图片链接放入image标签里 5. 再利用wx.saveImageToPhotosAlbum保存图片 这里有几个坑点需要注意下: 1. 用canvas进行画图的时候要注意画出来的图的大小一定要是你用标签写好那个样式的两倍大小,比如你的海报大小是400*600的大小,那你用canvas画的时候大小就要是800*1200,宽高可以写在样式里,如果你画出来的图跟你海报图是一样的大小的话生成的图片是会很模糊的,所以才需要放大两倍。 2. 画图的时候要注意尺寸的转化,如果你是用rpx做单位的话,就要对单位进行转化,因为canvas提供的方法都是经px为单位的,所以这一点要注意一下,px转rpx的公式是w/750*z*2,w是手机屏幕宽度screenWidth,可以通过wx.getSystemInfo获取,z是你需要画图的单位,2就是乘以两倍大小。 3. 图片来源问题,因为canvas不支持网络图片画图,所以你的图片要么是固定的,如果不是固定的,那就要用wx.downloadFile下载后得到一个临时路径才行 4. 小程序码问题,小程序需要后台请求接口后返回一个二进制的图片,因为二进制图片canvas也是不支持的,所以也是要用wx.downloadFile下载后得到一个临时路径,或者可以叫后台直接返回一个小程序码的路径给你 5. 这里保存的时候是有个授权提醒的,如果拒绝的话再次点击就没有反应了,所以这里我做了一个判断是否有授权的,如果没有就弹窗提醒,确认的话会打开设置页面,确认授权后再次返回就行了,这里有个坑注意下,就是之前拒绝后再进入设置页面确认授权返回页面时保存图片会不成功,官方还没解决,我是加了个setTimeOut处理的,详情可以看这里https://developers.weixin.qq.com/community/develop/doc/000c46600780f0fa68d7eac345a400 代码实现: [图片] 这里图片我先用的是网上的链接,实际项目中是后台返回的数据,这个可以自行处理,这里只是为了演示方便,生成临时路径的方法我这里是分别定义了一个方法,其实可以合成一个方法的,只是生成小程序码时如果要传入参数要注意一下。 绘图方法是drawImg,这里截一部分,详细的可以看代码片段 [图片] 不足: 由于在实际项目中返回的图片宽高是不固定的,但是canvas画出来的又需要固定宽高,所以分享图会有图片变形的问题,使用drawImage里的参数也不能解决,如果各位有比较好的方案可以一起讨论一下。 代码片段: https://developers.weixin.qq.com/s/3pcsjDmS7M5Y 系甘先,得闲饮茶
2019-01-23 - 【优化】小程序优化-代码篇
本文主要是从代码方面跟大家分享我自己在开发小程序的一些做法,希望能帮到一些同学。 前言 不知道大家有没有这种体会,刚到公司时,领导要你维护之前别人写的代码,你看着别人写的代码陷入了深深的思考:“这谁写的代码,这么残忍” [图片] 俗话说“不怕自己写代码,就怕改别人的代码”,一言不和就改到你吐血,所以为了别人好,也为了自己好,代码规范,从我做起。 项目目录结构 在开发之前,首先要明确你要做什么,不要一上来就是干,咱们先把项目结构搭好。一般来说,开发工具初始化的项目基本可以满足需求,如果你的项目比较复杂又有一定的结构的话就要考虑分好目录结构了,我的做法如下图: [图片] component文件夹是放自定义组件的 pages放页面 public放公共资源如样式表和公共图标 units放各种公共api文件和封装的一些js文件 config.js是配置文件 这么分已经足以满足我的需求,你可以根据自己的项目灵活拆分。 配置文件 我的项目中有个config.js,这个文件是用来配置项目中要用到的一些接口和其它私有字段,我们知道在开发时通常会有测试环境和正式环境,而测试环境跟正式环境的域名可能会不一样,如果不做好配置的话直接写死接口那等到上线的时候一个个改会非常麻烦,所以做好配置是必需的,文件大致如下: [图片] 首先是定义域名,然后在config对象里定义接口名称,getAPI(key)是获取接口方法,最后通过module暴露出去就可以了.引用的时候只要在页面引入 import domain from ‘…/…/config’;,然后wx.request的时候url的获取方式是domain.getAPI(’’) 代码健壮性、容错性 例子 代码的健壮性、容错性也是我们应该要考虑的一点,移动端的项目不像pc端的网络那么稳定,很多时候网络一不稳定就决定我们的项目是否能正常运行,而一个好的项目就一定要有良好的容错性,就是说在网络异常或其它因素导致我们的项目不能运行时程序要有一个友好的反馈,下面是一个网络请求的例子: [图片] 相信多数人请求的方式是这样,包括我以前刚接触小程序的时候也是这样写,这样写不是说不好,而是不太严谨,如果能够正常获取数据那还好,但是一旦请求出现错误那程序可以到此就没法运行下去了,有些比较好的会加上faill失败回调,但也只是请求失败时的判断,在请求成功到获取数据的这段流程内其实是还有一些需要我们判断的,一般我的做法是这样: [图片] 在请求成功后小程序会进行如下判断: 判断是否返回200,是则进行一下步操作,否则抛出错误 判断数据结构是否完整,是则进行一下步操作,否则抛出错误 然后就可以在页面根据情况进行相应的操作了。 定制错误提示码 可以看到上面的截图的错误打印后面会带一个gde0或gde1的英文代码,这个代码是干嘛用的呢,其实是用来报障的,当我们的小程序上线后可能会遇到一些用户发来的报障,一般是通过截图发给我们,之前没有做错误提示码的时候可能只是根据一句错误提示来定位错误,但是很多时候误提示语都是一样的,我们根本不知道是哪里错了,这样一来就不能很快的定位的错误,所以加上这样一个提示码,到时用户一发截图来,我们只要根据这个错误码就能很快的定位错误并解决了,错误提示码建议命名如下: 不宜过长,3个字母左右 唯一性 意义明确 像上面gde表示获取草稿失败,后面加上数字表示是哪一步出错。 模块化 我们组内的大神说过, 模块化的意义在义分治,不在于复用。 之前我以为模块化只是为了可以复用,其实不然,无论模块多么小也是可以模块化,哪怕只是一个简单的样式也一样,并是不为了复用,而是管理起来方便。 很多同学经常将一些公共的样式事js放在app.wxss和app.js里以便调用,这样做其实有一个坏处,就是维护性比较差,如果是比较小的项目还好,项目一大问题就来了。而且项目是会迭代的,不可能总是一个人开发,可能后面会交接给其他人开发,所以会造成的问题就是: app.wxss和app.js里的内容只会越来越多,因为别人不确定哪些是没用的也不敢删,只能往里加东西,造成文件臃肿,不利于维护。 app.wxss和app.js对于每个页面都有效,可读性方面比较差。 所以模块化的意义就出来了,将公共的部分进行模块化统一管理,也便于维护。 样式模块化 公共样式根据上面的目录结构我是放在public里的css里,每个文件命名好说明是哪个部分的模块化,比如下面这个就表示一个按钮的模块化 [图片] 前面说过模块化不在于大小,就算只是一个简单的样式也可以进行模块化,只要在用到的地方import一下就行了,就知道哪里有用到,哪里没有用到,清晰明了。 js模块化 js模块化这里分为两个部分的模块化,一部分是公共js的模块化,另一部分是页面js的模块化即业务与数据的拆分。 公共js模块化 比较常用的公共js有微信登录,弹窗,请求等,一般我是放在units文件夹里,这里经微信弹窗api为例: [图片] 如图是在小程序中经常会用到的弹窗提示,这里进行封装,定义变量,只要在页面中引入就能直接调用了,不用每次都写一大串。比如在请求的时候是这样用的 [图片] toast()就是封装的弹窗api,这样看起来是不是清爽多了! 业务与数据模块化 业务与数据模块化就是指业务和数据分开,互不影响,业务只负责业务,数据只负责数据,可以看到页面会比普通的页面多了一个api.js [图片] 这个文件主要就是用来获取数据的,而index.js主要用来处理数据,这样分工明确,相比以往获取数据和处理数据都在一个页面要好很多,而且我这里获取数据是返回一个promise对象的,也方便处理一些异步操作。 组件化 组件化相信大家都不陌生了,自从小程序支持自定义组件,可以说是大大地提高了开发效率,我们可以将一些公共的部分进行组件化,这部分就不详细介绍,大家可以去看文档。组件化对于我们的项目来说有很大的好处,而且组件化的可移植性强,从一个项目复用到另一个项目基本不需要做什么改动。 总结 这篇文章通过我自己的一些经验来给大家介绍如何优化自己的代码,主要有以下几点 分好项目目录结构 做好接口配置文件 代码健壮性、容错性的处理 定制错误提示码方便定位错误 样式模块化和js模块化 组件化 最后放上项目目录结构的代码片段,大家可以研究一下,有问题一起探讨:https://developers.weixin.qq.com/s/1uVHRDmT7j6l
2019-03-07