小程序节流函数

场景

小程序的页面添加跳转或者触发一个函数,发现在超过0.3s的连续点击中

小程序的机制会多次触发,尤其在使用navigateTo 进行跳转的时候

快速点击,发现会连续跳转,虽然不会对页面的栈造成堆积,如果你不使用wx.navigateBack

会造成返回多次现象

解决方式

可以使用throttle节流函数,进行封装一个小程序专有的函数

保证在可控时间内,这个函数的事件只能触发一次

1.首先在util.js创建节流函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function throttle(fn, gapTime) {
if (gapTime == null || gapTime == undefined) {
gapTime = 1500
}

let _lastTime = null

// 返回新的函数
return function () {
let _nowTime = + new Date()
if (_nowTime - _lastTime > gapTime || !_lastTime) {
fn.apply(this, arguments) //将this和参数传给原函数
_lastTime = _nowTime
}
}
}

记得要在 module.exports抛出函数

1
2
3
module.exports = {
throttle: throttle
}

2.在页面逻辑中使用

首先要引入util.js

1
const util = require('../../utils/util.js')

在需要使用的函数

1
2
3
4
5
checkBtn: util.throttle(function (e) {
wx.navigateTo({
url: '../X/X',
})
}, 3000),

函数中加入的3s为,从触发函数到3s在这个时间内,这个函数只能执行一次

这样就完美避开了,如何防止多次触发函数事件了

而且3s后这个函数事件恢复正常

js获取数据流的类型

图片数据流

如果你得到是一条数据流,如何获取到数据的type信息

1
2
3
4
var str = URL.split('.').join('/');
var index = str.lastIndexOf("\/");
str = str.substring(index + 1, str.length);
console.log(str)

小备注

js 获取字符串中最后一个斜杠前面的内容

1
2
3
var str = "/asdasf/asfaewf/agaegr/trer/rhh"; 
var index = str .lastIndexOf("\/");
str = str .substring(0, index+1);

js 获取字符串中最后一个斜杠后面的内容:

1
2
3
var str = "/asdasf/asfaewf/agaegr/trer/rhh"; 
var index = str .lastIndexOf("\/");
str = str .substring(index + 1, str .length);

angular/ng-change of select

ng-change 在select下第一次触发失效

因为需要动态注入select options的数据,同时保证注入完数据后,复填选择的数据

同时还对select添加了ng-change事件

结果发现,ng-change默认第一条数据无论怎么点击就是无效

有效状态是,除非点击其他的选项,再去点击第一条options,第一条数据才有效

经过排查,发现

1.这里的select是在弹窗中的

2.弹窗打开的时候先返回复填信息,然后再调用select注入信息的函数

3.注入信息后,才复填选择的数据

测试

在ng-change函数中,第一条数据无论怎么点击选择,就是不会console.log出所选择数据

复查,因为 ng-change 和 ng-model是组合使用,但是发现ng-model的数据页面竟然绑上了

修改

因为selcet注入信息的函数是在第三步的时候触发

突发奇想,觉得,进入页面就加载数据好了,干嘛非要在弹窗弹开的时候加载数据(我以前都是页面级加载数据)

然后就把函数提出来了

0.0 好了

后记

猜测可能是,异步加载的问题,造成,在获取信息,然后再载入select的数据,然后再填充的时候,因为请求时间关系,造成,ng-model的数据虽然传进去了,但是select的数据还没加载完
虽然看着,绑定数据是对的,但是 没有按照 调用函数的先后顺序来执行

小程序开发进程笔记分享

小程序本质基于vue,有相同的生命周期和事件处理

·1.小程序的页面跳转,非常重要,每个跳转方式代表不同的使用途径

1 switchTab 跳到有tab页面,并关闭其他没有tab的页面

2.redirectTo 关闭当前页,跳到应用内的某个页面

3.navigateTo 保留当前页,跳到应用中的某个页面,可以使用wx.navigateBack 返回上个页面,最多只能跳五个

4.reLaunch 跳转到指定页面,并关闭其他所有的页面(最好在返回首页的时候用)

