个人案例
- 纪录一个增加订阅次数的交互方案
普通小程序没有长期订阅消息,只能按照用户订阅次数发送订阅消息。如果订阅次数用完了怎么办呢? 可以让用户多点几次订阅,就可以做到了,但是这个操作对用户来说还是不太方便。怎样设计交互,让用户做起来不那么麻烦,是需要好好考虑的事情。 最近正好看到ReadHub的订阅方式,截图纪录一下。 [图片][图片][图片] 首先提醒用户,通知次数用完了,需要手动点击订阅,增加订阅次数。第一次会申请两个订阅,“每日早报提醒”和“订阅次数耗尽提醒”。用户点击允许以后,会发现可以接收的次数变成1了。 [图片][图片] 再次点击增加通知次数,从第二次开始,只申请一个“每日早报提醒”,每操作一次,订阅次数+1。点多了以后,嫌麻烦索性选中“总是保持以上选择,不再询问”,然后狂按增加订阅次数,会发现增加的次数并没有那么快,应该是每次订阅服务器端都要纪录一下才能展示出来,也就是说每次点击都落到数据库了。这样大概每秒1次,我点这21下也花了接近一分钟时间,不是一个可以忽略的操作。 更多参考: 云开发·多次订阅一次性订阅消息后定时发送
2021-03-08 - 熟练使用微信开发工具的代码块功能提升编码效率,降低误码率
1. 写在前面 自从上次介绍了宇宙第一强集成IDE的微信开发者工具安装插件等隐藏功能后,很多开发者社区哥们老铁感兴趣,一些哥们还私我问我是否支持代码块功能。答案是:支持!而且很完美的支持(此处必须有感恩,感恩微信团队每天的辛苦开发,作为同开发过小编辑器的人知道其中的苦与乐,同时呼吁各位猿少些喷喷喷的负能量,多些宣传和赞美的正能量!)。代码块是小编非常非常常用的一个功能,基本从04年开始建站和开发过程用过的所有IDE中都必备的功能。熟练使用微信开发工具的代码块功能提升编码效率,降低高频代码段的误写率。 2. 什么是代码块 可能有些刚接触开发的哥们不了解什么是「代码块」,这里我仅仅说说我个人对「代码块」功能的理解:代码块,英文名字:Code snippets,代码块的作用就是把比较长的一段代码在编码时只需要输入简写后的几个字母,比如把高频的代码console.log();简写成「clg」,再比如把小程序的页面.js里面的onLoad(),onShow等常用代码简写成「page_init」几个字母,最早提出这个概念和想法的人我也不知道是谁,总之得感谢他。如果说现在很多的编程语言有「语法糖」的说法,那么我个人觉得「代码块」可以称为「代码糖/编码糖」!熟练使用编码糖一定能让你尝到编码中的甜味。他的优点非常明显:极速,0误差输入高频代码段。个人觉得无论你现在处在编码的哪个级别都应该熟练使用Code snippets来提升工作效率。 3. 如何使用 3.1 打开开发者工具的编辑器扩展目录 [图片] 3.2 创建相关文件夹 返回上一级目录到User目下(里面有Workspaces文件夹),创建/进入snippets,此目录mac下完整路径应为:"~/Library/Application Support/微信开发者工具/【当前开发者工具特征码】/Default/Editor/User/snippets" [图片] 3.3 新建/编辑代码块json文件(如上图) [图片] 格式如上面,1,2,3是我比较常用的代码糖,生效后输入图1里面的clg回车就是console.log()(可以用这个来检测你代码糖功能是否生效);并且光标自动定位到()里,如下图: [图片][图片] 3.4 附带自用all.code-snippets 下面附上我常用的粗陋的代码糖块文件all.code-snippets(可以直接复制使用,你可以自行自己添加删除。里面有自己写的java框架常用的代码块,php常用和html常用以及nginx比较常用的,个人习惯不一样建议全部干掉重来,只需按里面的格式来写就可以了,格式如下: 字段名 意义 备注 prefix 简写后的字符串 必填 body 原字符串,可以用转义符 必填 description 备注 可控 [代码]{ // Example: // "Print to console": { // "scope": "javascript,typescript", // "prefix": "log", // "body": [ // "console.log('$0');", // "$2" // ], // "description": "Log output to console" // } //java begin "valueOf": { "prefix": "val", "body": "valueOf($0)", }, "parseInt": { "prefix": "par", "body": "Integer.parseInt($0);", }, "parseLong": { "prefix": "parl", "body": "Long.parseLong($0);", }, "equ": { "prefix": "equ", "body": "equals(\"$0\")", }, "isnull": { "prefix": "isnull", "body": "Tools.myIsNull($0)", }, "setattr": { "prefix": "setattr", "body": "request.setAttribute(\"$0\",$2)", }, "getattr": { "prefix": "getattr", "body": "request.getAttribute(\"$0\")", }, "getparam": { "prefix": "getparam", "body": "request.getParameter(\"$0\")", }, "getpost": { "prefix": "getpost", "body": "TtMap postUrl = Tools.getUrlParam();\r\nTtMap post = Tools.getpostmap(request, true);// 过滤参数,过滤mysql的注入,url参数注入\r\n" }, "tcf": { "prefix": "tcf", "body": "try{\r\n}catch(Exception e){\r\n\tTools.logError(e.getMessage());\r\n}finally{\r\n\t$0.closeConn();\r\n}", }, "777": { "prefix": "777", "body": "Runtime.getRuntime().exec(\"chmod 777 -R \" + strFileFullPath);" }, "go-1": { "prefix": "go-1", "body": "javascript:history.go(-1);" }, "dbctrl": { "prefix": "!dbctrl", "body": "DbCtrl dbCtrl = new DbCtrl(\"$0\");\r\ntry{\r\n\tTtList list = dbCtrl.lists(\"\", \"\");\r\n\tTtMap info = dbCtrl.info($2);\r\n}catch(Exception e){\r\n\tTools.logError(e.getMessage());\r\n\tif (Config.DEBUGMODE) {\r\n\t\te.printStackTrace();\r\n\t}\r\n}finally{\r\n\tdbCtrl.closeConn();\r\n}", "description": "TT-DbCtrl" }, "dbtools": { "prefix": "dbtools", "body": "DbTools dbTools = new DbTools();\r\ntry{\r\n\tTtList list = dbTools.reclist(\"$0\");\r\n\tTtMap info = dbTools.recinfo(\"$2\");\r\n}catch(Exception e){\r\n\tTools.logError(e.getMessage());\r\n}finally{\r\n\tdbTools.closeConn();\r\n}" }, "!recinfo": { "prefix": "rrecinfo", "body": "Tools.recinfo(\"$0\")", "description": "TT-DbTools-recinfo" }, "!reclist": { "prefix": "rreclist", "body": "Tools.reclist(\"$0\")", "description": "TT-DbTools-reclist" }, "ss": { "prefix": "ss", "body": "String[] sS = new String[]{}; ", "description": "new String[]" }, "mss": { "prefix": "mss", "body": "TtMap info = new HashMap<>();", "description": "new Map<String,String>" }, "lss": { "prefix": "lss", "body": "TtList lmss = new ArrayList<>();", "description": "new TtList " }, "<%": { "prefix": "!s", "body": "<%\r\n\t$0\r\n%>", "description": "TT-JSP<%自动完成" }, "<%=": { "prefix": "!ss", "body": "<%=$0%>", "description": "TT-JSP<%=自动完成" }, "jsp_include": { "prefix": "!sss", "body": "<jsp:include page=\"<%=$0%>\">\r\n\t<jsp:param name=\"$3\" value=\"$2\"/>\r\n</jsp:include>" }, "jsp_include2": { "prefix": "<jsp", "body": "<jsp:include page=\"<%=$0%>\">\r\n\t<jsp:param name=\"$3\" value=\"$2\"/>\r\n</jsp:include>" }, "!jsp_requery": { "prefix": "!req", "body": "request.getParameter(\"$0\")", }, "!jsp_requery_getAttribute": { "prefix": "!req2", "body": "request.getAttribute(\"$0\")", }, "!": { "prefix": "!ssss", "body": "<%@page import=\"com.tt.tool\"%>\r\n<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\"%>\r\n<%@ taglib prefix=\"c\" uri=\"http://java.sun.com/jsp/jstl/core\"%>\r\n<%@ taglib prefix=\"fmt\" uri=\"http://java.sun.com/jsp/jstl/fmt\"%>\r\n<%@ taglib uri=\"http://java.sun.com/jsp/jstl/functions\" prefix=\"fn\"%>\r\n<!DOCTYPE html>\r\n<html lang=\"en\">\r\n<head>\r\n <meta charset=\"UTF-8\">\r\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n <meta http-equiv=\"X-UA-Compatible\" content=\"ie=edge\">\r\n <title>$0</title>\r\n</head>\r\n<body>\r\n\t$2\r\n</body>\r\n</html>", "description": "jsp-header" }, "div": { "prefix": "<div", "body": "<div id=\"$0\" name=\"$0\">\r\n\t\r\n</div>", }, "p": { "prefix": "<p", "body": "<p id=\"\" name=\"\"></p>", }, "a": { "prefix": "<a", "body": "<a href=\"$0\" id=\"\" name=\"\">$2</a>", }, "head": { "prefix": "<head", "body": "<head>\r\n\t$0\r\n</head>", }, "img": { "prefix": "<img", "body": "<img id=\"\" name=\"\" src=\"$0\">" }, "ul": { "prefix": "<ul", "body": "<ul id=\"\" name=\"\">\r\n\t\r\n</ul>" }, "li": { "prefix": "<li", "body": "<li id=\"\" name=\"\">\r\n\t\r\n</li>" }, "select": { "prefix": "<select", "body": "<select id=\"\" name=\"\">\r\n\t\r\n</select>" }, "option": { "prefix": "<option>", "body": "<option value=\"\">$0</option>" }, "input": { "prefix": "<input", "body": "<input type=\"$0\" id=\"$2\" name=\"$2\" value=\"$3\">" }, "form": { "prefix": "<form", "body": "<form id=\"info_form\" action=\"$${posturl}\" class=\"form-horizontal\" method=\"post\" enctype=\"multipart/form-data\">\r\n\t$2\r\n</form>" }, "!i": { "prefix": "!i", "body": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\"%>\r\n<%@ page import=\"com.tt.tool.Tools\" %>\r\n<%@ page import=\"com.tt.data.TtMap\" %>\r\n<%@ page import=\"com.tt.data.TtList\" %>\r\n<%@ page import=\"com.tt.tool.JspTools\" %>\r\n<%@ page import=\"java.util.*\" %>\r\n<%@ taglib prefix=\"c\" uri=\"http://java.sun.com/jsp/jstl/core\"%>\r\n<%@ taglib prefix=\"fmt\" uri=\"http://java.sun.com/jsp/jstl/fmt\"%>\r\n<%@ taglib uri=\"http://java.sun.com/jsp/jstl/functions\" prefix=\"fn\"%>\r\n<%@ taglib prefix=\"Tools\" uri=\"/tld/manager\" %>\r\n", }, "loginfo": { "prefix": "loginfo", "body": "Tools.logInfo($0)", "description": "loginfo" }, "logerror": { "prefix": "logerror", "body": "Tools.logError($0)", "description": "loginfo" }, //javascript "!go-1": { "prefix": "!go-1", "body": "javascript:history.go(-1);", }, "!tag": { "prefix": "!tag", "body": "<%@ taglib prefix=\"c\" uri=\"http://java.sun.com/jsp/jstl/core\"%>\r\n<%@ taglib prefix=\"fmt\" uri=\"http://java.sun.com/jsp/jstl/fmt\"%>\r\n<%@ taglib uri=\"http://java.sun.com/jsp/jstl/functions\" prefix=\"fn\"%>\r\n<%@ taglib prefix=\"Tools\" uri=\"/tld/manager\" %>", }, "$$": { "prefix": "$$", "body": "$(function(){$0\r\n});", "description": "TT-jquery自动运行" }, "$(": { "prefix": "$f", "body": [ "$(function(){", "});" ], "description": "TT-jquery自动运行" }, "timer": { "prefix": "timer", "body": "inv = setInterval(\"$0showtimes();\",1000);", "description": "TT-JS每隔几秒自动运行", }, "!posturl": { "prefix": "!posturl", "body": "<%=Tools.urlKill(\"id$0\")%>", }, "!ifdebug": { "prefix": "ifd", "body": [ "if (Config.DEBUGMODE) {", "\te.printStackTrace();", "}" ], }, "reload":{ "prefix": "reload", "body": "location.reload(true);" }, //PHP "<?php": { "prefix": "php", "body": "<?php $0 ?>", "description": "Global-PHP插入标签" }, "nav":{ "prefix": "nav", "body": "<navigator url=\"car_yy/car_yy_ppuser/car_yy_ppuser\">", "description": "老子的微信小程序的跳转", }, "bind":{ "prefix": "bind", "body": "bindtap=\"$1\"", "description": "老子的bindtap" }, "wx_ra":{ "prefix": "wepy_ra", "body":"let result = await util.wxRequest(httpSet);", "description": "微信小程序阻塞等待请求" }, "wx_r":{ "prefix": "wepy_r", "body":["util.wxRequest(httpSet).then(function(result){\r\n\tif(result.result==\"success\"){$1\r\n\t}\r\n});"], "description": "微信小程序阻塞等待请求" }, "httpset":{ "prefix": "wepy_hs", "body": "let params= {};\r\nlet httpSet={\r\n\turl:'$1',\r\n\tparams:params,\r\n\tmethod:'GET',\r\n\tisShowLoading: false,\r\n}", "description": "httpSet" }, "wepy_global":{ "prefix": "wepy_global", "body": "wepy.$$instance.globalData.$1", }, "wepy_castfail":{ "prefix": "wepy_castfail", "body": "this.$$broadcast('alertHeaderWarning', '$1');" }, "wepy_castOK":{ "prefix": "wepy_castok", "body": "this.$$broadcast('alertHeader', '$1');" }, "wepy_castfail_height":{ "prefix": "wepy_castfailh", "body": "this.$$broadcast('alertHeaderWarningHeight', '$1',60);" }, "wepy_castOK_height":{ "prefix": "wepy_castokh", "body": "this.$$broadcast('alertHeaderHeight', '$1',60);" }, "clg": { "prefix": "clg", "body": "console.log($0);" }, "wepy_tt":{ "prefix": "wepy_tt", "body": "let that = this;" }, "wepy_currtarget":{ "prefix": "wepy_currt", "body": " e.currentTarget.dataset.$1", }, "wepy_gourl":{ "prefix":"wepy_gourl", "body":"@tap=\"goUrl\" data-url=\"$1\" data-memberflag=\"$2\"", }, "wepy_goback":{ "prefix": "wepy_goback", "body":"wepy.navigateBack();" }, "wepy_urlencode":{ "prefix": "wepy_urlencode", "body": "encodeURIComponent($1);" }, "wepy_urldecode":{ "prefix": "wepy_urldecode", "body": "decodeURIComponent($1);" }, "wepy_noimg":{ "prefix": "wepy_noimg", "body": "/images/imgload.png", }, "wepy_errmsg":{ "prefix": "wepy_errmsg", "body": "(result && result.errorMsg) ? result.errorMsg :\"删除失败!\"", }, "wepy_sets":{ "prefix": "wepy_sets", "body": "wepy.setStorageSync($1,$2);" }, "wepy_gets":{ "prefix": "wepy_gets", "body": "wepy.getStorageSync($1);" } } [代码] 4. 相关链接 持续更新:收藏整理官方隐藏的小程序功能/参数/方法/API 动手打造更强更好用的微信开发者工具-编辑器扩展篇 点击wxml里面的绑定事件/变量名/样式名直接跳转到对应文件代码 小程序编码时变量名中文转英文变量名工具,各种驼峰取名 微信开发者工具编辑器支持「书签」功能,快速跳转到指定文件指定行和列 愉快的编写和调试Java:体验新版开发者工具的编辑器扩展功能 5. 其他未公布的隐藏功能 当你觉得有用的时候,就点赞和收藏或者分享,觉得没用的话就投诉,不管点赞还是投诉后的码农写代码永无BUG ,CP设计的产品人见人爱,BOSS每年收入翻番! ↓↓↓↓↓↓__________________________________________________________________________投诉的话点…↓↓↓
2020-05-17