定位问题:
- 验证码生成的cookies,无法发送到登录接口
- 见下图
- 感叹号中会提示sameSite属性问题,
- 严格的 SameSite 属性意味着只能加载同一个网站的 cookies,宽松或缺省意味着可以加载跨站 cookies
解决方法:
- 打开chrome 输入chrome://flags/搜索 SameSite by default cookies
- 找到SameSite by default cookies和Cookies without SameSite must be secure
- 将上面两项设置为 Disable
devServer属性
- https属性设置为true
- 本地访问时,为https://localhost:8080
pluginOptions属性
pluginOptions: { 'style-resources-loader': { preProcessor: 'less', // 可改成scss patterns: [ path.resolve(__dirname, 'src/assets/styles/var.less'), path.resolve(__dirname, 'src/assets/styles/mixin.less') ] } }
- 提前加载后,每一个vue文件都可以直接使用var.less中的变量,及mixin.less里的mixin方法
chainWebpack属性
chainWebpack: config => { // webpack4.0以上,使用该方法 // 设置全局变量VUE_APP_CURRENTMODE,供axios跨域使用 config.plugin('define').tap(args => { // 执行参数:argv.deploy,即 --deploy=dev 操作 args[0]['process.env'].VUE_APP_CURRENTMODE = JSON.stringify(appConfig[argv.deploy].path) return args }) }
- appConfig = { dev: { path: ‘http://172.168.200.11:8015‘ } }
- package.json中,增加scripts命令
"serve:dev": "vue-cli-service serve --deploy=dev"
argv = require('yargs').argv
,argv.deploy取值为dev- axois中,
axios.defaults.baseURL = process.env.VUE_APP_CURRENTMODE
- 运行 npm run serve:dev,即可在请求接口时,直接请求dev环境的接口
- 除dev外,可添加各种环境的接口地址(如test,uat等),直接使用npm命令执行
需要给元素添加背景色
方法一:
ie9-10:background:rgba(255,255,255,0);
ie8:background:url(about:blank)(ie8不兼容rgba)
方法二:
设置元素背景色后设置透明度为0,(ie8:filter:alpha(opacity=0))
但是这种方式有个缺点,如果元素内有其他内容,其他内容透明度也会变成0
通过模拟生成其它标签实现placeholder效果
function placeholderSupport() {
return 'placeholder' in document.createElement('input');
}
function placeholderRender() {
//兼容ie9不支持placeholder标签
if (!placeholderSupport()) { // 判断浏览器是否支持 placeholder
function GetStringNumValue(pxstr) {
return pxstr.substring(0, pxstr.length - 2);
}
if ($('input[placeholder],textarea[placeholder]').parents('#formBuild-ie8').length) {
return false;
}
$('input[placeholder],textarea[placeholder]').each(function () {
var $element = $(this),
placeholder = $element.attr('placeholder');
if (placeholder) {
// 文本框ID
var elementId = $element.attr('id');
if (!elementId) {
var now = new Date();
elementId = 'lbl_placeholder' + now.getSeconds() + now.getMilliseconds();
$element.attr('id', elementId);
}
}
// 添加label标签,用于显示placeholder的值
var $label = $('<label>', {
html: $element.val() ? '' : placeholder,
'for': elementId,
css: {
position: 'absolute',
cursor: 'text',
color: '#ccc',
fontSize: $element.css('fontSize'),
fontFamily: $element.css('fontFamily'),
zIndex: 9,
}
}).insertAfter($element);
// 绑定事件
$label.addClass('ie-placeholder')
var _setPosition = function () {
$label.css({
top: '7px',
left: '30px',
});
};
var _resetPlaceholder = function () {
if ($element.val()) {
$label.html(null);
} else {
_setPosition();
$label.html(placeholder);
}
};
_setPosition();
$element.on('focus blur input keyup propertychange resetplaceholder', _resetPlaceholder);
/**
以下代码可省略,为了解决点击表单弹出复杂弹窗选中数据的问题,
问题:ie9中,点击input弹出复杂弹窗后选中数据赋值到input中,模拟出来的placeholder内容还存在,导致选中的数据和placeholder内容重叠
原因:ie9的propertychange在失去焦点后不会触发
解决:使用定时器来绑定了此方法!如果认为此方式耗性能,建议不要给该项添加placeholder属性
**/
if (isIE9 && $element.attr('readonly')){
$element.click(function(){
var intervalName;
intervalName = setInterval(function () {
$element.trigger("propertychange");
if ($element.val()){
clearInterval(intervalName);
}else{
}
},1000);
});
}
});
}
}
效果(ie8):
label为生成的模拟placeholder效果的标签。
上面css样式可根据项目需求自行设置。
如上面注释中存在的问题,ie9的propertychange在失去焦点后不会触发,面对类似注释中比较复杂特殊的交互,使用了这种比较耗性能的方式解决,或者可以不要给该项设置placeholder,有其他更好的解决方式可以一起讨论。
设置允许跨域 jQuery.support.cors = true 也不支持
原因:IE10+ 才支持withCredentials属性,IE9以下不支持,跨域对象只能用XDomainRequest对象,而jQuery并不兼容XDomainRequest。
解决:
方法一:设置ie浏览器配置,“工具->Internet 选项->安全->自定义级别”将“其他”选项中的“通过域访问数据源”选中为“启用”(不太现实,无法操控用户设置)
方法二:别跨域请求了,前端配个nginx转发代理吧。(目前的项目采用的这种方式)
方法三:插件 jQuery-ajaxTransport-XDomainRequest,这是一个基于 XDomainRequest 实现 jquery ajxa 的 jquery 插件,为了支持 IE8、9的cors
PS:这里只是说jquery的ajax请求,不包括XMLHttpRequest等。
但是………它兼容jquery的:nth-child()…………
emmmmmmmm……..
所以css文件中正常这么设置的样式
.index_bg .mainmenu li:nth-child(8n+1) {background-color:#36A1DB}
.index_bg .mainmenu li:nth-child(8n+2) {background-color:#678ce1}
.index_bg .mainmenu li:nth-child(8n+3) {background-color:#8c67df}
要兼容ie8的话,在js中:
if (isIE8) { //isIE8为项目中设置的一个全局变量
$('.index_bg .mainmenu li:nth-child(8n+1)').css('backgroundColor', '#36A1DB')
$('.index_bg .mainmenu li:nth-child(8n+2)').css('backgroundColor', '#678ce1')
$('.index_bg .mainmenu li:nth-child(8n+3)').css('backgroundColor', '#8c67df')
}
ie8也不兼容很多css3新属性,border-radius、box-shadow、background 背景渐变等,如果需求有这些,要么干掉需求,要么百度。
比如filter、forEach、map、Object.assign()、Object.keys()等等等等。。。
兼容:
//filter
if (!Array.prototype.filter) {
Array.prototype.filter = function (fun ) {
if (this === void 0 || this === null)
throw new TypeError();
var t = Object(this);
var len = t.length >>> 0;
if (typeof fun !== "function")
throw new TypeError();
var res = [];
var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
for (var i = 0; i < len; i++) {
if (i in t) {
var val = t[i];
if (fun.call(thisArg, val, i, t))
res.push(val);
}
}
return res;
};
}
//forEach
if (!Array.prototype.forEach) {
Array.prototype.forEach = function forEach(callback, thisArg) {
var T, k;
if (this == null) {
throw new TypeError("this is null or not defined");
}
var O = Object(this);
var len = O.length >>> 0;
if (typeof callback !== "function") {
throw new TypeError(callback + " is not a function");
}
if (arguments.length > 1) {
T = thisArg;
}
k = 0;
while (k < len) {
var kValue;
if (k in O) {
kValue = O[k];
callback.call(T, kValue, k, O);
}
k++;
}
};
}
//map
if (typeof Array.prototype.map != "function") {
Array.prototype.map = function (fn, context) {
var arr = [];
if (typeof fn === "function") {
for (var k = 0, length = this.length; k < length; k++) {
arr.push(fn.call(context, this[k], k, this));
}
}
return arr;
};
}
//Object.assign()
if (typeof Object.assign != 'function') {
Object.assign = function(target) {
'use strict';
if (target == null) {
throw new TypeError('Cannot convert undefined or null to object');
}
target = Object(target);
for (var index = 1; index < arguments.length; index++) {
var source = arguments[index];
if (source != null) {
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
}
return target;
};
}
//Object.keys()
var DONT_ENUM = "propertyIsEnumerable,isPrototypeOf,hasOwnProperty,toLocaleString,toString,valueOf,constructor".split(","),
hasOwn = ({}).hasOwnProperty;
for (var i in {
toString: 1
}) {
DONT_ENUM = false;
}
Object.keys = Object.keys || function (obj) {//ecma262v5 15.2.3.14
var result = [];
for (var key in obj) if (hasOwn.call(obj, key)) {
result.push(key);
}
if (DONT_ENUM && obj) {
for (var i = 0; key = DONT_ENUM[i++];) {
if (hasOwn.call(obj, key)) {
result.push(key);
}
}
}
return result;
};
都是从网上撸来的兼容方案。
百度文件respond.min.js,引入到用到的文件中的条件注释里
<!--[if IE 8]>
<script src="respond.min.js"></script>
<![endif]-->
注意:媒体查询在IE8里简写不生效。
实际上,a标签没有disabled属性
但是,如果a标签中添加disabled属性,在ie中a标签点击事件无效
(本来也没想到会给a标签添加disabled属性,奈何可爱的后端同事们自己写功能的时候以为disabled对所有标签有效就乱加,以至于发现了这个奇怪的现象。)
比较坑的一个问题,现在都是用的ie11仿真模式调试ie8浏览器,一般都是打开控制台调试,控制台关了之后仿真的ie8其实不准确,所以开发是没有关控制台,就没发现问题。
直到项目组用的时候发现了问题,就装了个虚拟机用真实ie8调试,发现某个功能有问题,f12开发者工具打开之后就正常了(也是测了很久才发现f12打开才正常)。
解决:删掉console.log(),IE8会将console.log()默认处理为错误逻辑,但是在F12下处理为控制台输出。
在H5中,不像微信小程序有自带的api,因此我们需要引入微信jssdk
在uni可以使用
npm install jweixin-module --save
var jweixin = require('utils/weixin-js-sdk')
wxshare(){
var that = this
uni.request({
url: this.$serve.qcloudUrl + "/lbyxWeChat/config/getConfig",
method: 'POST',
data: {
url: that.url
},
success(res) {
jweixin.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: res.data.data.appId, // 必填,公众号的唯一标识
timestamp: res.data.data.timestamp, // 必填,生成签名的时间戳
nonceStr: res.data.data.nonceStr, // 必填,生成签名的随机串
signature: res.data.data.signature,// 必填,签名
jsApiList: [
"checkJsApi",
'updateAppMessageShareData',
'updateTimelineShareData'
] // 分享到朋友圈和微信好友
});
jweixin.ready(function () {
//获取“分享给朋友”按钮点击状态及自定义分享内容接口
jweixin.updateAppMessageShareData({
title: getMessage(that.url).title || '裂变营销', // 分享标题
desc: getMessage(that.url).desc, // 分享描述
link: getMessage(that.url).link || that.url, // 分享链接
imgUrl: getMessage(that.url).imgUrl, // 分享图标
type: '', // 分享类型,music、video或link,不填默认为link
dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
success: function () {
console.log("设置成功")
}
})
//获取“分享到朋友圈”按钮点击状态及自定义分享内容接口
jweixin.updateTimelineShareData({
title: getMessage(that.url).title || '裂变营销', // 分享标题
link: getMessage(that.url).link || that.url, // 分享链接
imgUrl: getMessage(that.url).imgUrl, // 分享图标
type: '', // 分享类型,music、video或link,不填默认为link
dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
success: function () {
console.log("设置成功")
}
})
})
// that.$hideLoading()
that.tipsVisible = true
}
})
function getMessage(url) {
return {
title: that.shareData.title || '',
desc: that.shareData.desc || '',
imgUrl: that.shareData.imgUrl || '',
link: that.shareData.link || ''
}
}
}
在IOS中网页得URL不会随着路由得变化而改变,所以配置得URL 跟当前显示得URL不同
而Android中的URL会随着路由得变化而改变
当我们需要获取url做一些配置的时候,比如分享、支付,就会导致url不一致报错
解决:根据运行机型取值(如果有分享的话,建议在第一次进入时候保存url路径,做分享的时候,直接取,而非使用spilt方式)
var that = this
let os
uni.getSystemInfo({
success: function (res) {
os = res.platform
}
});
if(os == "ios"){
that.url = window.location.href.split("#")[0]
}else if(os == "android"){
that.url = window.location.href
}
延展:当我们重定向页面返回以后,会发现上述方法没有办法解决
解决:刷新当前页面
mounted () {
this.$nextTick(()=>{
//跳转至地图或者静默授权返回 IOS不兼容页面自动刷新问题
var u = navigator.userAgent,
app = navigator.appVersion;
var isAndroid = u.indexOf('Android') > -1; //android终端
var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
if(isiOS){
window.onpageshow = function(event) {
if (event.persisted) {
window.location.reload()
}
};
}
})
},
3.1、如果选用history模式会有个问题就是刷新当前页面会报错,hash模式不会
3.2 微信授权重定向页面如果是history模式,重定向页面正常,如果是hash模式,因为微信不会解析#,回调以后微信传回参数会写在#前面,因此我们去参前需要对url进行处理,处理方式如下
const w = location.href.indexOf('?');
const j = location.href.indexOf('#');
let href = window.location.href;
// 处理微信回调url
if (w !== -1 && j > w) {
href = location.href.substr(0, w) + location.href.substr(j, location.href.length) + location.search;
location.href = href;
}
uni可视化可以选择uCharts,更实用兼容性会更强,支持H5、APP、小程序(微信/支付宝/百度/头条/QQ/360)
eCharts更适合在vue项目中引入
uCharts官方网站
https://www.uCharts.cn
开源地址:
https://gitee.com/uCharts/uCharts
uni-app插件市场地址:
http://ext.dcloud.net.cn/plugin?id=271
定义一个map.js
export function mymap(ak) { // 此处ak是百度地图获取的密钥
return new Promise(function(resolve, reject) {
window.init = function() {
resolve(mymap)
}
var script = document.createElement('script')
script.type = 'text/javascript'
script.src = `//api.map.baidu.com/api?v=2.0&ak=${ak}&callback=init`
script.onerror = reject
document.head.appendChild(script)
})
}
新增map.vue组件
<template>
<view class="baiduMap">
<cu-custom bgColor="bg-gradual-theme">
<block slot="leftAction">百度地图</block>
<view class="cuIcon-close" slot="right" @click="$emit('closeMap')"></view>
</cu-custom>
<view class="allmap-container" v-show="show">
<view id="allmap"></view>
<view class="posiTop">
<view class="dis">
<view class="input">
<input ref='suggestInput' id="suggestId" placeholder='输入关键字搜索' height='58' type="text" :border="true" />
</view>
<view class="button">
<button type="primary" shape="square" size="mini" @click="$emit('closeMap', addrData)">确认</button>
</view>
</view>
</view>
</view>
</view>
</template>
<script module="allmap" lang="renderjs">
import { mymap } from '@/utils/map' // 引入方法
export default {
data() {
return {
// city: '',
map: null,
ak: 'GFMn8UVkLLDdHbO8WZcTWuh9v4vDbl4Q',
show: false,
lng: '', // 当前位置
lat: '', // 当前位置
// localSearch:null,
addrData: {}
}
},
mounted() {
// 百度地图API功能
// 动态引入较大类库避免影响页面展示
this.$nextTick(() => {
let _this = this;
// 如需要弹窗授权,请写在此处
mymap(_this.ak).then((mymap) => {
// 创建地图实例
var map = new BMap.Map( "allmap" );
// 关键字输入提示 用户选择地址后 只能获取详细位置 不能获取经纬度 所以我们需要把详细地址转经纬度
// this.$refs.suggestInput.$el.querySelector('input') 很重要
// suggestInput 是input标签中属性 ref的值
let ac = new BMap.Autocomplete({
"input": this.$refs.suggestInput.$el.querySelector('input'),
"location": map
})
var localSearch = new BMap.LocalSearch(map);
/**
* 浏览器定位 获取当前位置
* 当前方法可以准确获取用户位置 经纬度信息
*/
var geolocation = new BMap.Geolocation();
geolocation.getCurrentPosition(function (r) {
if (this.getStatus() == BMAP_STATUS_SUCCESS) {
getAddress(r.point.lng, r.point.lat);// 通过经纬度获取详细地址信息
let point = new BMap.Point(r.point.lng, r.point.lat) // 设置中心点坐标
map.centerAndZoom(point, 16); //地图初始化并设置缩放级别
map.addOverlay(new BMap.Marker(point)); //添加标注
map.enableScrollWheelZoom(true); // 允许缩放地图
}else {
setByCity() // 若浏览器定位失败 改用IP定位
}
})
/**
* IP定位 获取当前位置
* 相比浏览器定位精确度更高
*/
function setByCity() {
var myCity = new BMap.LocalCity();
myCity.get(r => {
var cityName = r.name;
map.setCenter(cityName);
getAddress(r.center.lng, r.center.lat);// 通过经纬度获取详细地址信息
let point = new BMap.Point(r.center.lng, r.center.lat) // 设置中心点坐标
map.centerAndZoom(point, 16); //地图初始化并设置缩放级别
map.addOverlay(new BMap.Marker(point)); //添加标注
map.enableScrollWheelZoom(true); // 允许缩放地图
});
}
_this.map = map;
// 等地图加载好后显示地图
_this.show = true
var myValue;
//鼠标点击下拉列表后的事件
ac.addEventListener("onconfirm", function(e) {
var _value = e.item.value;
myValue = _value.province + _value.city + _value.district + _value.street + _value.business;
setPlace() // 移动到选中位置
searchByStationName(myValue) // 获取经纬度
});
// 地图上点击事件
map.addEventListener('click', function (e) {
let clickPoint = {lng: e.point.lng, lat: e.point.lat}
setPlace(clickPoint) // 移动到选中位置
getAddress(e.point.lng, e.point.lat) // 获取地址描述
});
// 点击列表 移动到选中的位置
function setPlace(clickPoint){
map.clearOverlays(); //清除地图上所有覆盖物
function myFun(){
let pp = clickPoint ? clickPoint : local.getResults().getPoi(0).point; //获取传值或获取第一个智能搜索的结果
map.centerAndZoom(pp, 20); // 放大
map.addOverlay(new BMap.Marker(pp)); // 添加标注
}
var local = new BMap.LocalSearch(map, { //智能搜索
onSearchComplete: myFun
});
local.search(myValue);
}
// 根据地址信息获取经纬度
function searchByStationName(keyword) {
localSearch.setSearchCompleteCallback(function (res) {
var poi = res.getPoi(0);
map.centerAndZoom(poi.point,16);
getAddress(poi.point.lng, poi.point.lat); // 通过经纬度 重新获取详细地址
});
localSearch.search(keyword);
}
// 根据坐标得到地址描述
function getAddress(lng, lat) {
_this.lng = lng // 经纬度
_this.lat = lat
var myGeo = new BMap.Geocoder();
// 根据坐标得到地址描述
myGeo.getLocation(new BMap.Point(lng, lat), function (result) {
if (result) {
_this.addrData = result
}
});
}
});
});
},
methods: {}
}
</script>
<style lang="scss" scoped>
.cuIcon-close {
height: 90upx;
line-height: 90upx;
margin-right: 20upx;
}
.cuIcon-close:before {
font-size: 40upx;
}
#allmap{
height: 100vh;
width: 100%;
}
.u-input--border{
padding: 0 0 0 20upx !important;
}
.posiTop{
position: fixed;
width: 100%;
top: 90upx;
.dis{
padding: 20upx;
background-color: rgba(255,255,255,0.97);
display: flex;
justify-content: space-between;
.input{
width: 80%;
input {
height: 72upx;
line-height: 72upx;
min-height: 72upx;
border: 2upx solid #e0e0e0;
border-radius: 10upx;
padding-left: 10upx;
}
}
.button{
height: 72upx;
button {
height: 60upx;
line-height: 60upx;
margin-top: 6upx;
}
}
}
}
</style>