SegmentFault SangSir最新的文章
2022-04-14T17:12:09+08:00
https://segmentfault.com/feeds/blogs
https://creativecommons.org/licenses/by-nc-nd/4.0/
天地图修改主题颜色修改背景色
https://segmentfault.com/a/1190000041703873
2022-04-14T17:12:09+08:00
2022-04-14T17:12:09+08:00
SangSir
https://segmentfault.com/u/sangsir
2
<h2>前言</h2><p><img src="/img/remote/1460000041703875" alt="天地图默认地图样式" title="天地图默认地图样式"><br>最近公司比较忙,也没时间发些博文,最近正好由于项目需要大屏展示地图,大屏多数都是使用暗蓝色底图,目前天地图不提供暗蓝色瓦片,自带的JS API只支持black和indigo,但项目要求必须要用天地图。搜索引擎找了找解决方案,也是花里胡哨的各种方式都有,最后决定用CSS的filter解决这个问题,在博客记录下解决方法。</p><h2>灵感</h2><blockquote><a href="https://link.segmentfault.com/?enc=AR3KnFEELmIrcJyfGEZamQ%3D%3D.iQbdTTUkdHin6HjX6josMK%2BXVBTwM5KXnN97xc1G83q8bReLanOpc%2FgiwAnhhmMVcTGcIN9wm0QrKIYISKaTvYbzRfX1WtFrBNSZ9LmdZbY%3D" rel="nofollow">https://blog.csdn.net/Corey_m...</a></blockquote><p>通过这篇博文的介绍,大概确定了方向,就是用<code>filter:url()</code>加上预定义效果的函数调整出最终效果。</p><h2>方法</h2><ol><li>打开:<a href="https://codepen.io/stoumann/pen/MWeNmyb">CSS Filter 编辑器</a></li><li>上传天地图的截图到编辑器,调整下方预设及右侧参数<br><img src="/img/remote/1460000041703876" alt="调整参数" title="调整参数"></li><li>将svg预设放置在<body>中,将编辑器中CSS Code的栏目所生成的CSS,加在天地图的canvas上面<br><img src="/img/remote/1460000041703877" alt="CSS Code" title="CSS Code"><br><img src="/img/remote/1460000041703878" alt="天地图改色效果" title="天地图改色效果"></li></ol><blockquote>如果预设没有想要的效果,可以使用<a href="https://link.segmentfault.com/?enc=l04rI783BKUZRoAu6obnQQ%3D%3D.juB%2BRi84nKFUeiHdTssr1TKiFrWTn4uFzOPA4Qrtz59ALobtCrZGD3Lmenj%2Bydzl" rel="nofollow">SVG Gradient Map Filter</a>,自己调出一个</blockquote><h2>效果展示</h2><p>经过调整后的最终展示效果,谁能想到这竟然是天地图呢?<br><img src="/img/remote/1460000041703879" alt="调整后的最终展示效果" title="调整后的最终展示效果"></p>
阿里巴巴前端暑期实习面经
https://segmentfault.com/a/1190000019406592
2019-06-06T12:15:40+08:00
2019-06-06T12:15:40+08:00
SangSir
https://segmentfault.com/u/sangsir
31
<h2>前言</h2>
<p>先说一下为什么要去面试,因为之前跟学长吃饭的时候聊起来,大三这时候找一个暑期实习是个好机会,并且我在学校拿的奖也都围绕着前端来的。作为一个想知道自己处于什么水平的人来说,肯定要投大厂了,于是选择了阿里巴巴的前端开发,在3月19日阿里大佬将简历内推至校园招聘系统。</p>
<h2>一面(57分钟)</h2>
<p>在完善简历的第二天,3月20日晚上20:20,便有阿里巴巴的座机号打来进行电话面试,没想到来的这么快,当时一点准备的东西都没有,脑袋是懵的。</p>
<ul>
<li>简单介绍一下你自己</li>
<li>你所学的专业在班中的水平是怎样的</li>
<li>印象深刻的一个项目</li>
<li>github开源项目的90+ star怎么来的</li>
<li>css盒模型</li>
<li>css实现垂直居中</li>
<li>jQuery的dollar($)是怎么实现的</li>
<li>jQuery的ajax原理</li>
<li>跨域问题怎么解决</li>
<li>jsonp的原理</li>
<li>js的事件绑定</li>
<li>document.ready和window.onload的区别</li>
<li>有什么问题想问我的</li>
<li>Ps.面试结尾时直接说面试过了,还有一些小细节忘记了...</li>
</ul>
<h2>二面(29分钟)</h2>
<p>3月25日晚上21:28,浙江杭州的私人手机号打来进行电话面试。</p>
<ul>
<li>简单介绍一下你自己</li>
<li>为什么选择做前端(我的专业是设计)</li>
<li>
<p>说说你的项目经历和技术难点</p>
<ul>
<li>...围绕项目的技术点深入展开</li>
<li>...围绕项目的技术点模拟其他场景如何实现或解决</li>
</ul>
</li>
<li>es6和es5的区别</li>
<li>let和var的区别</li>
<li>js怎么解决继承问题</li>
<li>如果有一个helloworld字符串,怎么反转</li>
<li>小程序相比h5有哪些优势</li>
<li>有哪些跨平台开发的框架</li>
<li>有什么问题想问我的</li>
<li>Ps.还有一些小细节忘记了...</li>
</ul>
<h2>三面(31分钟)</h2>
<p>3月31日晚上19:31,二面的面试官打来进行电话面试,深入说一下你的两个比赛所做的项目,面试官用STAR原则引导着我把项目深入的说出来,这点很棒!其实在简历和面试中也应该用STAR原则来说明!最后是有什么问题想问我的,没有问基础。</p>
<p><strong>Ps.三面完成之后我加了面试官的微信,跟我说后面还会有交叉面,让我多看一下基础,例如:事件,闭包,盒模型,vue、react的数据绑定,虚拟DOM等等</strong></p>
<h2>交叉面(32分钟)</h2>
<p>4月2日晚上18:12,天猫技术部的面试官打来进行电话面试,自我介绍+印象深刻的项目,针对项目问一些问题,有什么问题想问我的,没有问基础。</p>
<p><strong>Ps.项目问的非常有深度,这点要注意,不要在简历上面给自己挖坑!</strong></p>
<h2>hr面(43分钟)</h2>
<p>4月4日中午11:10,hr小姐姐打来进行电话要进行视频面试,用的是阿里自家的视频会议系统,聊的内容与牛客网中的阿里hr面试的问题基本相同。</p>
<h2>感受</h2>
<p>阿里的面试官态度真的超棒!!!面试最后可以问一下面试官我之后该怎样去学习,哪方面比较欠缺,大佬们会对你进行一个总结和建议,让你针对性的去学习薄弱的部分。疯狂打call!!!<br>通过这次面试之后,发现自己对前端的了解仅限于面向文档、Google、Stack Overflow,对于JavaScript的基础和所做项目的技术深度了解非常差,算法更是一片空白。不管面试过不过,未来还是要加油啦!</p>
<h2>最后</h2>
<p>2019.04.12,23:57。邮件+短信通知,发来阿里录用意向书,没想到只面试了阿里,还能走到最后,运气爆炸!<br>2019.04.22,11:54。hr小姐姐打电话确定入职时间和流程,offer call终于来啦~~~</p>
<p>另外推荐一个前端大佬给我的面试图谱,基本上js的基础面试问题都在里面包含了!真后悔面试前没好好看一下!!!点这里>>> <a href="https://link.segmentfault.com/?enc=UQ%2Bk%2FYrKiy2Q38loxPkrWg%3D%3D.BA9ZyP0lULgmSsxsLqfluXuIrKnItw0gBQikef2fP8ldLdofOfSKqweytUiRDwC4" rel="nofollow">InterviewMap</a></p>
<p>还有另外一个面经,也是超棒的!点这里>>> <a href="https://link.segmentfault.com/?enc=gxlX9kwmTW0ABVw2bxUNIQ%3D%3D.eV3xqwHay9bbo2N%2F2pfwqG8yIcR%2BZGX3C19g%2FRf04s7XXNw0%2FBrIJ4DIgJ1szkKBKAfY0rNFKZDhC7bf7Oiz6A%3D%3D" rel="nofollow">中高级前端大厂面试秘籍,为你保驾护航金三银四,直通大厂(上)</a></p>
利用XSS漏洞轻松拿到登录用户的cookie
https://segmentfault.com/a/1190000019406499
2019-06-06T12:03:46+08:00
2019-06-06T12:03:46+08:00
SangSir
https://segmentfault.com/u/sangsir
2
<h2>前言</h2>
<p>最近在逛小程序,其中发现一个小程序是申请用户信息后自动在某站注册账号。<br>于是便去网站看了下,WOW!好多输入框~就顺手试了下xss。<br><img src="/img/remote/1460000019406502" alt="1.png" title="1.png"></p>
<h2>找到XSS漏洞</h2>
<p>本着学习交流的目的,用颤巍巍的手指在用户名称的输入框里输下了如下代码:<br><code><script>alert(1)</script></code><br><img src="/img/remote/1460000019406503?w=567&h=100" alt="2.png" title="2.png"><br>emm...没反应,内心一阵失落,并没有预期中那样弹出个框来,叹了口气。<br>但是,好歹是个程序猿,不能轻言放弃。<br>便找了一些xss变异代码进行测试:<br><code></textarea><img onerror="alert(1)" src='1'></code><br><img src="/img/remote/1460000019406504?w=448&h=130" alt="3.png" title="3.png"><br>WOW!棒呆呆!</p>
<h2>进一步利用XSS漏洞</h2>
<p>当时我在想,他的小程序是有充值功能的。<br>管理员或者财务肯定会没事儿看一下今天有没有消费呀~有哪些新用户充值了呀~<br>那不如~<br>刷两笔充值的单子,然后在用户名称中植入xss,姜太公钓鱼愿者上钩。<br>便从搜索引擎找了几家带https的xss平台,勾选个能获取cookie的模块:<br><img src="/img/remote/1460000019406505" alt="4.png" title="4.png"></p>
<h2>Two(第) years(二) later(天)...</h2>
<p><img src="/img/remote/1460000019406506" alt="5.png" title="5.png"><br>鱼儿上钩~成功拿到用户名和cookie,那么挂代理,开发者工具,Application,修改Cookies,刷新页面。</p>
<h2>真的幸运</h2>
<p><img src="/img/remote/1460000019406507?w=218&h=334" alt="6.png" title="6.png"><br>头一次利用xss干一些事情,很舒服。<br>可惜的是后台和用户中心是共用的,并没有找到上传文件等再利用的地方。<br><img src="/img/remote/1460000019406508" alt="7.png" title="7.png"><br>只能充个小钱啥的~</p>
<h2>漏洞提交</h2>
<p><img src="/img/remote/1460000019406509" alt="8.png" title="8.png"><br>已反馈给相关管理员进行修复。</p>
<h2>结束语</h2>
<p>做开发的,安全防范意识一定要有啊!</p>
URP教务内网查询解决方案
https://segmentfault.com/a/1190000014699077
2018-05-02T22:28:30+08:00
2018-05-02T22:28:30+08:00
SangSir
https://segmentfault.com/u/sangsir
0
<h2>起因</h2>
<p>目前在许多学校中存在着教务外包、运维人员技术差、服务器资源少等问题,所以一般教务系统都不会暴露在外网中。但成绩查询、课表查询这种<strong>刚需</strong>,让我不得不研究一下如何将内网穿透出去。</p>
<h2>分析</h2>
<p>目前<strong>我已知</strong>的内网穿透方式有:ssh tunnel、frp、ngrok、花生壳,但ssh tunnel速度一般,花生壳高昂的服务价格已经不在考虑之列,加之手里已经有 vps,所以倾向于用现有的资源,在frp与ngrok中进行比对选择。</p>
<h2>ngrok(<a href="https://link.segmentfault.com/?enc=lmi2LKqCRvkvTjpfmO%2FDcw%3D%3D.lIsMAcPw6kM4EmILvEtyRm2afgAm8ZyA%2FUM734crEjQ94wAmoxyVaiE2gSPYHGZA" rel="nofollow">https://github.com/inconshrev...</a>)</h2>
<ol>
<li>ngrok1为开源版本,存在许多已知问题(http模式有内存泄露bug),ngrok2闭源,并且官方好像并不打算开源,只会开源client端</li>
<li>ngrok需要自己编译程序,因为ngrok采用的是证书验证,而且证书直接编译到exe文件里面去了,所以必须自行编译客户端与服务器端</li>
</ol>
<h2>frp(<a href="https://link.segmentfault.com/?enc=Eb2DePxZRFBuEGWJtARk%2Bw%3D%3D.sSeQ1Mhdw88sKetGNJoTcq3MTLSS3yB8Z16ag9t1XmQ%3D" rel="nofollow">https://github.com/fatedier/frp</a>)</h2>
<ol>
<li>完全开源</li>
<li>有中文文档</li>
<li>未来计划:frps 支持直接反向代理,类似 haproxy;frpc 支持负载均衡到后端不同服务。</li>
</ol>
<p>这样一对比,发现frp完全符合我的需求,所以有了下面一套解决方案:</p>
<p><img src="/img/remote/1460000014699082" alt="解决方案" title="解决方案"></p>
<p>现在已经入手树莓派,坐等到货开始折腾,后续会继续记录整套方案的实施过程。<br>另外推荐frp一键脚本:<a href="https://link.segmentfault.com/?enc=rEFfBSsrMkyMNOtlaONQUg%3D%3D.5FyRltF34ymH%2FQuxjZNI3LWHHqky6um32ToY%2BLIjBVs%3D" rel="nofollow"></a><a href="https://link.segmentfault.com/?enc=ntjmyaOqGuqbEJVAy18E9Q%3D%3D.sTSIADnARwHmqsEliqj0%2FI2J%2B6otKg%2BWm2UJV6D%2Bh8Y%3D" rel="nofollow">http://www.lu8.win/frp.html</a>,该站还有ngrok、n2n的一键脚本。</p>
制作QQ微信支付宝三合一收款码
https://segmentfault.com/a/1190000013301132
2018-02-17T23:00:28+08:00
2018-02-17T23:00:28+08:00
SangSir
https://segmentfault.com/u/sangsir
44
<h2>前言</h2>
<p>最近在逛博客时,发现很多博客都带了打赏功能,虽说打赏的人可能很少,但始终是一份心意,能让博主知道自己写的文章有用,能够帮助到人。所以,我也想加一个打赏功能~</p>
<h2>分析</h2>
<p>但在github逛了一圈之后发现,打赏插件基本上千篇一律的:QQ扫码/微信扫码/支付宝扫码。</p>
<p><img src="/img/remote/1460000013301137?w=320&h=111" alt="按钮捐赠" title="按钮捐赠"><br>有的是点击每个按钮出现每个收款码</p>
<p><img src="/img/remote/1460000013301138?w=409&h=436" alt="二维码捐赠" title="二维码捐赠"><br>有的则是每个收款码全部展现出来</p>
<p>微信扫这个,支付宝扫那个,不仅要加载多张二维码,还要加css/js让它变的好看,作为一个又懒又不想写这些东西的程序猿来说,这可不行。</p>
<p>那能不能把QQ微信支付宝三合一,只需要扫一个收款码就行呢?<br>这里涉及到一个知识点,则是User-Agent,大厂的webview都会携带自家的UA信息,比如说:</p>
<p>QQ:<code>MQQBrowser/6.2 TBS/043221 Safari/537.36 QQ/7.0.0.3135</code><br>微信:<code>MQQBrowser/6.2 TBS 043220 Safari/537.36 MicroMessenger/6.5.8.1060 NetType/4G Language/zh_CN</code><br>支付宝:<code>UCBrowser/11.5.0.939 UCBS/2.10.1.6 Mobile Safari/537.36 AliApp(AP/10.0.15.051805) AlipayClient/10.0.15.051805 Language/zh-Hans</code></p>
<p>这样就很轻松区分是QQ还是微信还是支付宝扫码了:</p>
<p>User-Agent 含有 <code>QQ/</code> 为QQ<br>User-Agent 含有 <code>MicroMessenger</code> 为微信<br>User-Agent 含有 <code>AlipayClient</code> 为支付宝</p>
<p>既然能够区分每个软件,那就可以通过自建一个网址,通过二维码生成扫描这个网址后,判断浏览器的UA,来分发不同的收款码</p>
<p>大致的流程则为:<br>客户端扫码 -> 服务端根据 User-Agent 判断客户端类型 -> 分别返回不同的处理</p>
<h2>开始折腾</h2>
<p>首先解码QQ、微信和支付宝生成的付款码,可以<a href="https://link.segmentfault.com/?enc=%2F5218oPcjgsYHlJqE1V2aA%3D%3D.HBrV1iFGh71LIR2v2NS19ps1B%2BEbVnWjW0qERgi%2BZ5oDU9G8Gul69bAyoc7m2I0Q" rel="nofollow">去这里</a>在线解码。</p>
<p>QQ:<code>https://i.qianbao.qq.com/wallet/sqrcode.htm?m=tenpay&a=1&u=17878127&ac=E04BE442991E7FFED28B3B5C3E187148F063DC3C6DACAD2983C87B482FC9E7AD&n=薛定谔的猫&f=wallet</code><br>(https 协议,无法唤醒QQ)<br>支付宝:<code>HTTPS://QR.ALIPAY.COM/FKX03549OW666ME7BXWF7A</code><br>(https 协议,可直接唤醒支付宝 APP)<br>微信:<code>wxp://f2f09hjzo72AAYEITIBaolV-3cvGrDjE0q7k</code><br>(微信自己的支付协议,无法唤醒微信)</p>
<p>下面就可以直接写代码了,判断 User-Agent 如果是支付宝直接跳转支付宝链接,如果是QQ和微信则跳转QQ和微信的链接。</p>
<p>但由于QQ与微信无法直接唤醒APP,所以直接输出一个QQ与微信的二维码,然后长按扫码实现支付。</p>
<p>代码如下:</p>
<pre><code class="php"><?php
$ua = $_SERVER['HTTP_USER_AGENT'];
if (strpos($ua, 'MicroMessenger')) {
$type = 'wepay';
$name = '微信支付';
//微信支付链接
$url = 'wxp://f2f09hjzo72AAYEITIBaolV-3cvGrDjE0q7k';
$icon_img = '<img src="http://ww2.sinaimg.cn/large/005zWjpngy1fojrwgr20oj303k03kglg.jpg" width="48px" height="48px" alt="'.$name.'">';
}
elseif (strpos($ua, 'AlipayClient')) {
//支付宝链接
$url = 'HTTPS://QR.ALIPAY.COM/FKX03479QJ0RVOS3UJLQAE';
header('location: ' . $url);
}
elseif (strpos($ua, 'QQ/')) {
$type = 'qq';
$name = 'QQ钱包支付';
//QQ钱包支付链接
$url = 'https://i.qianbao.qq.com/wallet/sqrcode.htm?m=tenpay&a=1&u=17878127&ac=E04BE442991E7FFED28B3B5C3E187148F063DC3C6DACAD2983C87B482FC9E7AD&n=薛定谔的猫&f=wallet';
$icon_img = '<img src="http://ww2.sinaimg.cn/large/005zWjpngy1fojrvmp427j303k03kjrb.jpg" width="48px" height="48px" alt="'.$name.'">';
}
else {
$type = 'other';
$name = '打赏作者';
$url = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
$icon_img = '<img src="http://ww2.sinaimg.cn/large/005zWjpngy1fojs089x6tj303k03kjr6.jpg" width="48px" height="48px" alt="'.$name.'">';
}
$qr_img = '<img src="http://qr.liantu.com/api.php?text='.urlencode($url).'">';
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=Edge, chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?=$name?></title>
<style type="text/css">
* {margin: auto;padding: 0;border: 0;}
html {-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%}
body {font-family: -apple-system, SF UI Text, Arial, Microsoft YaHei, Hiragino Sans GB, WenQuanYi Micro Hei, sans-serif;color: #333;}
img {max-width: 100%;}
h3 {padding: 10px;}
.container {text-align: center;}
.title {padding: 2em 0;background-color: #fff;}
.content {padding: 2em 1em;color: #fff;}
.wepay {background-color: #23ac38;}
.qq {background-color: #4c97d5;}
.other {background-color: #ff7055;}
</style>
</head>
<body class="<?=$type?>">
<div class="container">
<div class="title"><?=$icon_img?><h1><?=$name?></h1></div>
<div class="content"><?=$type=='other'?$qr_img.'<h3>请使用支付宝、微信、QQ客户端扫码付款</h3>':$qr_img.'<h3>扫描或长按识别二维码,向TA付款</h3>'?></div>
</div>
</body>
</html></code></pre>
<h2>Demo演示</h2>
<p>可以通过扫描文章底部的二维码进行测试,或点击下面的演示地址:<br><a href="https://link.segmentfault.com/?enc=QGyGMxUnq4ujNLGbPwXKDQ%3D%3D.4%2FP5UJw%2BEX8UbxPvb7397NnrME%2BsFMskS0uiBJTBpYDkKZbiian%2FyUIl36ThB%2BtO" rel="nofollow"></a><a href="https://link.segmentfault.com/?enc=TksTsNn%2FF5t517qL%2FMJTlA%3D%3D.6eEjLKNR09wCBVs%2FQsc1YeeDUelVPPgcmqAIjL2L1qcIkXPmFvsO3wHQ%2Fphe6KhE" rel="nofollow">http://lab.sangsir.com/api/do...</a></p>
<h2><del>顺便打赏一下作者?</del></h2>
<p><img src="/img/remote/1460000013301139?w=300&h=300" alt="打赏作者" title="打赏作者"></p>
初探python之做一个简单小爬虫
https://segmentfault.com/a/1190000012949844
2018-01-23T11:31:04+08:00
2018-01-23T11:31:04+08:00
SangSir
https://segmentfault.com/u/sangsir
2
<h2>准备工作</h2>
<p>初探python,这个文章属于自己的一个总结。所以教程面向<strong>新手</strong>,无技术含量。<br>python环境Linux基本都有,Windows下官网也提供了便利的安装包,怎么安装配置网上有很多教程在此就不一一说明。<br>我使用的python版本为Python 3.6.4,后面的代码也是基于python3的。</p>
<h2>分析需求</h2>
<p>做一个小爬虫离不开获取网页内容和匹配存储内容,那么我们先装上python爬虫的老朋友requests:<br><code>pip install requests</code><br>再装上pymysql扩展,方便将匹配到的内容插入到mysql数据库中:<br><code>pip install pymysql</code></p>
<h2>第一步:获取网页内容</h2>
<p>在python中有意思的是你需要什么,就去import什么,不像php一样获取网页内容直接来个<code>file_get_contents</code>完事儿<br>废话不多说,贴出代码来看一下:</p>
<pre><code class="python"># -*- coding:utf-8 -*-
# 加载 requests 模块
import requests
# GET方式获取 Response 对象
response = requests.get('https://www.xxx.com/')
if response:
# 输出html代码到控制台
print(response.text)
else:
# 输出错误信息
print('requests error')</code></pre>
<p>在python中缩进一定要严格,初学者(4个空格为语句块缩进)经常犯的错误是tab键和空间键混用,造成的缩进不一致。凡是报错信息看到:IndentationError: unexpected indent ,就是表示缩进不一致。<br>如果本身没有编码基础,那么我推荐你看一下python的基本概念:<a href="https://link.segmentfault.com/?enc=weDSOENIGHnDlZgU1VASoQ%3D%3D.KZXGidsV9lKJPaoalhyVtE89V%2BifJ2LGl1KSPCrCsCEL7pdwtoP3tfbuoF8Es6%2B4" rel="nofollow"></a><a href="https://link.segmentfault.com/?enc=xXsYiFlY9FUmRdsRHER02Q%3D%3D.HXrds9ouBG45j9voyxqMcpSklrbqG%2BA%2B1nJLSOSiI%2BZHVUDwZrfG1To8vtwgq3H4" rel="nofollow">http://www.kuqin.com/abyteofp...</a><br>如果已经有了编码基础但对缩进这方面没有深究,可以看python的缩进规范:<a href="https://link.segmentfault.com/?enc=mRzf6M%2FsJeGmQUUItYEUfA%3D%3D.4F%2Bi6CYGxCXqfzfgKhWHRyavCfiwBcHNXdqe8GXb1p5fr12nA%2FqD6iejLU1vwYipBsvV5XlMO%2FLoIBvmxkAKTw%3D%3D" rel="nofollow"></a><a href="https://link.segmentfault.com/?enc=JQChvrhtfcKfFTUaOMQx%2FA%3D%3D.VK8To5cqidzG%2B2MFnO%2FPHJlSYZ2IdpqusLV25aeLgsJiWq%2F%2FqHGIX34XuoQdxicS5H3IgM8DYE5PwqPPGO%2FIdw%3D%3D" rel="nofollow">http://www.kuqin.com/abyteofp...</a></p>
<p>好,写完代码之后我们拿到控制台试一下,完美输出html代码<br><img src="/img/remote/1460000012949849?w=786&h=408" alt="requests" title="requests"></p>
<h2>第二步:正则匹配内容</h2>
<p>既然能够获取html代码,那我们就要找出需要的部分,这就用上了正则。Python 自1.5版本起增加了 re 模块,它提供 Perl 风格的正则表达式模式。具体细节可以在菜鸟教程中查看:<a href="https://link.segmentfault.com/?enc=wXShNwmS%2FYHYXEtr8WZZyQ%3D%3D.QcURSx%2FM0iI%2BPGuZeInYUUmSE%2F2%2F4iyuEu26mk8K8TFoOEPWeY0vpXLDK4GzbElsYFaAunYLgP2M0u%2FLP912Zw%3D%3D" rel="nofollow"></a><a href="https://link.segmentfault.com/?enc=%2FChi0Gz%2FWCVgJMYSuJVDpg%3D%3D.qKMKU8ofRJiG%2FepOqO0yCFw9E0aNPkdaUNDz2dDR9lgDyksieeLGS%2BA%2B%2FgPjxVQ8GlLPiirfW90Sg5xm%2FSXYvw%3D%3D" rel="nofollow">http://www.runoob.com/python/...</a>,话不多说再贴代码:</p>
<pre><code class="python"># -*- coding:utf-8 -*-
# 加载 requests 模块
import requests
# 加载 re 模块
import re
response = requests.get('https://www.xxx.com/')
# 正则匹配文本
match = re.findall(r'<p><!--markdown-->([\s\S]*?)</p>', response.text)
if match:
# 输出匹配的内容到控制台
print(match[0])
else:
# 输出html代码到控制台
print(response.text)</code></pre>
<p><img src="/img/remote/1460000012949850?w=733&h=159" alt="re" title="re"></p>
<p>注:原网址为随机一句文字显示,每刷新一次就会变化一次。</p>
<h2>第三步:循环匹配并加入数据库中</h2>
<p>首先我们把数据库和表做好,可以用sql语句创建:</p>
<pre><code class="sql">CREATE DATABASE IF NOT EXISTS `sentence`;
USE `sentence`;
CREATE TABLE IF NOT EXISTS `sexy` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`content` varchar(50) NOT NULL,
`datetime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `content` (`content`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;</code></pre>
<p>这里将content设置为了UNIQUE KEY,是为了保证抓取到的内容不重复,如果有已存在的值便直接跳过</p>
<pre><code class="python"># -*- coding:utf-8 -*-
# 加载 requests 模块
import requests
# 加载 re 模块
import re
# 加载 pymysql 模块
import pymysql
# 打开数据库连接
db = pymysql.connect('127.0.0.1', 'root', 'root', 'sentence', charset='utf8')
# 使用cursor()方法获取操作游标
cursor = db.cursor()
#死循环到天长地久
while(True):
response = requests.get('https://www.xxx.com/')
# 正则匹配文本
match = re.findall(r'<p><!--markdown-->([\s\S]*?)</p>', response.text)
if match:
sql = "INSERT INTO `sexy` (`content`) VALUES ('%s')" % (match[0])
try:
# 执行sql语句
cursor.execute(sql)
# 提交到数据库执行
db.commit()
except:
# 如果发生错误则回滚
db.rollback()
# 输出sql语句到控制台
print(sql)
else:
# 输出html代码到控制台
print(response.text)</code></pre>
<p>运行演示:<br><img src="/img/remote/1460000012949851?w=1049&h=625" alt="pymysql" title="pymysql"><br>数据库内容:<br><img src="/img/remote/1460000012949852?w=532&h=543" alt="mysql" title="mysql"></p>
<h2>总结</h2>
<p>python是个好东西,<del>万物based on python</del>。<br>感觉教程贴比较难写,每个地方都有细节,但如果讲细了文章又太繁琐,若简单些不好取舍初学者又看不懂什么意思,向那些写易懂的入门教程文章的作者致敬。<br>注:由于原网址不方便公布,代码中的网址全部替换为了xxx.com。<br>源码在Github中:<a href="https://link.segmentfault.com/?enc=RNeewkVwshhCmu5gHxxGSA%3D%3D.rKyvdZl0jrFAqdJtISJlej6aomIaVfmrFRbmvhom9RCs5diebhtVKdm7YuE2swVl" rel="nofollow"></a><a href="https://link.segmentfault.com/?enc=q423MMALDmu2bMxCVcwqQw%3D%3D.IYKHe7OtmSDu7ko8g83uBMMu%2B3jjtbznEKdcuxDIzSJ6quniv67ZtoB9Q1m9GRDr" rel="nofollow">https://github.com/st1ven/Pyt...</a>,欢迎Star</p>
PHP 一行代码删除目录下所有文件
https://segmentfault.com/a/1190000012771495
2018-01-09T19:11:46+08:00
2018-01-09T19:11:46+08:00
SangSir
https://segmentfault.com/u/sangsir
4
<p>想必很多人都会写几行甚至几十行代码使其列出所有文件变为数组进行删除,但是glob函数分分钟解决问题!</p>
<blockquote><strong>例子 1</strong></blockquote>
<pre><code class="php"><?php
print_r(glob("*.txt"));
?></code></pre>
<blockquote><strong>输出类似:</strong></blockquote>
<pre><code class="php">Array
(
[0] => target.txt
[1] => source.txt
[2] => test.txt
[3] => test2.txt
)</code></pre>
<blockquote><strong>例子 2</strong></blockquote>
<pre><code class="php"><?php
print_r(glob("*.*"));
?></code></pre>
<blockquote><strong>输出类似:</strong></blockquote>
<pre><code class="php">Array
(
[0] => contacts.csv
[1] => default.php
[2] => target.txt
[3] => source.txt
[4] => tem1.tmp
[5] => test.htm
[6] => test.ini
[7] => test.php
[8] => test.txt
[9] => test2.txt
)</code></pre>
<blockquote><strong>删除目录下所有文件</strong></blockquote>
<pre><code class="php">array_map('unlink', glob('*'));</code></pre>
PHP中获取当前页面的各种URL格式
https://segmentfault.com/a/1190000012751796
2018-01-08T17:28:29+08:00
2018-01-08T17:28:29+08:00
SangSir
https://segmentfault.com/u/sangsir
2
<blockquote>测试网址: <a href="https://link.segmentfault.com/?enc=YUEoXNHFFEkcVHudVCK82w%3D%3D.Zbet6%2FR0A6FbO87mBrxCiYz3r3%2FvZ38UuyvJicu0W5e0Rxw2EHhCA77n6iFjRvyQ" rel="nofollow">http://localhost/sangsir/mani...</a>
</blockquote>
<pre><code class="php">//获取域名或主机地址
echo $_SERVER['HTTP_HOST'];
#localhost</code></pre>
<pre><code class="php">//获取网页地址
echo $_SERVER['PHP_SELF'];
#/sangsir/manito.php</code></pre>
<pre><code class="php">//获取网址参数
echo $_SERVER["QUERY_STRING"];
#id=1</code></pre>
<pre><code class="php">//获取完整的url
echo 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']; //第一种
echo 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'?'.$_SERVER['QUERY_STRING']; //第二种
#http://localhost/sangsir/manito.php?id=1</code></pre>
<pre><code class="php">//包含端口号的完整url
echo 'http://'.$_SERVER['SERVER_NAME'].':'.$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
#http://localhost:80/sangsir/manito.php?id=1</code></pre>
<pre><code class="php">//只取路径
$url='http://'.$_SERVER['SERVER_NAME'].$_SERVER["REQUEST_URI"];
echo dirname($url);
#http://localhost/sangsir</code></pre>
导出csv文件数字变科学计数法的解决方法
https://segmentfault.com/a/1190000012711114
2018-01-05T10:06:19+08:00
2018-01-05T10:06:19+08:00
SangSir
https://segmentfault.com/u/sangsir
1
<p>其实这个问题跟用什么语言导出csv文件没有关系。<br>Excel显示数字时,如果数字大于12位,它会自动转化为科学计数法;<br>如果数字大于15位,由于受精度限制,15位以后的数字会显示为0。</p>
<p>解决这个问题:<br>只要把数字字段后面加上显示上看不见的字符即可,字符串前面或者结尾加上制表符"t";<br>php程序可以这样判断,注意一定是"t",不是't'。</p>
iOS Safari 中点击事件失效的解决方法
https://segmentfault.com/a/1190000012703734
2018-01-04T17:15:01+08:00
2018-01-04T17:15:01+08:00
SangSir
https://segmentfault.com/u/sangsir
1
<h2>问题描述</h2>
<p>当使用委托给一个元素添加click事件时,如果事件是委托到 document 或 body 上,并且委托的元素是默认不可点击的(如 div, span 等),此时 click 事件会失效。</p>
<p>可以使用下面的代码在 iOS 中进行测试。</p>
<pre><code class="html"><!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<title>iOS click bug test</title>
<style>
.container {
}
.target {
display: block;
text-align: center;
margin: 100px 30px 0;
padding: 10px 0;
border: 1px solid #ccc;
}
</style>
</head>
<body>
<div class="container">
<div class="target"> Click Me! </div>
</div>
<script src="//code.jquery.com/jquery-2.1.4.min.js"></script>
<script type="text/javascript">
// 或者 $(document).on('click', ....)
$('body').on('click', '.target', function (e) {
alert('click');
});
</script>
</body>
</html></code></pre>
<h2>解决办法</h2>
<p>解决办法有 4 种可供选择:</p>
<ol>
<li>将 click 事件直接绑定到目标元素(即 .target)上</li>
<li>将目标元素换成 <code><a></code> 或者 button 等可点击的元素</li>
<li>将 click 事件委托到非 document 或 body 的父级元素上</li>
<li>给目标元素加一条样式规则 cursor: pointer;</li>
</ol>
<p>推荐后两种。从解决办法来看,推测在 safari 中,不可点击的元素的点击事件不会冒泡到父级元素。通过添加 cursor: pointer 使得元素变成了可点击的了。</p>
MySQL查询某个列中相同值的数量统计
https://segmentfault.com/a/1190000012684950
2018-01-03T14:53:13+08:00
2018-01-03T14:53:13+08:00
SangSir
https://segmentfault.com/u/sangsir
0
<h2>前言</h2>
<p>今天突然想到自己写的课表查询Api没有加统计功能,因此今天加上了统计,记录了请求的类型、事件和时间,等新学期到来的时候就能用上了,毕竟刚开学同学们还是比较在意这学期都有什么课的哈哈哈,而且也能够丰富一下<a href="https://link.segmentfault.com/?enc=Z7rFQ4C0lPxSK4o10FpUow%3D%3D.%2FF1t%2BgsUT494fMa9k5dIyDqJlm8yplh7w55XNlN%2F1Mg%3D" rel="nofollow">文经课表产品页</a>的内容。<br>不过光统计到数据库也没用啊对不对,起码要加个获取每个请求类型的总次数,方便显示出同学们更注重查询哪一方面,能为后面的优化指出方向。</p>
<h2>正文</h2>
<p>既然有了需求,那就分析一下,假设站在了客户和程序员的角度上来看:<br>客户的语言:获取每个请求类型的总次数<br>程序员的语言:查询某个列中相同值的数量统计<br>ok,写了这么多的铺垫终于点题了,那么就请出mysql的统计大佬:count,让它写用代码的语言展示一下<br>代码的语言:</p>
<pre><code class="sql">select `type`,count(1) as counts from `api_count` group by `type`</code></pre>
<h2>解析</h2>
<pre><code class="sql">select
`type`, //查询某个列
count(1) as counts //相同值的数量统计到(as)某列中
from
`api_count` //来自某个表
group by
`type` //根据(by)一定的规则进行分组(Group)</code></pre>
<h2>结语</h2>
<p>第一次这样写文章,应该会有趣些吧~<br>效果如链:<a href="https://link.segmentfault.com/?enc=HMQInfUI19noDG%2B%2BiUMKiw%3D%3D.vz%2F5GXSv9OA6BoyhdFLMcTxPl7ZDVU4uOW4G34hHXyelnXP2NMae9ZyzW9t4yjRy%2FRMmIpR113SNK1k8nZhqjg%3D%3D" rel="nofollow"></a><a href="https://link.segmentfault.com/?enc=WFwuZ3wjQm5cn9mZfpLhEA%3D%3D.un5QFqKB0YwVw8E2k%2FlMfpjVzIdg1lxRd1L3R3tQZUooUyVGipvgkmC29MyxFqOIoDRLMfcIzsdIwbp1W6eV0w%3D%3D" rel="nofollow">https://wechat.sangsir.com/ti...</a></p>
MySQL数据库规范及解读
https://segmentfault.com/a/1190000012658563
2018-01-01T14:31:13+08:00
2018-01-01T14:31:13+08:00
SangSir
https://segmentfault.com/u/sangsir
3
<h2>一、基础规范</h2>
<blockquote>第一条:必须使用InnoDB存储引擎</blockquote>
<p>解读:支持事务、行级锁、并发性能更好、CPU及内存缓存页优化使得资源利用率更高</p>
<blockquote>第二条:必须使用utf8(utf8mb4)字符集</blockquote>
<p>解读:万国码,无需转码,无乱码风险,节省空间,utf8mb4是utf8的超集,由于近年移动设备的增多,emoji表情以及部分不常见汉字在utf8下会表现为乱码,故需要升级至utf8mb4</p>
<blockquote>第三条:数据表、数据字段必须加入中文注释</blockquote>
<p>解读:N年后谁会知道这个a1,a2,a3字段是干嘛的</p>
<blockquote>第四条:禁止使用存储过程、视图、触发器、Event</blockquote>
<p>解读:<em>高并发<strong>大数据</strong>的互联网业务,<strong>架构</strong>设计思路是“解放<strong>数据库</strong>CPU,将计算转移到服务层”</em>,并发量大的情况下,这些功能很可能将数据库拖死,<em>业务逻辑放到服务层具备更好的扩展性,能够轻易实现“增机器就加性能”</em>。数据库擅长存储与索引,CPU计算还是上移吧</p>
<blockquote>第五条:禁止存储大文件或者大照片</blockquote>
<p>解读:为何要让数据库做它不擅长的事情?大文件和照片存储在文件系统,数据库里存URI多好</p>
<h2>二、命名规范</h2>
<blockquote>第一条:只允许<em>使用内网域名,而不是ip连接数据库</em>
</blockquote>
<p>解读:虽然IP访问更快,域名访问需要内网dns,但是对于大数据库的扩展和迁库考虑,域名更好</p>
<blockquote>第二条:线上环境、开发环境、<strong>测试</strong>环境数据库内网域名遵循命名规范</blockquote>
<p>业务名称:xxx<br>线上环境:dj.xxx.db<br>开发环境:dj.xxx.rdb<br>测试环境:dj.xxx.tdb<br>从库在名称后加-s标识,备库在名称后加-ss标识<br>线上从库:dj.xxx-s.db<br>线上备库:dj.xxx-sss.db</p>
<blockquote>第三条:库名、表名、字段名:小写,下划线风格,不超过32个字符,禁止拼音英文混用</blockquote>
<p>解读:见名知意,方便后续维护</p>
<blockquote>第四条:表名t_xxx,非唯一索引名idx_xxx,唯一索引名uniq_xxx</blockquote>
<p>解读:见名知意,方便后续维护</p>
<h2>三、表和字段设计规范</h2>
<blockquote>第一条:禁止使用外键,如果有外键完整性约束,需要应用程序控制</blockquote>
<p>解读:<em>外键会导致表与表之间耦合,update与delete操作都会涉及相关联的表,十分影响sql的性能</em>,甚至会造成死锁。高并发情况下容易造成数据库性能,<em>大数据高并发业务场景数据库使用以性能优先</em></p>
<blockquote>第二条:必须把字段定义为NOT NULL并且提供默认值</blockquote>
<p>解读:<br>a) null的列使索引/索引统计/值比较都更加复杂,对MySQL来说更难优化<br>b) null这种类型MySQL内部需要进行特殊处理,增加数据库处理记录的复杂性;同等条件下,表中有较多空字段的时候,数据库的处理性能会降低很多<br>c) null值需要更多的存储空,无论是表还是索引中每行中的null的列都需要额外的空间来标识<br>d) 对null的处理时候,只能采用is null或is not null,而不能采用=、in、<、<>、!=、not in这些操作符号。<em>如:where name!='shenjian',如果存在name为null值的记录,查询结果就不会包含name为null值的记录</em></p>
<blockquote>第三条:禁止使用TEXT、BLOB类型</blockquote>
<p>解读:会浪费更多的磁盘和内存空间,<em>非必要的大量的大字段查询会淘汰掉热数据,导致内存命中率急剧降低,影响数据库性能</em></p>
<blockquote>第四条:禁止使用小数存储国币</blockquote>
<p>解读:曾经踩过这样的坑,100元分3天摊销,每天摊销(100/3)元,结果得到3个33.33。后来实施对账系统,始终有几分钱对不齐,郁闷了很久(不是几分钱的事,是业务方质疑的眼神让研发很不爽),最后发现是除法惹的祸<br>解决方案:使用“分”作为单位,这样数据库里就是整数了</p>
<blockquote>第五条:必须使用varchar(20)存储手机号</blockquote>
<p>解读:<br>a) 涉及到区号或者国家代号,可能出现+-()<br>b) 手机号会去做数学运算么?<br>c) varchar可以支持模糊查询,例如:like“138%”</p>
<blockquote>第六条:禁止使用ENUM,可使用TINYINT代替</blockquote>
<p>解读:<br>a) 增加新的ENUM值要做DDL操作<br>b) ENUM的内部实际存储就是整数,你以为自己定义的是字符串?</p>
<blockquote>第七条:表必须有主键,例如自增主键</blockquote>
<p>解读:<br>a) 主键递增,数据行写入可以提高插入性能,可以避免page分裂,减少表碎片提升空间和内存的使用<br>b) 主键要选择较短的数据类型, Innodb引擎普通索引都会保存主键的值,较短的数据类型可以有效的减少索引的磁盘空间,提高索引的缓存效率<br>c) 无主键的表删除,在row模式的主从架构,会导致备库夯住</p>
<h2>四、索引设计规范</h2>
<blockquote>第一条:单表索引建议控制在5个以内</blockquote>
<p>解读:一个好的索引设计,可以让你的效率提高几十甚至几百倍,但过多反而适得其反</p>
<blockquote>第二条:单索引字段数不允许超过5个</blockquote>
<p>解读:字段超过5个时,实际已经起不到有效过滤数据的作用了</p>
<blockquote>第三条:禁止在更新十分频繁、区分度不高的属性上建立索引</blockquote>
<p>解读:<br>a) 更新会变更B+树,更新频繁的字段建立索引会大大降低数据库性能<br>b) "性别"这种区分度不大的属性,建立索引是没有什么意义的,不能有效过滤数据,性能与全表扫描类似</p>
<blockquote>第四条:建立组合索引,必须把区分度高的字段放在前面</blockquote>
<p>解读:能够更加有效的过滤数据</p>
<h2>五、SQL使用规范</h2>
<blockquote>第一条:禁止使用SELECT *,只获取必要的字段,需要显示说明列属性</blockquote>
<p>解读:<br>a) 读取不需要的列会增加CPU、IO、NET消耗<br>b) 不能有效的利用覆盖索引<br>c) 使用SELECT *容易在增加或者删除字段后出现程序BUG</p>
<blockquote>第二条:禁止使用INSERT INTO t_xxx VALUES(xxx),必须显示指定插入的列属性</blockquote>
<p>解读:容易在增加或者删除字段后出现程序BUG</p>
<blockquote>第三条:禁止使用属性隐式转换</blockquote>
<p>解读:SELECT uid FROM t_user WHERE phone=13812345678 会导致全表扫描,而不能命中phone索引,猜猜为什么?<br>int数据类型优先级高于archer, 该查询会把phone转换为int,因此需要把表中所有数据改成int,所以必须全盘扫描<br>phone是varchar类型,SQL语句带入的是整形,故不会命中索引,加个引号就好了:<br>SELECT uid FROM t_user WHERE phone='13812345678'</p>
<blockquote>第四条:禁止在WHERE条件的属性上使用函数或者表达式</blockquote>
<p>解读:SELECT uid FROM t_user WHERE from_unixtime(day)>='2017-02-15' 会导致全表扫描<br>正确的写法是:SELECT uid FROM t_user WHERE day>= unix_timestamp('2017-02-15 00:00:00')</p>
<blockquote>第五条:禁止大表使用JOIN查询,禁止大表使用子查询</blockquote>
<p>解读:会产生临时表,消耗较多内存与CPU,极大影响数据库性能,大表指的是数据量在1000万以上的表</p>
<blockquote>第六条:禁止使用OR条件,必须改为IN查询</blockquote>
<p>解读:旧版本Mysql的OR查询是不能命中索引的,即使能命中索引,为何要让数据库耗费更多的CPU帮助实施查询优化呢?</p>
<blockquote>第七条:禁止使用负向查询,以及%开头的模糊查询</blockquote>
<p>解读:<br>a) 负向查询条件:NOT、!=、<>、!<、!>、NOT IN、NOT LIKE等,会导致全表扫描<br>b) %开头的模糊查询,会导致全表扫描<br>一般来说,WHERE过滤条件不会只带这么一个“负向查询条件”,还会有其他过滤条件,举个例子:查询沈剑已完成订单之外的订单(好拗口):<br>SELECT oid FROM t_order WHERE uid=123 AND status != 1;<br>订单表5000w数据,但uid=123就会迅速的将数据量过滤到很少的级别(uid建立了索引),此时再接上一个负向的查询条件就无所谓了,扫描的行数本身就会很少<br>但如果要查询所有已完成订单之外的订单:<br>SELECT oid FROM t_order WHERE status != 1;<br>这就挂了,立马CPU100%,status索引会失效,负向查询导致全表扫描</p>
<blockquote>第八条:应用程序必须捕获SQL异常,并有相应处理</blockquote>
<p>解读:方便维护,及时“查漏补缺”</p>
<p><strong>总结:大数据量高并发的互联网业务,极大影响数据库性能的都不让用,不让用哟。</strong></p>
「文经课表」当日课表界面实现方法
https://segmentfault.com/a/1190000012653992
2017-12-31T14:49:27+08:00
2017-12-31T14:49:27+08:00
SangSir
https://segmentfault.com/u/sangsir
2
<h2>前言</h2>
<p>先简单介绍一下「文经课表」:基于微信小程序MINA框架的WXML、WXSS、JS为代码语言进行开发,视图层采用Flex弹性布局,逻辑层采用模块化模式开发。发布一周累计用户人数1000+,烟台大学文经学院、烟台大学文经学院学生会等官方微信公众号主动关联小程序,更多介绍:<a href="https://link.segmentfault.com/?enc=M8eMrV6Gog2U1bz6VcdWNQ%3D%3D.Jf20xP%2FzBD104pMWkQ2aH3t6tQhnpjtEhhB2aquUakM%3D" rel="nofollow"></a><a href="https://link.segmentfault.com/?enc=ZMyS6KXtWXaKGCHfGOdZbw%3D%3D.qxm6%2FEML5VY8rNkIPvrdHZShv6BKnYd8Dx64TCcPEpw%3D" rel="nofollow">https://lab.sangsir.com/kb/</a>。<br><img src="/img/remote/1460000012653997" alt="today-timetable" title="today-timetable"><br>为什么要单独说这个界面的实现方法,其实这与课表数据是分不开的。好,装逼完成,开始说一下当日课表界面的实现方法。</p>
<h2>分析</h2>
<p><img src="/img/remote/1460000012653998" alt="json" title="json"><br>先看一下我处理的课表数据,这是一个由上到下,由左到右进行的分组。每一大节课为1个数组,数组内包含8个数组,里面包含星期一到星期日的两小节的课程内容。嗯,有点绕,总之这样写有利于for循环出当日课表。<br>因此这样一个for循环出来之后的数据是无法使用css选择器<strong>直接控制</strong>格式,可以看一下直出后的效果。<br><img src="/img/remote/1460000012653999" alt="step1-1" title="step1-1"><img src="/img/remote/1460000012654000" alt="step1-2" title="step1-2"><br>所有内容都挤在了一行之中,那该怎么办?这样也未免太不注重用户体验了吧?每循环一次加一个<code><br></code>总可以了吧?不不不,前言中说了,微信小程序中的代码语言为WXML、WXSS、JS,意味着这并不是一个HTML页面,<code><br></code>标签并不存在。</p>
<h2>解决</h2>
<p>既然如此,先看一下输出规律。每一大节课包含8个数组,数组内包含两小节的课程内容,第一行的课程内容为课题,那么就简单了!可以每隔4个数组将显示出的标题加一个bold属性进行突出显示。</p>
<pre><code class="html"><block wx:if="{{i[index][k]!==null}}">
<text class="weui-media-box__Bold" wx:if="{{index % 4 == 0}}">
{{i[index][k]}}\n
</text>
<text wx:else>
{{i[index][k]}}\n
</text>
</block></code></pre>
<p>因为有了<code>{{index % 4 == 0}}</code>的每隔四行加上bold属性与<code><text></code>中的<code>\n</code>换行符,便能将课题和其他内容区分开来,实现标题突出显示的功能,看下图效果。<br><img src="/img/remote/1460000012654001" alt="step2" title="step2"></p>
<h2>优化</h2>
<p>emmm...不错,但总感觉看起来找不到关键信息?或者关键信息有些少?我们看当日课表要看的是什么来着?第几节课+上什么课+上课地点,对吧!<br>第几节课用符合小程序开发的主题色高亮显示了,上什么课也用加粗标注出来了,那么地点在标题下面看起来感觉好累啊!因为人眼已经将目光直接投射在了你所要关注的点上面了,这些关键点都已经用不同的方式凸显出来方便一眼看到,然而上课地点并没有安排在合适的地方一眼看到,毕竟这也是所要看到的关键信息之一,因此需要把它也凸显一下,我们把它放到右边如何?<br><img src="/img/remote/1460000012654002" alt="step4-1" title="step4-1"><br>用开发者工具将这一段加上<code>float: right</code>,嗯,不错,这样效果就好多了,突出但不喧宾夺主,符合用户体验。那么……该怎么实现?聪明的你一定会想到刚刚提到的每隔N行加一个css属性,不过多个if可不是好现象,小程序设计指南中可是指出小程序要<strong>“减少等待,反馈及时”</strong>,既然我们的大标题已经有了bold属性,大标题的下一行就是上课地点,那能不能在css中动一下手脚?<br>在翻css手册时我便看到了一个实现方法:<a href="https://link.segmentfault.com/?enc=pqyfN6YPXtsqGzK37ZBRSA%3D%3D.PfjdXQDoqQ47Hpd%2Bi1r6uRguKqUoa7Aua%2BqTRZN0lIp%2FCNmPkV39DPvDL5zNOrsn7LW5Wt99vsq5YNKixJpbIKD1zD253bG%2BtBwvIw5VGiI%3D" rel="nofollow">CSS 相邻兄弟选择器</a><br><img src="/img/remote/1460000012654003" alt="step4-2" title="step4-2"><br>怎么说?是不是很有趣?只能说我需要把前端方面的手册发送到kindle啃上几遍。<br>ok,有了这个<strong>相邻兄弟选择器</strong>那就简单多了,完成之后的效果图则是前言中的附图了。</p>
<h2>总结</h2>
<p>一入前端深似海,此时不啃基础何时啃,文章干货不多,更多的是思路,希望以后多挖几个坑提升一下自己的技术。<br><a href="https://link.segmentfault.com/?enc=nRhjmTQLiGALNw%2BqMPCOmw%3D%3D.NcogSN%2F2V2zGtnC3w0sZbSXBNjAtS79z1S0uqsGQDEIeTNIn7VWwDskZr%2FBZMB1Z" rel="nofollow"><img src="/img/remote/1460000012654004" alt="WeApp-timeTable" title="WeApp-timeTable"></a></p>