2020年尾末问题总结
2020年尾末问题总结
- CSS的一个bug
- vue中markdown解析
- CSS-伪元素、定位和z-index的结合
- 浏览器 navigator.clipboard is undefined
- 微信自定义分享
- Js按A-Z排序通讯录)
- keep-alive 的使用
- 页面可见性API
- Vue采用CDN方式引入基础第三方库
- vue-cli3项目开启gzip压缩
1. CSS的一个bug
CSS的一个bug,由于语法过时,导致此部分内容不生效
Gradient has outdated direction syntax. New syntax is like to left
instead of right
.
background: linear-gradient(left, #FF9999 0%,#FF6F6F 100%);
background: linear-gradient(225deg, #FF9999 0%, #FF6F6F 100%);
2. vue中markdown解析
2.1 安装依赖
npm install hyperdown prismjs -D
2.2 新增 markdown-loader.js
const HyperDown = require('hyperdown');
const Prism = require('prismjs');
function markdownLoader(val) {
let parser = new HyperDown();
let html = parser.makeHtml(val);
html = html.replace(/(?<=<pre><code[^>]*?>)[\s\S]*?(?=<\/code><\/pre>)/gi, v => {
v = v.replace(/_&/g, ' ').replace(/"/g, '"').replace(/</g, '<').replace(/>/g, '>').replace(/&/g, '&');
return Prism.highlight(v, Prism.languages.javascript);
});
return (
`<template><div class="markdown">${html}</div></template>`
);
}
module.exports = markdownLoader;
2.3 使用
// vue-cli 3.x ,在vue.config.js添加以下配置
module.exports = {
configureWebpack: config => {
config.module.rules.push({
test: /\.md$/,
use: [
{
loader: 'vue-loader',
},
{
loader: require.resolve('./markdown-loader'),
},
],
},
);
},
};
// webpack.conf.base.js 里新增loader
在入口文件main.js导入prismjs样式
//
import 'prismjs/themes/prism.css';
3. CSS-伪元素、定位和z-index的结合
应用场景是元素盒子通过设置z-index来改变伪元素before, after与元素内容的层叠关系
<div class="ele">
aaaaaaaaaaaa
</div>
<style>
.ele {
position: relative;
width: 100px;
height: 100px;
background-color: red;
font-size: 20px;
z-index: 1;
}
.ele::before {
content: '';
background-color: yellow;
width: 100px;
height: 100px;
position: absolute;
top: 20px;
left: 20px;
z-index: -1;
}
</style>
如上图所示,元素层级只要设置z-index,其内伪类为-1也不会到最底层
4. 浏览器 navigator.clipboard is undefined
let clipboard = navigator.clipboard;
if (clipboard == undefined) {
// alert('clipboard is undefined');
} else {
navigator.clipboard.readText().then(clipText => {
this.pasteTxt = clipText
});
}
该API需要在安全网络下并且需要授权才可以使用,IE不支持
localhost或者https,127.0.0.1是本机域名是安全的,所以可以获取到clipboard,谷歌现在很多api都是必须要求https的情况的
4.1 在微信浏览器调用该API不会直接获取值,而是出现一个提示框包含粘贴和搜索(ios),还需要用户手动点击才可以赋值。
5. 微信自定义分享
记录写的两种方式,一种是跟后台取jsapi_token,一种是跟后台取已经写好的 wx.config 里全部内容
5.1 jsapi_token
import axios from 'axios'
import sha1 from 'hex-sha1'
import wx from 'weixin-js-sdk'
let url = window.location.href.split('#')[0];
let jsapi_ticket = '',
timestamp=0,
nonceStr,
string1,
signature,
wxTokenUrl= 'https://snailsleep.net/snail-confession/confession/get/token';
function base_objKeySort(arys) {
//先用Object内置类的keys方法获取要排序对象的属性名,再利用Array原型上的sort方法对获取的属性名进行排序,newkey是一个数组
let newkey = Object.keys(arys).sort();
//console.log('newkey='+newkey);
let newObj = {}; //创建一个新的对象,用于存放排好序的键值对
for (let i = 0; i < newkey.length; i++) {
//遍历newkey数组
newObj[newkey[i]] = arys[newkey[i]];
//向新创建的对象中按照排好的顺序依次增加键值对
}
return newObj; //返回排好序的新对象
}
function base_getNowTimeStamp() {
let time = new Date();
let timeStamp = Date.parse(new Date(time));
return timeStamp;
}
function base_randomWord(randomFlag, min, max) {
let str = "",
pos,
range = min,
arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
// 随机产生
if (randomFlag) {
range = Math.round(Math.random() * (max - min)) + min;
}
for (let i = 0; i < range; i++) {
pos = Math.round(Math.random() * (arr.length - 1));
str += arr[pos];
}
return str;
}
const wxShare = function () {
timestamp = base_getNowTimeStamp();
timestamp = String(timestamp).slice(0, 10);
timestamp = Number(timestamp);
nonceStr = base_randomWord(false, 16);
let paramsData = {
noncestr: nonceStr,
jsapi_ticket: jsapi_ticket,
timestamp: timestamp,
url: url,
}
let data = base_objKeySort(paramsData);
// console.log(data);
string1 = JSON.stringify(data);
let stringSignTemp = string1.substring(1, string1.length - 1);
stringSignTemp = stringSignTemp.replace(/"/g, "");
stringSignTemp = stringSignTemp.replace(/,/g, "&");
stringSignTemp = stringSignTemp.replace(/:/, "=");
stringSignTemp = stringSignTemp.replace(/:/, "=");
stringSignTemp = stringSignTemp.replace(/:/, "=");
stringSignTemp = stringSignTemp.replace(/:/, "=");
// console.log(stringSignTemp);
signature = sha1(stringSignTemp);
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: 'wxb71e95ab1ea7f54d', // 必填,公众号的唯一标识
timestamp: timestamp, // 必填,生成签名的时间戳
nonceStr: nonceStr, // 必填,生成签名的随机串
signature: signature, // 必填,签名
jsApiList: [
'onMenuShareTimeline',
'onMenuShareAppMessage',
], // 必填,需要使用的JS接口列表
});
wx.ready(function() {
// alert('微信成功');
// config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
wx.onMenuShareAppMessage({
title: '', // 分享标题
desc: '', // 分享描述
link: url, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: '', // 分享图标
type: '', // 分享类型,music、video或link,不填默认为link
dataUrl: '', // 如果nzbzpe是music或video,则要提供数据链接,默认为空
success: function() {
// 用户点击了分享后执行的回调函数
}
});
wx.onMenuShareTimeline({
title: '', // 分享标题
link: url, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: '', // 分享图标
success: function() {
// 用户点击了分享后执行的回调函数
},
});
});
wx.error(function(res) {
console.log(res)
// alert('微信失败')
// config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
});
}
export default {
install(Vue) {
// 获取微信token
Vue.prototype.getWxtoken=function() {
axios.get(wxTokenUrl)
.then(res => {
jsapi_ticket = res.data;
wxShare();
})
.catch(err => {
console.log(err);
});
}
Vue.prototype.base_isEquipment = function() {
const UA = navigator.userAgent,
isAndroid = /android|adr|linux/gi.test(UA),
isIOS = /iphone|ipod|ipad/gi.test(UA) && !isAndroid,
isBlackBerry = /BlackBerry/i.test(UA),
isWindowPhone = /IEMobile/i.test(UA),
isMobile = isAndroid || isIOS || isBlackBerry || isWindowPhone;
return {
isAndroid: isAndroid,
isIOS: isIOS,
isMobile: isMobile,
isWeixin: /MicroMessenger/gi.test(UA),
isQQ: /QQ/gi.test(UA),
isPC: !isMobile,
isWeibo: /WeiBo/gi.test(UA)
}
}
}
}
5.2 wx.config
axios({
url: `/api/weChat/jsApiSdkAuth`,
method: 'POST',
params: {
link: decodeURIComponent(location.href)
}
})
.then(({data}) => {
if (data.code === '1') {
wx.config({
debug: true,
appId: data.data.appId,
timestamp: data.data.timestamp,
nonceStr: data.data.nonceStr,
signature: data.data.signature,
jsApiList: [
'onMenuShareAppMessage', 'onMenuShareTimeline', 'updateAppMessageShareData', 'updateTimelineShareData'
],
})
wx.ready(() => {
let shareData = this.shareData
//兼容新老版本接口, 如不需要处理逻辑情况下, 调试好可以直接使用
if (wx.onMenuShareAppMessage) { //微信文档中提到这两个接口即将弃用,故判断
wx.onMenuShareAppMessage(shareData);//1.0 分享到朋友
wx.onMenuShareTimeline(shareData);//1.0分享到朋友圈
} else {
wx.updateAppMessageShareData(shareData);//1.4 分享到朋友
wx.updateTimelineShareData(shareData);//1.4分享到朋友圈
}
wx.error(function(res) {
console.log(res)
});
});
} else {
Toast(data.msg)
}
})
最本质的还是根据微信的坑爹文档来灵活应变。
坑1:我一直以为微信自定义分享也可以通过按钮来调起原生的分享……
坑2:自定义分享的link跟当前页面的链接不一致,签名的时候还需要签 location.herf,这个问题找了好久
大多数遇到情况下在 微信分享填坑指南 都能找到解决方案。
6. Js按A-Z排序通讯录
直接抄的轮子,作者说有Bug,也没时间去细细看,能满足需求
7. keep-alive 的使用
主要是用来实现类似 前进刷新后退不刷新 的功能,但写出来多多少少还是挺麻烦的,实际需求未能满足废除了,以后根据需求再次开发吧
8. 页面可见性API
配合粘贴板使用
document.addEventListener('visibilitychange', function () {
// 用户离开了当前页面
if (document.visibilityState === 'hidden') {
document.title = '页面不可见';
}
// 用户打开或回到页面
if (document.visibilityState === 'visible') {
document.title = '页面可见';
}
})
9. Vue采用CDN方式引入基础第三方库
Staticfile CDN 搜索开源库的cdn链接
9.1 public/index.html
<!DOCTYPE html>
<html lang="en">
.....
<body>
<!-- 引入组件库 -->
<script src="https://cdn.staticfile.org/vue/2.6.11/vue.min.js"></script>
<script src="https://cdn.staticfile.org/vuetify/2.2.20/vuetify.min.js"></script>
<script src="https://cdn.staticfile.org/vuex/3.1.3/vuex.min.js"></script>
<script src="https://cdn.staticfile.org/vue-router/3.1.3/vue-router.min.js"></script>
<script src="https://cdn.staticfile.org/axios/0.19.2/axios.min.js"></script>
</body>
</html>
9.2 main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import axios from 'axios'
import VueAxios from 'vue-axios'
import VueRouter from 'vue-router'
9.3 vue.config.js
module.exports = {
..., // 其他配置省略,主要是加一项externals
externals: {
'vue': 'Vue',
'vue-router': 'VueRouter',
'vuex': 'Vuex',
'axios': 'axios'
}
}
10. vue-cli3项目开启gzip压缩
const CompressionPlugin = require("compression-webpack-plugin");
moudle.export = {
configureWebpack: () => {
if (process.env.NODE_ENV === 'production') {
return {
plugins: [
new CompressionPlugin({
test: /\.js$|\.html$|\.css$|\.jpg$|\.jpeg$|\.png/,
threshold: 10240,
deleteOriginalAssets: false
})
]
}
}
}
}
10.1 Cannot read property 'tapPromise' of undefined
解决的方案是降级处理
yarn add compression-webpack-plugin@5.0.1