开发项目中涉及到了很多未涉及的知识,项目完结后来总结下
1.大屏设备适配
在项目中适配的方案是rem,通过rem原理,先获取屏幕宽度划分N块,每一块都是1rem.
// 首先是一个立即执行函数,执行时传入的参数是window和document(function flexible(window, document) { // 返回文档的root元素 var docEl = document.documentElement; // 获取设备的dpr,即当前设置下物理像素与虚拟像素的比值 var dpr = window.devicePixelRatio || 1; // 设置默认字体大小,默认的字体大小继承自body function setBodyFontSize() { if (document.body) { // 调整body标签的fontSize,fontSize = (12 * dpr) + 'px' document.body.style.fontSize = 12 * dpr + 'px'; } else { document.addEventListener('DOMContentLoaded', setBodyFontSize); } } setBodyFontSize(); // set 1rem = viewWidth / 24 function setRemUnit() { // 设置root元素的fontSize = 其clientWidth / 24 + 'px' var rem = docEl.clientWidth / 24; docEl.style.fontSize = rem + 'px'; } setRemUnit(); // 当页面展示或重新设置大小的时候,触发重新 window.addEventListener('resize', setRemUnit); window.addEventListener('pageshow', function(e) { if (e.persisted) { setRemUnit(); } }); // 检测0.5px的支持,支持则root元素的class中有hairlines if (dpr >= 2) { var fakeBody = document.createElement('body'); var testElement = document.createElement('div'); testElement.style.border = '.5px solid transparent'; fakeBody.appendChild(testElement); docEl.appendChild(fakeBody); if (testElement.offsetHeight === 1) { docEl.classList.add('hairlines'); } docEl.removeChild(fakeBody); }})(window, document);
最后在页面里引入 import "@/assets/js/flexible";
比如说设计图的尺寸是3840,然后你划分的是24块,那你的根元素就是 3840/24=160。如果你在设计图量的是16px,转换成rem就是16/160=1rem。
echarts图表自适应;通过设计图的高宽决定缩放程度
// 屏幕缩放export function screenSize(editorDom) { let screenWidth = document.body.clientWidth || document.documentElement.clientWidth; let screenHeight = document.body.clientHeight || document.documentElement.clientHeight; let defWidth = 3840; let defHeight = 2160; let xScale = screenWidth / defWidth; let yScale = screenHeight / defHeight; editorDom.style.cssText += ';transform: scale(' + xScale + ',' + yScale + ')'; $(window).resize(() => { let screenWidth = document.body.clientWidth || document.documentElement.clientWidth; let screenHeight = document.body.clientHeight || document.documentElement.clientHeight; xScale = screenWidth / defWidth; yScale = screenHeight / defHeight; editorDom.style.cssText += ';transform: scale(' + xScale + ',' + yScale + ')'; })}
然后在每次在setoption时
let myChart = echarts.init(document.getElementById("chart_circular1"));
let option={...};
myChart.setOption(option, true); window.addEventListener("resize", () => { myChart.resize();});
2.Echarts使用
**1.**echarts获取dom
两种方法:普遍的就是getElementById,在vue里面还有一种方法,就是使用ref,在标签中写上ref=“test”,在methods里面就使用this.$ref.test
就可以实现获取dom;
-
<div class="chart" id="charts"></div> let myChart = echarts.init(document.getElementById("charts"));
-
<div class="chart" ref="test"></div> let myChart = echarts.init(this.$refs.test);
ref 需要在dom渲染完成后才会有,在使用的时候确保dom已经渲染完成。比如在生命周期 mounted(){} 钩子中调用,或者在 this.$nextTick(()=>{})
中调用。
2.echarts生成图表
在获取dom之后,配置option(配置项详细说明 ),最后使用setoption方法生成图表
var myChart = echarts.init(document.getElementById('main'));
// 指定图表的配置项和数据
var option = {
title: {
text: 'ECharts 入门示例'
},
tooltip: {},
legend: {
data:['销量']
},
xAxis: {
data: ["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"]
},
yAxis: {},
series: [{
name: '销量',
type: 'bar',
data: [5, 20, 36, 10, 10, 20]
}]
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
3. echarts更新图表
echarts创建后,数据变化后,仍然使用setoption方法进行修改所需的项(创建时的其他配置项可以不写,只修改所需的);
var myChart = echarts.init(document.getElementById('main'));
myChart.setOption({
//如需更新数据
series:[{
name:'',
type:'bar',
data:['a']
}]
});
4.echarts图表位置的放置
echarts有一个配置项grid,简单的设置为如下
grid:{
left:10, //也可以用百分比设置 例: left:'10%'
right:10,
top:10,
bottom:10
}
5.echarts图例设置
图例组件展现了不同系列的标记(symbol),颜色和名字。可以通过点击图例控制哪些系列不显示,配置legend即可,默认legend是一个对象,但也可以是多个即legend数组,图例有时候设置了不显示,这时候有可能配置的series没有跟图例相关联,如series
legend: { orient: "vertical", //设置列表的布局朝向 right: "10%",//图例位置 top: "10%", itemWidth: 15, //图例宽 itemHeight: 10,//图例高 textStyle: { color: "#f2f2f2", fontSize: 8, }, icon: "Rect", //图标的形状,可设置不同的 data: ['测试','测试'],},
也可以是这种形式(多个图例)
legend: [ { orient: "vertical", right: "10%", top: "10%", itemWidth: 15, itemHeight: 10, textStyle: { color: "#f2f2f2", fontSize: 8, }, icon: "Rect", data: ['测试','测试'], }, { orient: "vertical", right: "10%", top: "10%", itemWidth: 15, itemHeight: 10, textStyle: { color: "#f2f2f2", fontSize: 8, }, icon: "Rect", data: ['测试','测试'], },]
图例可以监听点击事件
myChart.on("legendselectchanged", (obj) => { // console.log('点击',obj); });
6.图表的x轴label文字设置垂直
xAxis: { axisLabel: { textStyle: { fontSize: 10, color: "#b9b8be", }, formatter: function(value) { return value.split("").join("\n"); }, },
}
更详细的配置可以查下官网的配置项
3.websocket使用
因项目中需要实时更新数据 ,所以直接使用websocket。websocket这边也不详细说明是什么了,只是简单的说下用法:
示例:
var ws = new WebSocket("wss://echo.websocket.org"); //需要连接的服务器端的URL 注意: ws或者wss一定要有 两者就是http协议和https协议的区别
ws.onopen = function(evt) {
console.log("Connection open ...");
ws.send("Hello WebSockets!"); //向服务器端发送数据的方法
};
ws.onmessage = function(evt) { //发送完数据后,从服务器端接收相应返回的方法
console.log( "Received Message: " + evt.data);
ws.close();
};
ws.onclose = function(evt) { //与服务器端断开连接后执行的方法
console.log("Connection closed.");
};
这里是我项目中的封装好的socket.js
let socket = null;let lockReconnet = false; //避免重复连接const wsUrl = ''; //服务器端的urllet isReconnet = false;let globalCallback = null, sendData = null; //把要发送给socket的数据和处理socket返回数据的回调保存起来let createSocket = url => { //创建socket try { if ('WebSocket' in window) { socket = new WebSocket(url) } initSocket() } catch (e) { reconnet(url) }}let sendMsg = (data, callback) => { //发送数据,接收数据 if (socket.readyState === 1) { globalCallback = callback; sendData = data; data = JSON.stringify(data); socket.send(data); } else { setTimeout(() => { sendMsg(data, callback) }, 1500) return false } socket.onmessage = ev => { let responseData = JSON.parse(ev.data); callback && callback(ev) }}let initSocket = () => { //初始化websocket socket.onopen = () => { console.log('socket连接成功') //heartCheck.reset().start() //后端说暂时不需要做心跳检测 if (isReconnet) {//执行全局回调函数 //console.log('websocket重新连接了') sendMsg(sendData, globalCallback) isReconnet = false } } socket.onmessage = (ev) => { console.log(ev, '连接正常') //heartCheck.reset().start() } socket.onerror = () => { console.log('websocket服务出错了---onerror'); reconnet(wsUrl) } socket.onclose = () => { console.log('websocket服务关闭了+++onclose'); reconnet(wsUrl) }}let reconnet = url => { //重新连接websock函数 if (lockReconnet) return false isReconnet = true; lockReconnet = true setTimeout(() => { createSocket(url) lockReconnet = false }, 2000)}let heartCheck = { //心跳检测 timeout: 60 * 1000, timeoutObj: null, serverTimeoutObj: null, reset() { clearTimeout(this.timeoutObj) clearTimeout(this.serverTimeoutObj) return this; }, start() { let that = this; this.timeoutObj = setTimeout(() => { //发送数据,如果onmessage能接收到数据,表示连接正常,然后在onmessage里面执行reset方法清除定时器 socket.send('heart check') this.serverTimeoutObj = setTimeout(() => { socket.close() }, that.timeout) }, this.timeout) }}createSocket(wsUrl)export default { sendMsg }
设置全局
import socket from '@/util/socket'Vue.prototype.sendMsg = socket.sendMsg
用法:
this.sendMsg({ class: "Statistics", action: "setScreenFds" },(ev)=>{
console.log(ev)
});
我在刚开始使用时不太适应,因为websocket客户端发送一条消息,服务端会异步返回。
比如,发送a,b,c三条消息,服务端只会在c消息的回调中,返回三条相应的消息,然后我这边做的调整就是让服务端返回不同的字段,在c消息的回调中做出不同的处理。如果是服务端主动发出的消息,客户端这边只能存储在vuex,然后在页面中更新。
如果有更好的处理方式,麻烦请在评论区告知下^_^
4.vuex的使用
在之前接触的项目,项目并不多使用vuex,等到用的时候就是手忙脚乱的
vuex的安装什么的可以在网上找找,很多的.这里只说下用法:
在js中引用,比如上面的自己封装好的socket.js
//引入
import store from '@/store/index'
//储存数据store.commit('editfunc', data); //editfunc是mutations里设置data值的一个方法
store.js
import Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)export default new Vuex.Store({ state: {
cdata:''
}, getters: { }, mutations: { editfunc(state, val) { state.editfunc= val }, }, actions: { }, modules: { }})
index.vue
computed: { ...mapState({ cdata: (state) => state.cdata, }), },