交替使用跳转API可以达到很好的效果

·2.小程序自主插件 commpents ,这里介绍关于日期时间插件

https://github.com/Velg03961485/time-choose-plug-in-of-wechat-mini-app

·3.wxchart 一款纯js编写插件,使用相当方便 如果遇到问题,建议直接修改插件

https://github.com/Velg03961485/wx-charts

·4.小程序引用外部字体

1 如果没有ttf、eot、svg、woff 字体包,或者不对应,可以通过
https://www.fontconverter.org/ 这个网站进行转换一下

2 然后把得到的ttf 字体包(如果有这种字体包,就不用进行步骤1),在
https://transfonter.org/ 这个网站
“Add fonts” 上传字体包
选择 Base64 encode 为 on
勾选下面的所有选项 ,TTF WOFF SVG EOT WOFF2
点击 Convert ,生成新字体包,生成后会出现 Download
点击下载 ,这样你项目中需要用的字体就生成了

3 在小程序项目里 第一等级(和components,pages平级 ) 创建文件夹 fontStyle (自定义)
把刚才下载的文件里面的内容,全部粘贴复制到 这个fontStyle文件里面

4 在fontStyle文件夹下,创建一个新的 newFont.wxss 文件,在刚才复制的内容里面,找到stylesheet.css 打开,把里面的内容全部粘贴复制到 newFont.wxss中

5.在你要引用字体的wxss文件中,先引入字体 @import ‘../../fontStyle/newFont.wxss’;
在样式里面 font-family: ‘286-CAI978’;
这里要注意的是 引入字体的名称 ,可以直接在 newFont.wxss 中查看,如果想更改,可以把名字更改为自定义,记得要改完整

·6.小程序wxs过滤器 这里主要是提醒注意几点

1.不要使用let 声明对象,会报错 只能用var

2.不要使用new Date() 获取当前时间,同样会报错
可以使用getDate()获取当前时间

·7.使用节流函数,防止多次触发点击事件
当然你也可以使用布尔值通过切换来改变
这里的节流函数可以自主改变控制的时间长短

  1. 在utils 文件中 util.js 中

    // 函数节流限制测试
    function throttle(fn, gapTime) {
    if (gapTime == null || gapTime == undefined) {
    gapTime = 1500
    }

    let _lastTime = null

    // 返回新的函数
    return function () {
    let _nowTime = + new Date()
    if (_nowTime - _lastTime > gapTime || !_lastTime) {
    fn.apply(this, arguments) //将this和参数传给原函数
    _lastTime = _nowTime
    }
    }
    }

记得下面要在 module.exports 中抛出此函数

module.exports = {
throttle: throttle
}

  1. 在需要用到的js文件中,引入 js
    const util = require(‘../../utils/util.js’)

checkMemberBtn: util.throttle(function (e) , 3000),

微信公众号内嵌网页

搭建微信公众号,点击 实现链接跳转
这里给出一些常用的插件地址
1.基础设置,通过一个js来调整分辨率,适配不同的手机尺寸
https://github.com/Velg03961485/web-weixin

设计师给的750的图 通过1rem : 100px 来调整

2.时间选择插件(底部轮播滑动)
https://github.com/Velg03961485/phone-select-date

通过引入插件 在js中调用 时间选择对象来实现

3.提示框插件
https://github.com/Velg03961485/layer-of-phone-hint

通过引入外部js ,直接调用方法就能实现 页面弹框提醒
layer.msg(“”)

