imondo / docs Goto Github PK
View Code? Open in Web Editor NEW记录自己工作与生活的点点滴滴
Home Page: https://imondo.github.io/docs/
记录自己工作与生活的点点滴滴
Home Page: https://imondo.github.io/docs/
vue-cli
打包修改相对路径
config/index.js
文件
build: {
assetsPublicPath: './'
}
build/utils.js
const extractLoader = {
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../../'
}
}
...
if (options.extract) {
loaders.push(extractLoader)
} else {
loaders.push('vue-style-loader')
}
在vue
定义到data
中setInterval
轮询时,无法清除。
处理方案:
const polling = setInterval(() =>{
// do something
}, 1500);
this.$once('hook:beforeDestroy', () => {
clearInterval(polling);
})
// function start(id) {
// setTimeout(() => {
// execute(id).catch(console.error)
// }, id * 1000)
// }
function start(id) {
this.promise = this.promise
? this.promise.then(_ => execute(id))
: execute(id);
}
// 测试代码 (请勿更改):
for (let i = 0; i < 5; i++) {
start(i);
}
function sleep() {
const duration = Math.floor(Math.random() * 500);
return new Promise(resolve => setTimeout(resolve, duration));
}
function execute(id) {
return sleep().then(() => {
console.log("id", id);
});
}
浏览器缓存statusCode
区别
200 OK (from cache)* 是直接点击链接访问,输入网址按回车访问也能触发;浏览器没有跟服务器确认,直接用了浏览器缓存;
304 Not Modified 是刷新页面时触发,或是设置了长缓存、但 Entity Tags 没有移除时触发;是浏览器和服务器确认了一次缓存的有效性,再使用缓存,多一次确认
vue
项目首页index.html
强制去掉缓存
// index.html
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
// nginx
location /demo{
add_header Cache-Control 'private, no-store, max-age=0';
alias /opt/nginx-front/test/demo;
index index.html;
try_files $uri $uri/ /demo/index.html;
}
使用箭头函数你要格外的小心;箭头函数运行时候bind this
。
场景:
定义对象方法
定义原型方法
定义构造函数
定义事件回调函数
箭头函数没有定义this绑定
var obj = {
i: 10,
b: () => console.log(this.i, this),
c: function() {
console.log( this.i, this)
}
}
obj.b();
// undefined, Window{...}
DOM格式
<View className="college-container">
<Swiper
className="swiper-block"
circular
autoplay
current={this.state.current}
previous-margin="32rpx"
next-margin="32rpx"
onChange={this.handleChange.bind(this)}
>
{list.slice(0, 1).map(item => {
return (
<SwiperItem className="swiper-item">
<FallbackImage src={item.content.posterPath} directory={false}/>
</SwiperItem>
);
})}
</Swiper>
</View>
样式
.index-wrapper {
.college-container {
display: flex;
flex-direction: column;
}
.swiper-block {
height: 258px;
width: 100%;
}
swiper-item {
width: 620px !important;
height: 258px !important;
}
.swiper-item {
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
overflow: unset;
}
.swiper-image {
height: 258px;
width: 620px;
border-radius: 9px;
box-shadow: 0 2px 14px 0 rgba(0, 0, 0, 0.10);
margin: 0px 32px;
z-index: 1;
transform: scale(0.9);
}
.active {
transform: scale(1);
transition: all 0.2s ease-in 0s;
z-index: 20;
}
}
// a.js
actions: {
same(){
...
}
}
// b.js
actions: {
same(){
...
}
}
disaptch('same');
执行这个same
的函数时都会触发
但执行的顺序跟store
模块顺序有关,先引入先执行。
export default new Vuex.Store({
modules: {
a,
b
}
});
// 克隆元素
const cloneNode = dom.cloneNode(true);
// 创建元素,插入子元素
const exportNode = document.createElement('div').appendChild(cloneNode);
// 设置元素样式
exportNode.style = 'display: none';
// 查找元素,返回元素arr
const checkBoxNode = exportNode.querySelectorAll('.el-table-column--selection');
const displayNoneNode = exportNode.querySelectorAll('[style*="display: none"]');
// 设置元素属性
thNode.setAttribute('colspan', 10);
trNode.appendChild(thNode);
// 插入到existingDom[0]元素前
dom.insertBefore(trNode, existingDom[0]);
// 移除DOM
dom.remove();
window.addEventListener('scroll', () => {
this.handleScroll();
}, false)
去掉App.vue
中overflow:auto
可实现监听
前端可以使用Blob
来下载文件
具体代码如下
const blob = res.response;
const reader = new FileReader();
reader.readAsDataURL(blob); // 转换为base64,可以直接放入a表情href
const disposition = decodeURI(xhr.getResponseHeader('Content-Disposition'));
const dispositionArray = disposition.split('filename=');
const name = dispositionArray[dispositionArray.length - 1];
reader.onload = function(e) {
// 转换完成,创建一个a标签用于下载
const a = document.createElement('a');
a.download = name;
a.href = e.target.result;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
};
还可以通过后台返回的数据来判断错误提示
const reader = new FileReader();
reader.onload = e => {
if (!e.target.result.includes('%PDF')) {
const result = JSON.parse(e.target.result);
Message({
message: result.msg,
type: 'warning'
});
}
};
reader.readAsText(res.response);
ElInput的change 事件现在仅在输入框失去焦点或用户按下回车时触发,与原生 input 元素一致。如果需要实时响应用户的输入,可以使用 input 事件
对于数据量> 1000
的数组操作
大量数据可先定义缓存数组arr
长度,再循环添加元素
优先使用for i++
循环
赋值时注意缓存
let postData = [];
let _projectId = $('[name="projectId"]').val();
let _rogId = $('[name="orgId"]').val();
postData.length = tableData.length;
console.log(new Date());
for (let i = 0, len = tableData.length; i < len; i++) {
postData[i] = {
projectId: _projectId,
id: tableData[i].id
req: { orgId: _rogId }
};
}
需要对请求设置 { responseType: 'blob' }
根据返回来的流Blob
数据处理
window.URL.createObjectURL(blob);
const routePath = getRoutePath(this.routers, parentPath);
const path = routePath.join('/');
console.log(path) // /school/instrument/assetin
const getRoutePath = (data, target) => {
let flag = false;
const path = [];
const whileRoutePath = (data, target) => {
for (let i = 0; i < data.length; i++) {
const route = data[i];
if (!flag) {
if (i > 0) {
path.pop();
}
path.push(route.path);
if (route.path === target) {
flag = true;
return;
} else {
const children = route.children;
if (children) {
whileRoutePath(children, target);
}
}
}
}
if (!flag) {
path.pop();
}
return;
};
whileRoutePath(data, target);
return path;
}
HTTPS页面里动态的引入HTTP资源,比如引入一个js文件,会被直接block掉的.在HTTPS页面里通过AJAX的方式请求HTTP资源,也会被直接block掉的。
可以在相应的页面的里加上这句代码,意思是自动将http的不安全请求升级为https
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
position: absolute;
left: 0;
right: 0;
bottom: 0;
text-align: center;
<el-input
v-model="barcode"
@compositionstart.native="start"
@compositionend.native="end"
></el-input>
methods: {
start() { // 中文开始输入
this.composing = true;
},
end() { // 输入结束
this.composing = false;
this.barcode = '';
}
}
// 设置请求统一信息
import axios from 'axios';
import store from '../store/index.js';
import qs from 'qs';
import { messages } from './msg-box.js';
import { logout } from './logout.js';
const service = axios.create({
timeout: 300000, // 超时设置
withCredentials: true // 跨域请求
});
let hasLogoutStatus = false; // 是否某个请求存在需要退出的状态
const queue = []; // 请求队列
const CancelToken = axios.CancelToken; // axios内置的中断方法
/**
* 拼接请求的url和方法;
* 同样的`url + method` 可以视为相同的请求
* @param {Object} config 请求头对象
*/
const token = config => {
return `${config.url}_${config.method}`;
};
/**
* 中断重复的请求,并从队列中移除
* @param {Object} config 请求头对象
*/
const removeQueue = config => {
for (let i = 0, size = queue.length; i < size; i++) {
const task = queue[i];
if (!task) return;
// 出现401,403状态码中断后续请求
const isLogout = token(config).includes('logout');
// 退出接口跳过中断逻辑
if (!isLogout && hasLogoutStatus) {
task.token();
queue.splice(i, 1);
} else {
const cancelMethods = ['post', 'put', 'delete']; // 需要中断的请求方式
const { method } = config;
if (cancelMethods.includes(method)) {
if (task.token === token(config)) {
task.cancel();
queue.splice(i, 1);
}
}
}
}
};
/**
* 请求错误统一处理
* @param {Object} response 错误对象
*/
const errorHandle = response => {
const { status, data: { message }} = response;
let msg = message;
if (!message) {
switch (status) {
case 401:
msg = '您没有权限访问此操作!';
break;
case 403:
msg = '您的登录状态已失效,请重新登录。';
break;
case 424:
msg = response.data.error;
break;
default:
msg = '请求失败!';
}
}
hasLogoutStatus = status === 401 || status === 403;
if (hasLogoutStatus) {
messages('error', msg, () => {
logout();
});
}
messages('error', msg);
};
// 请求拦截器
service.interceptors.request.use(
config => {
// 中断之前的同名请求
removeQueue(config);
// 添加cancelToken
config.cancelToken = new CancelToken(c => {
queue.push({ token: token(config), cancel: c });
});
// 登录后添加token
if (store.getters.token) {
config.headers['Authorization'] =
store.getters.token.token_type + ' ' + store.getters.token.access_token;
}
return config;
},
error => {
return Promise.reject(error);
}
);
// 响应拦截器
service.interceptors.response.use(
response => {
// 在请求完成后,自动移出队列
removeQueue(response.config);
// 设置全局按钮Loading响应
store.dispatch('SetLoading', false);
// 错误码处理
if (response.status !== 200) {
return Promise.reject(response);
}
return response;
},
error => {
const { response } = error;
if (response) {
// 错误处理
errorHandle(response);
return Promise.reject(response);
} else {
// 请求超时
if (error.message.includes('timeout')) {
console.log('超时了');
messages('error', '请求已超时,请刷新或检查互联网连接');
} else {
// 断网,可以展示断网组件
console.log('断网了');
messages('error', '请检查网络是否已连接');
}
}
}
);
export default {
get: (url, data = {}) => {
return new Promise((resolve, reject) => {
service
.get(store.getters.api.EMS_API + url, { params: data })
.then(response => {
resolve(response.data);
})
.catch(error => {
reject(error);
});
}).catch(error => {
throw new Error(error);
});
},
exportFile: (url, data = {}) => {
return new Promise((resolve, reject) => {
service
.post(store.getters.api.EMS_API + url, data, {
headers: { 'Content-Type': 'application/json' },
withCredentials: true,
responseType: 'blob'
})
.then(response => {
resolve(response);
})
.catch(error => {
resolve(error);
});
}).catch(error => {
return Promise.reject(error);
});
},
post: (url, data = {}) => {
return new Promise((resolve, reject) => {
service
.post(store.getters.api.EMS_API + url, data, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
},
withCredentials: true,
transformRequest: [
data => {
return qs.stringify(data);
}
]
})
.then(response => {
resolve(response.data);
})
.catch(error => {
reject(error);
});
}).catch(error => {
return Promise.reject(error);
});
},
putJson: (url, data = {}) => {
return new Promise((resolve, reject) => {
service
.put(store.getters.api.EMS_API + url, data, {
headers: { 'Content-Type': 'application/json' },
withCredentials: true
})
.then(response => {
resolve(response.data);
})
.catch(error => {
throw new Error(error);
});
}).catch(error => {
throw new Error(error);
});
},
delete: (url, data = {}) => {
return new Promise((resolve, reject) => {
service
.delete(store.getters.api.EMS_API + url, {
data
})
.then(response => {
resolve(response.data);
})
.catch(error => {
throw new Error(error);
});
}).catch(error => {
throw new Error(error);
});
}
};
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.