2020 步入工作的第一年,有很多不懂的地方,一开始不懂的很多,经常看一下同事的代码思考怎么写,基本上有点照抄模式;做不一样的部分,自己就会写的有点复杂化和低复用,当然慢慢写着也有点小领悟。在工作的过程中遇到了大大小小的问题,大多数的问题最后都得到了解决,我都把这些点都记起来了,在这里做一个总结。
小程序
1.微信小程序的wx.request()的PUT方法请求,后端接收不到任何数据
由于接触小程序不深,写wx.request()还是遇到了一些问题的就是关于请求的header的content-type的值。 官方文档是这样写,但是我遇到了另一种情况,就是请求PUT的时候,后端一直和我说,他收不到任何我前端传送过去的数据data,其实我看到network已经请求成功的,由于小白问了,他也是说真的没收到,这样就尴尬了,我也不太懂后端。
data 参数说明
最终发送给服务器的数据是 String 类型,如果传入的 data 不是 String 类型,会被转换成 String 。转换规则如下:
对于 GET 方法的数据,会将数据转换成 query string(encodeURIComponent(k)=encodeURIComponent(v)&encodeURIComponent(k)=encodeURIComponent(v)...)
对于 POST 方法且 header['content-type'] 为 application/json 的数据,会对数据进行 JSON 序列化
对于 POST 方法且 header['content-type'] 为 application/x-www-form-urlencoded 的数据,会将数据转换成 query string (encodeURIComponent(k)=encodeURIComponent(v)&encodeURIComponent(k)=encodeURIComponent(v)...)
本来我一直用的是一个封装好的request请求方法,但是PUT方法的接口对接不成功,后来我就只一直查文档,官方文档还是没提到这个问题,只提到了POST, 最后只能随便试试了,我把header['content-type'] 为 application/json换成了header['content-type'] 为 application/x-www-form-urlencoded. 这只是简化版,逻辑并不严密,使用的时候还是要逻辑严密点。这里这个问题就这样解决了,但是问题我也不知道是不是真的是前端问题,有清楚的XDM可以评论指点一下。
// data: {
// isPass: "0",// 通过1,驳回0
// Id: this.data.id,
// remark: this.data.inputValueNo
// },
// method : "PUT"
let link = 'http://**.**.***.***:8081';
http(url, method, params) {
let data = { ...params.data }
wx.request({
url: link + url,
method: method,
data,
header: {
'content-type': 'application/x-www-form-urlencoded',
'Authorization': token
},
success(res) {
params.success && params.success(res.data)
},
fail(err) {
params.fail && params.fail(err)
}
})
}
2.微信小程序调用指纹验证
这个是简单的本地验证,是调用设备的指纹接口。官方提供了三个接口文档,
检查当前设备是否支持生物识别 wx.checkIsSupportSoterAuthentication,
获取设备内是否录入如指纹等生物信息的接口 wx.checkIsSoterEnrolledInDevice,
开始 SOTER 生物认证 wx.startSoterAuthentication
这个指纹验证只是适用简单的安全的验证,因为设备本地的,假如客户端被破解,就GG。想要安全性高的,还是要把获取的到的生物信息返回给小程序后台,进一步验证,我只是一个小白前端,后端不懂,就不写怎么进一步验证了了。但是这个验证已经在大部分场景适用了,只要不是金融关于钱交易的场景应用,都没有什么问题的,可以方便了不用在输入密码二次验证
checkedFingerPrin: function() {
let _this = this;
if (wx.canIUse('checkIsSupportSoterAuthentication')) {
// 获取本机支持的 SOTER 生物认证方式
wx.checkIsSupportSoterAuthentication({
success(res) {
// res.supportMode : ['fingerPrint', 'facial'] 支持指纹识别和人脸识别
if(res.supportMode.indexOf("fingerPrint") > -1 ){
wx.checkIsSoterEnrolledInDevice({
checkAuthMode: 'fingerPrint',
success(res) {
console.log(res.isEnrolled);// boolean 是否已录入信息
// 开始 SOTER 生物认证
wx.startSoterAuthentication({
requestAuthModes: ['fingerPrint'],
challenge: "123456",
authContent: '请用指纹解锁',
success(res) {
// res 中包含授权数据,需要进一步验证正确性
console.log('指纹解锁', res);
_this.getInfo();//验证成功,获取****(自己小程序)信息
},
fail(res){
console.log('用户取消了指纹识别,或调用出现错误');
_this.getCaptchaImage();
}
})
}
})
}else{
console.log('当前设备不支持指纹识别')
}
}
})
} else {
console.log("当前设备不支持指纹识别")
}
},
3.小程序的过滤器怎么写
第一,在小程序目录下新建这样的目录,已有就不用新建了,dict.wxs、、toThousandFilter.wxs就是我们需要的过滤器,这个过滤器制作我还不是很熟悉,所以我把它们一个方法一个文件的分开建立。以toThousandFilter.wxs为例:
第二,在toThousandFilter.wxs中,用js实现过滤方法,这个方法内容在PC部分的《vue金额的格式化----过滤器》中,就不粘贴了。这个很重要啊:WXS文件es6语法不能使用
var bill = {
toThousandFilter: function(val) {
// 因为不能用es6 所以第一行改成这样
var reg = getRegExp('/\-|\,/','g');
val = ((+val || 0) / 100).toString().replace(reg, '');
// 。。。
// 在PC部分的《vue金额的格式化----过滤器》中
}
}
module.exports = {
toThousandFilter: bill.toThousandFilter
}
第三,使用
在业务页面wxml中引用wxs,然后使用filter
<view class="feeNumb">¥
<wxs module="bill" src="../../../utils/filter/toThousandFilter.wxs"></wxs>
<text>{{bill.toThousandFilter(item.fee) || ''}}</text>
</view>
4.微信小程序设置open-data的样式
open-data组件是微信小程序的默认授权展示用户信息的组件。但是它的样式固定的,然而需求是要圆的,一开始以为很简单,改个样式圆角就好,然后发现这个加class不行,我还以为我编译器出问题了,试了很多次都是改变不了样式,只能另辟蹊径,于是想着我在这个组件上层加多两个view改一下样式覆盖,居然这样样式又成功了。我就奇怪了,为啥这个元素不能改样式宽高不能改圆边框?突然想起行内元素就是这样的,然后我去一查发现设置了display:inline,是没有办法设置宽高的,所以只要把 open-data 的display设置为 inline-block 或 block 后才能设置它的宽高,然后就可以随便改了,但是在这里说一嘴,微信这样做可能是为了尽最大可能去兼容不一样的open-data类型type的,还是不要整体改变,css有一个属性选择器,
open-data[type="userAvatarUrl"] {
display: block;
overflow: hidden;
}
PC
1.Vue跳转页面打开新窗口
这个就用到了$router.push,本来是这样写得this.$router.push({ path: '/home' }),查了一下vue好像没有给定一个参数去打开新页面,而打开新网站都可以,但是都是在这个当前窗口操作更换url,后面思考发现想要打开新的页面其实是在浏览器上操作的,然后一查发现了window.open,对js理解不深,基本只在面试的时候看了一边红宝书,这个在2021年要主攻的地方,所以就可以这样写了:
let route = this.$router.resolve({ path: '/home' });
window.open(route.href, '_blank');
2.获取url中的参数
有时候url中是带参数的,我们需要用他的值来做一些判断,但是又没有用框架的时候就需要自己去截取url了。 例如:url:http://localhost:8080/index.html?id=965&date=1024&name=chenxuyuan
function getURLParam(paramName)
{
//构造一个含有目标参数的正则表达式的对象
var reg = new RegExp("(^|&)" + paramName + "=([^&]*)(&|$)");
//匹配目标参数
var url = window.location.search.substr(1).match(reg);
//返回参数值
if(url != null)
return unescape(url[2]);
return null;
}
var type = getURLParam(name); // chenxuyuan
3.vue的@click.native 原生点击事件、阻止默认事件和冒泡
原生点击事件
给vue组件绑定事件时候,必须加上native ,不然不会生效(监听根元素的原生事件,使用 .native 修饰符)
等同于在自组件中:子组件内部处理click事件然后向外发送click事件:$emit("click".fn)
//子组件照常写,不作任何事件绑定,删掉methods
<svg :class="svgClass" aria-hidden="true">
<use :xlink:href="iconName"></use>
</svg>
//父组件
<svg-icon icon-class="user" @click.native="svgClick"></svg-icon>
阻止默认事件和冒泡
在事件处理程序中调用 event.preventDefault() 或 event.stopPropagation() 是非常常见的需求。尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。
这个是在vue的官网看到的,很有道理,至于这几个的使用去看文档,很具体了
4.vue-cli3打包去掉console.log
通过npm包 terser-webpack-plugin 来实现
第一步:安装
npm install terser-webpack-plugin --save-dev
第二步:配置 (vue.config.js)
module.export = {
configureWebpack: (config)=>{
if(process.env.NODE_ENV === 'production'){
config.optimization.minimizer[0].options.terserOptions.compress = {
// warnings: false,// 移除警告
// drop_debugger: true,// 发布时去除debugger
drop_console: true,// 发布时去除console
dead_code: true,// 移除没被引用的代码
pure_funcs: ['console.log'],// 发布时不被打包的函数
}
}
}
}
5.vue实现checkbox点击选择控制element-ui table表单动态列展示与隐藏
这个有分开一个篇幅写文章链接, 类似这个iview的,功能点是一样的,但是风格不一样
6.js中的offsetWidth、clientWidth、scrollWidth
元素视图属性
-
offsetWidth 水平方向 width + 左右padding + 左右border-width
-
offsetHeight 垂直方向 height + 上下padding + 上下border-width
-
clientWidth 水平方向 width + 左右padding
-
clientHeight 垂直方向 height + 上下padding
-
offsetTop 获取当前元素到 定位父节点 的top方向的距离
-
offsetLeft 获取当前元素到 定位父节点 的left方向的距离
-
scrollWidth 元素内容真实的宽度,内容不超出盒子高度时为盒子的clientWidth
-
scrollHeight 元素内容真实的高度,内容不超出盒子高度时为盒子的clientHeight
Window视图属性(低版本IE浏览器[<IE9]不支持) 【自测包含滚动条,但网络教程都说不包含???】
- innerWidth 浏览器窗口可视区宽度(不包括浏览器控制台、菜单栏、工具栏)
- innerHeight 浏览器窗口可视区高度(不包括浏览器控制台、菜单栏、工具栏)
Document文档视图
(低版本IE的innerWidth、innerHeight的代替方案)
-
document.documentElement.clientWidth 浏览器窗口可视区宽度(不包括浏览器控制台、菜单栏、工具栏、滚动条)
-
document.documentElement.clientHeight 浏览器窗口可视区高度(不包括浏览器控制台、菜单栏、工具栏、滚动条)
-
document.documentElement.offsetHeight 获取整个文档的高度(包含body的margin)
-
document.body.offsetHeight 获取整个文档的高度(不包含body的margin)
-
document.documentElement.scrollTop 返回文档的滚动top方向的距离(当窗口发生滚动时值改变)
-
document.documentElement.scrollLeft 返回文档的滚动left方向的距离(当窗口发生滚动时值改变)
元素方法
-
getBoundingClientRect() 获取元素到body
- bottom: 元素底边(包括border)到可视区最顶部的距离
- left: 元素最左边(不包括border)到可视区最左边的距离
- right: 元素最右边(包括border)到可视区最左边的距离
- top: 元素顶边(不包括border)到可视区最顶部的距离
- height: 元素的offsetHeight
- width: 元素的offsetWidth
- x: 元素左上角的x坐标
- y: 元素左上角的y坐标
-
scrollIntoView() 让元素滚动到可视区
7.vue金额的格式化----过滤器
src\filters\index.js
(1).10000 => "10,000"
export function toThousandFilter(num) {
return (+num || 0).toString().replace(/^-?\d+/g, m => m.replace(/(?=(?!\b)(\d{3})+$)/g, ','))
}
(2).分转元并格式化1234567 => "12,345.67"
export function toThousandFilter1(val) {
val = ((+val || 0) / 100).toString().replace(/\$|\,/g, '')
if (isNaN(val)) {
val = '0'
}
let sign = (val == (val = Math.abs(val)))
val = Math.floor(val * 100 + 0.50000000001)
let cents = val % 100
val = Math.floor(val / 100).toString()
if (cents < 10) {
cents = '0' + cents
}
for (let i = 0; i < Math.floor((val.length - (1 + i)) / 3); i++) {
val = val.substring(0, val.length - (4 * i + 3)) + ',' + val.substring(val.length - (4 * i + 3))
}
return (((sign) ? '' : '-') + val + '.' + cents)
}
8.Vue判断用户首次进入页面还是浏览器刷新页面
在首次进入页面时我们给window.name设置一个固定值(noFirstEnterPage)
mounted(){
if(window.name == ""){
console.log("首次被加载");
window.name = "noFirstEnterPage";
} else if (window.name == "noFirstEnterPage") {
console.log("页面被刷新");
}
}