4.自定义选择
这个插件需要严格的数据格式要求,在传入数据的时候,最好重新组装一下数据结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$.ajax({ 
type: "POST",
url: "/web/depart/getChildrenStore",
success:function(data){

for(var i=0;i<data.length;i++){
parm.push({
'id':data[i].id,
'value':data[i].name
})
}
//门店选择
var weekdayArr=parm;
var mobileSelect1 = new MobileSelect({
trigger: '#storeModel',
title: '请选择',
wheels: [
{data: weekdayArr}
],
position:[0], //初始化定位 打开时默认选中的哪个 如果不填默认为0
transitionEnd:function(indexArr, data){
// console.log(data); }, callback:function(indexArr, data){ id=data[0].id; $('.select').css('color','black'); } }); }, error:function(data){

}
})

你也可以用这个插件来实现省市级县 联动

5.缓加载demo

https://github.com/Velg03961485/postpone-load-demo

$(‘body’).mLoading(“show”) 加载demo显现

$(‘body’).mLoading(“hide”) 加载demo隐藏

input 解析

input 是最常用的前端标签,今天就要从它的样式,规范,兼容来详细的解析如何使用
input 给你带来不一样的效果

1.input样式优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.input{
border: 1px solid #ccc;
padding: 7px 0px;
border-radius: 3px;
padding-left:5px;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
-webkit-transition: border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;
-o-transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s;
transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s
}
.input:focus{
border-color: #66afe9;
outline: 0;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);
box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)
}

2.input 的type类型有 number,text,button,checkbox,file,hidden,image
password,radio,reset,submit
同时,根据input不同的类型,来配合使用它的属性,实现不同的效果

当为type=’number’ IE火狐下会出现,后缀上下调数值按钮
可以使用以下样式去除

1
2
3
4
5
.input::-webkit-outer-spin-button,
.input::-webkit-inner-spin-button{
-webkit-appearance: none !important;
margin: 0;
}

3.input 设置后缀或者前缀

1
2
3
<div class="col-md-8 yuan">
<input type="number" step="0.00001" class="form-control" ng-model="OldList.originalPrice"/>
</div>

后缀名 为元 ,通过样式调整

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.yuan{
position: relative;
}
.yuan:after{
content:'元';
display: inline-block;
z-index:2;
position: absolute;
top:8px;
right:24px;
width:16px;
height:16px;
color:gray;
}

同时也可以通过前缀设置动画图标等 效果

4.vue中通过动态类名设置禁止输入

1
:class="{disabled: !this.canClick}"

1
2
3
4
5
6
.disabled{
background-color: #ddd;
border-color: #ddd;
color:#57a3f3;
cursor: not-allowed; // 鼠标变化
}

URl 取值传值

JQuery下
动态生成的数据 onclick 函数下面 传两个动态的值给函数
结果报错 一个值为 is not defined ,开发者查询页面 在函数里面两个值是存在的

1
2
3
4
for (var i = 0;i < Data.length ;i++){
html = '<div class="guarant"> <div class="guarantBalck"><div class="guarantInfo"><p class="infoTime">维修日期:'+ Common.changemsTodate(Data[i].addtime) + '</p><p class="infoPart">'+ Data[i].beginDepartment +'</p></div><div class="guarantForm"><p class="infoName">商品名称:'+ Data[i].goodsName +'</p><p class="glyphicon glyphicon-chevron-right infoMark"></p></div></div><div class="btn" onclick="postCheck('+ Data[i].id+','+ Data[i].goodsName +')">查看进度</div></div>';
$('.guaranteeBox').append(html);
}

经排查传入的值是需要用转义字符来转义一次的
于是把函数修改为

1
onclick="postCheck(\''+ Data[i].id+','+ Data[i].goodsName +'\')"

这样postCheck 传值就成功了,但是还有问题
输出的值 为一个参数,用逗号隔开
这样还是不符合要求
再次修改

1
onclick="postCheck('+ Data[i].id+',\''+ Data[i].goodsName +'\')"

这样两个值就能传值成功了

1
$(window).attr('location',"/web/certification/miantenanceRecordDetail?id="+ id +"&&name="+ name +"");

传到另一个页面,分别获取两个值

1
2
var id = window.location.href.split('?')[1].split('=')[1].split('&&')[0];
var name = window.location.href.split('&&')[1].split('=')[1].split('#')[0];

输出id正确,但是name,因为传值为中文,取到的值乱码

what a fuck!
意外总是意想不到,老司机开始发车,js 带有转码解析函数
一共有三种,总有一款适合你

  1. escape 和 unescape
    介绍:是对ASCII字母、数字、标点符号@*_+-./以外的其他字符进行编码
    escape 编码
    1
    console.log(escape('懵可乐'));  %u61F5%u53EF%u4E50

unescape 解码

1
console.log(unescape('%u61F5%u53EF%u4E50'));   懵可乐

2.encodeURI 和 decodeURI
介绍:返回编码为有效的统一资源标识符(URL)的字符串,不会被编码的字符!@#$&*()=:/;?=’ encodeURI 是js中真正用来对URL进行编码的函数
encodeURI 编码

1
2
console.log(encodeURI('https://velg03961485.github.io'));  https://velg03961485.github.io
console.log(encodeURI('%u61F5%u53EF%u4E50')); 懵可乐

decodeURI 解码

1
2
3
4
console.log(decodeURI('https://velg03961485.github.io'));  https://velg03961485.github.io
console.log(decodeURI('%u61F5%u53EF%u4E50')); 报错
Uncaught URIError: URI malformed
at decodeURI

当编码的URL不是真正的URL,会报错此编译为malformed(畸形的地址)
3.encodeURIComponent 和 decodeURIComponent
介绍:对URL的组成部分进行个别编码,而不是对于整个URL进行编码
encodeURIComponent 编码

1
2
console.log(encodeURIComponent('%u61F5%u53EF%u4E50'));  %25u61F5%25u53EF%25u4E50
console.log(encodeURIComponent('https://velg03961485.github.io')); https%3A%2F%2Fvelg03961485.github.io

decodeURIComponent 解码

1
2
3
4
5
console.log(decodeURIComponent('https://velg03961485.github.io'));  https://velg03961485.github.io
console.log(decodeURIComponent('https%3A%2F%2Fvelg03961485.github.io')); https://velg03961485.github.io
console.log(decodeURIComponent('%u61F5%u53EF%u4E50')); 报错
Uncaught URIError: URI malformed
at decodeURIComponent

Vue 小方法2

这里主要是记录一下使用Vue的小方法(element下)
1.默认勾选-2.保存的富文本过滤标签以及转化文本-3.登录监听-4.本地模拟编译-5.表格label如何居中

1.默认勾选
使用element的表格(带有勾选的),查看已经勾选状态,后台返回的数据
前端要有默认勾选的
element 有专用的默认勾选方法 toggleRowSelection
刚开始的时候在请求数据返回的之后,写上

1
this.$refs.table.toggleRowSelection(this.tableData3[this.$data.index],true);

报错 toggleRowSelection undfined
十分纳闷,element官网给的方法,为什么会报错找不到
一层一层打印输出
console.log(this.$refs)
console.log(this.$refs.table)
console.log(this.$refs.table.toggleRowSelection)
发现在this.$refs.table里面toggleRowSelection方法存在
但是一输出 this.$refs.table.toggleRowSelection 方法就找不到了
备注:这里 table 指向的是 el-table ref=”table” 不要自己定义了但是没有换

这种事情怎么会发生?上一级有下面函数就丢了

我的返回数据函数,是在 created函数里面调用的,一进页面就触发
突然想到了,是不是生命周期的问题,是在是新手对Vue的各种触发函数(生命周期)不熟
试了一下,不在数据返回后直接调取勾选,而采用间接调用

1
2
3
4
checked(){
//首先el-table添加ref="table"引用标识
this.$refs.table.toggleRowSelection(this.tableData3[this.$data.index],true);
},

methods 函数
然后在数据获取之后再调用 checked方法

1
2
3
this.$nextTick(function(){
this.checked();//每次更新了数据,触发这个函数即可。
})

完美解决问题

2.保存的富文本过滤标签以及转化文本

使用富文本添加数据,展现列表,会把content内容返回到列表里面
但是由于你编辑的内容过多,不能全部展现在列表里面,同时展现的时候,后台给你返回的数据是带有标签的(标签是不能让后台过滤的,存储的标签是你文档编辑的格式,后台是不能给你删除的)
为了方便一些,这里封装了一个过滤函数,在列表展现的时候,过滤标签和限制文本长度
其余部分以…显示
首先在 vue 的filter index.js 里面 创建过滤函数

1
2
3
4
5
6
//文本过滤长度以及标签 
export const fontFilter = (value,num) =>{
value = value.replace(/<[^>]+>/gim, '');
value = value.substr(0, num)
return value + ('...');
}

然后在 main.js里面 把函数设置为全局

1
Vue.filter('fonts',filters.fontFilter)

过滤的函数具体使用以及介绍,在前面的博客有

接着在列表里面

1
item.content | fonts(10)

这里传入的 10 是截取的文本长度

列表有了,查看和修改就少不了
修改还好,你只要把获取的数据重新填回富文本就好了(这里就显示出来后台不能删标签的作用了),文本编辑的样式会重现出来

但是查看,你不能还填回富文本里面吧
后台返回的是一串带标签的字符串,这怎么展示啊
使用div包裹数据,同时使用html编译,自动生成前端文本
这里element有自带的方法
v-html 太好用了,直接转化标签为文本模式,同时样式还保留着

1
<div v-html="checkForm.content">checkForm.content</div>

尤其一些富文本插件,上传的图片是base64的

3.监听登录

在input 监听enter键登录
原生标签下

1
<input placeholder="请输入密码" type="password" @keyup.enter="login">

element 下

1
<el-input type="password" v-model="loginInfo.password" auto-complete="off" @keyup.enter.native="login" placeholder="密码" />

监听在输入密码的input监听keyup事件,加enter修饰符。如果input是组件(element),要加上.native修饰符

同时在vue文档里面 对监听事件有详细的介绍:
在监听原生 DOM 事件时,方法以事件为唯一的参数。如果使用内联语句,语句可以访问一个 $event 属性:v-on:click=”handle(‘ok’, $event)”。

.stop - 调用 event.stopPropagation()。
.prevent - 调用 event.preventDefault()。
.capture - 添加事件侦听器时使用 capture 模式。
.self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
.{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。
.native - 监听组件根元素的原生事件。
.once - 只触发一次回调。
.left - (2.2.0) 只当点击鼠标左键时触发。
.right - (2.2.0) 只当点击鼠标右键时触发。
.middle - (2.2.0) 只当点击鼠标中键时触发。
.passive - (2.3.0) 以 { passive: true } 模式添加侦听器

4.本地模拟编译
vue npm run dev 运行项目的时候在开发模式是可以的

但是线上是需要编译的,前端为了模拟一下编译环境,是可以直接执行下面的方法的

首先,你要安装一个anywhere 这个会自动在你本地生成一个服务环境
当你运行编译的时候,能直接把项目启动起来

终端 npm install anywhere -g 安装anywhere
项目下 npm run build 编译完后项目会出现一个 dist文件夹
在文件内 执行命令 anywhere 就可以了

5.表格label如何居中

在使用element的模板的时候,el-table-column 标签里面的 是左对齐的
为了样式美化,都是居中的
这里不要想着覆盖样式,element有自带的 居中 align=”center”
如果这样

1
2
3
4
5
<el-table-column
label="编号" width="50" align="center"
>
<template slot-scope="scope">scope.row.customer_id </template>
</el-table-column>

那就在 el-table 定义style 居中就行了

点击粘贴复制文本

点击复制,可以复制选取的文本内容,并在手机的任何地方粘贴
这里是通过clipboard插件来实现的

插件地址:https://github.com/Velg03961485/copy

使用方式:

1
2
3
<td class="" style="line-height: 1.54rem"  >
<span class="copy" id="btn" data-clipboard-text="18667034901">复制</span>
</td>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//    粘贴复制事件
var copy = document.getElementsByClassName('copy');
var clipboard = new ClipboardJS(copy);

clipboard.on('success', function(e) {
console.log(e);
console.log(e.text);
layer.msg("复制成功");

});

clipboard.on('error', function(e) {
console.log(e);
});

介绍:
data-clipboard-text 是粘贴复制文本的传入值(你自己想复制的内容)
应该是动态生成的,你可以选着填入标签本身的内容,点击就是复制本身了

原生监听事件

clipboard 监听触发事件,是否成功