文章目录
vue必须配置的部分代码
const port = 8888; // 端口号
const path = require("path");
const resolve = (dir) => path.join(__dirname, dir); // 用于获取指定目录的绝对路径
module.exports = {
publicPath:
process.env.NODE_ENV === "production"
? "./" // 生产环境
: "/", // 开发环境
outputDir: "dist", // 打包输出的文件
assetsDir: "static", // 设置放置打包生成的静态资源
productionSourceMap: false, // 生产环境是否要生成 sourceMap 文件,建议不加,不然反编译可以生成源代码(如果源码丢失那就得祈祷有map文件,不然源码就真的回不来了)
filenameHashing: true, // 文件名哈希
devServer: {
port,
},
}
参考文章:
vue.config.js 的完整配置(超详细)!
vue.config配置解读
element ui按需引入
注意:
这里是 element ui 不是 element plus,element plus 参考:element plus 使用问题
官网的比较老了,现在修改的是babel.config.js
module.exports = {
presets: [
"@vue/cli-plugin-babel/preset",
["@babel/preset-env", { modules: false }],
],
plugins: [
[
"component",
{
libraryName: "element-ui",
styleLibraryName: "theme-chalk",
},
],
],
};
vue动态绑定背景(transform类比)
<div class="cover1" :style="{transform:`rotate(${rotate1}deg)`}" v-if="rotate1 <= 90"></div>
<div class="cover2" :class="rotate1 <= 90 ? 'cover2i' : ''" :style="{transform:`rotate(${rotate1}deg)`}" v-if="rotate1 <= 180"></div>
<div class="cover3" :class="rotate1 <= 180 ? 'cover3i': ''" :style="{transform:`rotate(${rotate1}deg)`}" v-if="rotate1 <= 270"></div>
<div class="bgimg" :style="{backgroundImage:'url('+msg.url+')'}"></div>
自适应js
; (function (win) {
var bodyStyle = document.createElement('style')
bodyStyle.innerHTML = `body{width:1920px; height:1200px; overflow:hidden}` // 需要适配的屏幕的宽高
document.documentElement.firstElementChild.appendChild(bodyStyle)
function refreshScale() {
let docWidth = document.documentElement.clientWidth
let docHeight = document.documentElement.clientHeight
var designWidth = 1920 // 需要适配的屏幕的宽
var designHeight = 1200 // 需要适配的屏幕的高
var widthRatio = 0
widthRatio = docWidth / designWidth
var heightRatio = 0
heightRatio = docHeight / designHeight
document.body.style =
'transform:scale(' +
widthRatio +
',' +
heightRatio +
');transform-origin:left top;'
// 应对浏览器全屏切换前后窗口因短暂滚动条问题出现未占满情况
setTimeout(function () {
var lateWidth = document.documentElement.clientWidth,
lateHeight = document.documentElement.clientHeight
if (lateWidth === docWidth) return
widthRatio = lateWidth / designWidth
heightRatio = lateHeight / designHeight
document.body.style =
'transform:scale(' +
widthRatio +
',' +
heightRatio +
');transform-origin:left top;'
}, 0)
}
refreshScale()
window.addEventListener(
'pageshow',
function (e) {
if (e.persisted) {
// 浏览器后退的时候重新计算
refreshScale()
}
},
false
)
window.addEventListener('resize', refreshScale, false)
})(window);
这个自适应是最简单的自适应,主要用来对一些等比例的屏幕或者长宽比相近的屏幕的适配,主要还是针对类似电脑屏幕的适配!
注意:
1、如果项目有3d相关的操作,那么这个可能会适得其反,让本来百分比就可以适配的变得不适配!参考:swiper 3d 结合 loop 向左移动缺少一个内容
2、手机端、pad端还是建议使用px2rem,参考我的:使用px2rem不生效
3、一定要给body加overflow,因为只是缩小了,但是其实原来的内容大小没变!
禁止放大
// 禁用双指放大
document.documentElement.addEventListener(
'touchstart',
function (event) {
if (event.touches.length > 1) {
event.preventDefault()
}
},
{
passive: false,
}
);
// 禁用双击放大
var lastTouchEnd = 0
document.documentElement.addEventListener(
'touchend',
function (event) {
var now = Date.now()
if (now - lastTouchEnd <= 300) {
event.preventDefault()
}
lastTouchEnd = now
},
{
passive: false
}
)
播放声音
少量动态添加声音
// 添加音频
const audiodom = document.createElement("audio");
audiodom.setAttribute("id", "callmusic");
audiodom.setAttribute("loop", "loop");
audiodom.setAttribute("src", "static/audio/game_start.mp3");
document.body.appendChild(audiodom);
const callmusic = document.getElementById("callmusic");
callmusic.play();
// 移除音频
const callmusic = document.getElementById("callmusic");
document.body.removeChild(callmusic);
注意:
1、如果一个界面有好几个音频,一定要取不同的名字!
2、如果是组件里面有音频,而组件会复用,那么一定要动态绑定id!
eg:
audiodom.setAttribute("id", "callmusic"+this.id) // id由父组件传入
固定声音
html
<audio
ref="zongziAudio"
src="static/audio/zongzi.mp3"
@click="zingziPlay()"
></audio>
js
// 哪里触发自己决定
zingziPlay() {
this.$refs.zongziAudio.load(); // 防止一个声音接着播放
this.$refs.zongziAudio.play();
},
store的使用
store在项目中真的很容易使用到,但是每个界面都用什么this.$sotre.xxx的真的很麻烦,所以一定要记得这几个方法:
import {mapState, mapMutations, mapGetters, mapActions} from "vuex";
每一个的使用:
computed: {
...mapState([
"xxxx",
"yyyy",
]),
// v-model的时候,计算属性要加set
onoff:{
get(){
return this.actData.switchAction == 'true' || this.actData.switchAction == true;
},
set(v) {
console.log(v);
}
},
},
methods: {
...mapMutations([
"SET_AIRLIST",
"SET_AIRLIST_INDEX",
]),
...mapGetters([
"GET_CANQC",
]),
...mapActions([
"login",
"exit",
])
}
注意
这种把网络请求放action里面的,感觉菜鸟很少用到(但是应该是有用的,只是菜鸟比较菜),菜鸟都是请求完之后then的时候,用了 mapMutations 解决了!
websocket封装
websocket确实使用起来很简单,但是最好搞一个统一的断线重连以及连接流程,不然真的不太好规范!
这里菜鸟把公司一个同事的封装的献上:
data:
// 连接地址
websocketUrlPlay: ws://xxxxxx,
// 断线重连
lockReconnect: false,
// 重连定时器
reconnetTimer: null
method:
// 重连
reconnect() {
if (this.lockReconnect) {
return;
}
this.lockReconnect = true;
// 没连接上会一直重连,设置延迟避免请求过多
this.reconnetTimer && clearTimeout(this.reconnetTimer);
this.reconnetTimer = setTimeout(() => {
this.createWebsocketPlay();
this.lockReconnect = false;
}, 4000);
},
// 创建websocket
createWebsocketPlay() {
// eslint-disable-next-line
this.socket = new WebSocket(this.websocketUrlPlay);
this.socket.onopen = () => {
// onopen 连接触发
console.log("websocket pad open");
};
this.socket.onclose = () => {
// onclose 断开触发
console.log("websocket close");
this.reconnect();
};
this.socket.onerror = () => {
console.log("发生异常了");
this.reconnect();
};
this.socket.onmessage = (event) => {
// console.log(JSON.parse(event.data));
const data = JSON.parse(event.data);
}
}
注意:
1、这个 lockReconnect 类似于java中的 锁,所以 断开连接的时候一定要置为true
this.lockReconnect = true;
clearTimeout(this.reconnetTimer);
this.reconnetTimer = null;
setTimeout(()=>{
this.socket.close();
},100); // 如果关闭之前会发送消息,那么建议关闭时延时,可以更加有效!
注意
这里最好把 websocket 放在一个公共 js 里面,应用一开始就监听,应用卸载才关闭,不然自己在每一个界面创建时去创建 websocket 不仅影响性能,而且还要时刻关闭,不然就会创建多个!当然如果项目中本来就只有一个界面需要使用,那就无所谓!
echarts
echarts实现渐变
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "#17e5a2" },
{ offset: 1, color: "#23e8ca" },
]),
},
或者官网的代码:
labelLine: {
normal: {
show: true,
length: 30,
length2: 30,
lineStyle: {
color:{
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0, color: 'red' // 0% 处的颜色
}, {
offset: 0.5, color: 'red' // 100% 处的颜色
}, {
offset: 1, color: 'rgba(255,0,0,0)' // 100% 处的颜色
},],
global: false // 缺省为 false
},
width: 2,
}
}
},
参考:
配置color:https://echarts.apache.org/zh/option.html#color
echarts适配
window.addEventListener("resize", function () {
if (document.getElementById("echart_box2")) {
_this.chartssize(document.getElementById("echart_box2"), document.getElementById("echart2"), 3); // 第三个参数是自由发挥用的
_this.chart2.resize();
}
});
//为图表计算高度
chartssize(container, charts, type) {
function getStyle(el, name) {
if (window.getComputedStyle) {
return window.getComputedStyle(el, null);
} else {
return el.currentStyle;
}
}
let wi = getStyle(container, "width").width;
let hi = getStyle(container, "height").height;
charts.style.width = wi;
charts.style.height = hi;
},
MDN:
window.getComputedStyle
currentStyle
我的博客:
window.getComputedStyle
其实就是获取父元素最终样式,然后设置echarts样式而已!
echarts中间是图片或者文字(不要用定位,low)
graphic: {
elements: [{
type: 'image',
style: {
image: giftImageUrl,
width: 100,
height: 100
},
left: 'center',
top: 'center'
}]
},
参考:
配置graphic:https://echarts.apache.org/zh/option.html#graphic.elements
设置labelline的位置
参考饼图引导线调整:
https://echarts.apache.org/examples/zh/editor.html?c=pie-labelLine-adjust
打印效果:
参考edgeDistance – 防止太小显示字数过少:
https://echarts.apache.org/zh/option.html#series-pie.label.edgeDistance
swiper
swiper数据变化后,重新渲染
this.$nextTick(()=>{
this.mySwiper.update();
})
防止swiper变化而导致宽度不对
initSwiper() {
const _this = this;
setTimeout( () => {
_this.mySwiper = new Swiper(".swiper", {
width: window.innerWidth, // 全屏,不是全屏可以获取父元素宽度
observer: true,//修改swiper自己或子元素时,自动初始化swiper
observeParents: true,//修改swiper的父元素时,自动初始化swiper
autoplay: {
disableOnInteraction: false,
delay: 5 * 1000,//5秒切换一次
},
on: {
observerUpdate: function(){
console.log("检测到更新!");
this.updateSize();
},
slideChange: function () {
this.updateSize();
},
resize: function(){
this.params.width = window.innerWidth;
this.update();
},
},
});
}, 100);
},
注意:
最重要的就是这两个属性
observer: true,//修改swiper自己或子元素时,自动初始化swiper
observeParents: true,//修改swiper的父元素时,自动初始化swiper
后面on里面的方法其实不重要,只是菜鸟一开始两个属性写错位置了,写到autoplay里面去了!!!
如果前面设置无效,可以尝试加上后面的方法!!!