安装node js,输入命令,提示:'node' 不是内部或外部命令,也不是可运行的程序 或批处理文件的解决方法
大概率问题是环境变量未配置的问题
- 控制面板>系统>高级系统设置>高级>环境变量
- 新建用户环境变量
NODE_PATH
(变量名),值就是nodejs
安装路径(C:\Program Files\nodejs
)默认安装路径 - 编辑用户变量
Path
把nodejs
路径直接添加在后面即可
Vue报错Uncaught TypeError: Cannot read property 'match' of undefined
vue页面后退控制台报错
是因为a
标签没有设置href
属性,加上href
属性就好了
vue-awesome-swiper 使用loop:true后点击事件不生效的问题
<template>
<swiper class="swiper" :options="swiperOption">
<swiper-slide @click="next">Slide 1</swiper-slide>
<swiper-slide>Slide 2</swiper-slide>
<swiper-slide>Slide 3</swiper-slide>
<swiper-slide>Slide 4</swiper-slide>
<swiper-slide>Slide 5</swiper-slide>
<div class="swiper-pagination" slot="pagination"></div>
<div class="swiper-button-prev" slot="button-prev"></div>
<div class="swiper-button-next" slot="button-next"></div>
</swiper>
</template>
<script>
import { swiper, swiperSlide } from "vue-awesome-swiper";
import "swiper/swiper-bundle.css";
export default {
name: 'swiper-example-loop',
components: {
swiper,
swiperSlide
},
data() {
return {
swiperOption: {
slidesPerView: 1,
spaceBetween: 30,
loop: true,
pagination: {
el: '.swiper-pagination',
clickable: true
},
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev'
}
}
}
},
methods:{
next(){
console.log(11)
}
}
}
</script>
会发现
loop
出来的点击事件不生效
//解决
data() {
let vm=this;
return {
swiperOption: {
slidesPerView: 1,
spaceBetween: 30,
loop: true,
pagination: {
el: '.swiper-pagination',
clickable: true
},
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev'
},
on:function(e){
vm.next(e)//获取所需要的参数
}
}
}
}
js动态往body添加dom
let elem = document.createElement("div");
elem.className='loading' ;
// 或者 elem.id='loading';
elem.innerHTML = `<div class="load-3">
<div class="indexLine"></div>
<div class="indexLine"></div>
<div class="indexLine"></div>
</div>`;
document.body.appendChild(elem);
监听页面关闭或刷新执行
原理
window.onbeforeunload = function (e) {
e = e || window.event;
// 兼容IE8和Firefox 4之前的版本
if (e) {
// e.returnValue = '关闭提示';
}
// Chrome, Safari, Firefox 4+, Opera 12+ , IE 9+
// return '关闭提示';
localStorage.removeItem("ax");
};
在vue
中使用
created(){
window.addEventListener('beforeunload', this.leaveConfirm)
},
methods: {
leaveConfirm (e) {
e = e || window.event
if (e) {
// e.returnValue = '关闭提示'
}
// return '关闭提示'
// 执行一些操作
localStorage.removeItem('xx')
},
},
destroyed () {
window.removeEventListener('beforeunload', this.leaveConfirm);
},
Vue无痕刷新
//App.vue
<template>
<div id="app">
<router-view v-if="isRouterAlive" />
</div>
</template>
<script>
export default {
name: "App",
provide() {
return {
reload: this.reload
};
},
data() {
return {
isRouterAlive: true
};
},
methods: {
reload() {
this.isRouterAlive = false;
this.$nextTick(function() {
this.isRouterAlive = true;
});
}
}
};
</script>
<style>
</style>
//要用到刷新的组件 调用this.reload()
<script>
export default {
inject: ['reload'],
data() {
return {};
},
methods: {
refresh(){
this.reload();
}
},
};
</script>
还有两种方法(体验一般)
- 这两种都可以刷新当前页面的,缺点就是相当于按
ctrl+F5
强制刷新那种,整个页面重新加载,会出现一个瞬间的空白页面,体验不好
location.reload()
this.$router.go(0)
- 先跳转一个空白页,再跳转回来,这种方法就是地址栏url会有瞬间变化
<template>
<div></div>
</template>
<script>
export default {
mounted() {
let redirect = this.$route.query.redirect;
this.$router.replace(redirect);
},
};
</script>
<style lang="less" scoped>
</style>
ElementUI DatePicker选择月当前月份高亮样式修改
<template>
<div class="home">
<el-date-picker
v-model="value2"
type="month"
popper-class="month"
placeholder="选择月"
>
</el-date-picker>
</div>
</template>
<script>
export default {
name: "Home",
data() {
return {
value2: new Date(2021, 8, 1),//设置默认选择2021九月
};
},
};
</script>
<style lang="less">
.month {
.el-month-table {
td.today {
.cell {
font-weight: normal !important;
color: unset !important;
}
}
}
}
</style>
Css实现滚动时隐藏滚动条
html {
-ms-overflow-style:none;
overflow:-moz-scrollbars-none;
}
html::-webkit-scrollbar{
width:0px
}
Vue install 使用
const plugin = {
install(Vue, opts = {}) {
// 组件
// 指令
// 混入
// 挂载vue原型
//传入的参数
console.log(opts);
Vue.directive('copy', {
bind(el, { value }) {
el.$value = value
el.handler = () => {
if (!el.$value) {
// 值为空的时候,给出提示。可根据项目UI仔细设计
console.log('无复制内容')
return
}
// 动态创建 textarea 标签
const textarea = document.createElement('textarea')
// 将该 textarea 设为 readonly 防止 iOS 下自动唤起键盘,同时将 textarea 移出可视区域
textarea.readOnly = 'readonly'
textarea.style.position = 'absolute'
textarea.style.left = '-9999px'
// 将要 copy 的值赋给 textarea 标签的 value 属性
textarea.value = `${el.$value} - ${opts.name}`
// 将 textarea 插入到 body 中
document.body.appendChild(textarea)
// 选中值并复制
textarea.select()
const result = document.execCommand('Copy')
if (result) {
console.log('复制成功') // 可根据项目UI仔细设计
}
document.body.removeChild(textarea)
}
// 绑定点击事件,就是所谓的一键 copy 啦
el.addEventListener('click', el.handler)
},
// 当传进来的值更新的时候触发
componentUpdated(el, { value }) {
el.$value = value
},
// 指令与元素解绑的时候,移除事件绑定
unbind(el) {
el.removeEventListener('click', el.handler)
}
});
}
}
export default plugin
在main.js中引入
import copy from './assets/js/plugin' //plugin.js根据项目中的位置自己定
Vue.use(copy,{name:'shadow'}) //使用与传参
jsonp判断url是否能打开
$.ajax({
url:'http://ybj.zj.gov.cn/art/2019/8/7/art_1229225623_1181747.html',
cache: false,
dataType: "jsonp", //跨域采用jsonp方式
processData: false,
timeout:10000, //超时时间,毫秒
complete: function (data) {
if(data.status==200){
//可访问
}else{
//不可访问
}
}
})
获取Url参数(兼容哈希)
let url='https://xxx.cn/phone/dist/index.html?dataOpenId=oppyn1BSQzOA4C1706jNWLUoaSnU&dataUserId=406f3640614511ebad49bd6e5d36a63a#/home'
getQueryString = (name, search) => {
search = search || window.location.search.substr(1) || window.location.hash.split("?")[1];
let reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)");
let r = search.match(reg);
if (r != null) return unescape(r[2]); return null;
}
//getQueryString('dataOpenId') //'oppyn1BSQzOA4C1706jNWLUoaSnU'
//getQueryString('dataUserId') //'406f3640614511ebad49bd6e5d36a63a'
//getQueryString('dataUserId',url) //'406f3640614511ebad49bd6e5d36a63a#/home'
Elementel-cascader
级联选择器动态加载及回显
误区:默认不需要自己去加载第一层数据,会自动请求第一层数据
回显只需要传入address数组即选中的id回显会自动去请求回显
addressList设置空数组即可
<el-cascader
ref="cascaderAddr"
:props="addressProps"
v-model="address"
:options="addressList"
@change="addressChange"
></el-cascader>
<script>
export default {
name: "Home",
data() {
return {
addressList:[],
address:[],
addressProps:{
label:'title',
value:'key',
lazy: true,
lazyLoad(node, resolve){
const { level } = node;
const nodes = [];
homeRecommendApi.getTree({pId:node.value}).then(res=>{
res.data.map(item=>{
let obj = {
key: item.key,
title: item.title,
leaf: level >= 3,
};
nodes.push(obj);
})
resolve(nodes);
})
}
},
};
},
};
</script>
微信小程序使用Echarts控制台报错非法颜色none
在ec-canvas
文件夹下wx-canvas.js
文件的_initStyle()
方法中加入代码
使用
force-use-old-canvas="true"
属性引起(该属性解决图表不随屏幕滚动问题)
<ec-canvas id="progressChart" canvas-id="mychart-bar" ec="{{ ecProgress }}" force-use-old-canvas="true">
</ec-canvas>
var styles = [
"fillStyle",
"strokeStyle",
"globalAlpha",
"textAlign",
"textBaseAlign",
"shadow",
"lineWidth",
"lineCap",
"lineJoin",
"lineDash",
"miterLimit",
"fontSize",
];
styles.forEach((style) => {
Object.defineProperty(ctx, style, {
set: (value) => {
if (
(style !== "fillStyle" && style !== "strokeStyle") ||
(value !== "none" && value !== null)
) {
ctx["set" + style.charAt(0).toUpperCase() + style.slice(1)](value);
}
},
});
});
将字符串转换成数组("[上海, 天津, 河南]"
)
"[上海, 天津, 河南]".replace (/\[|]/g, '').split(',')
浙里办数据脱敏
const desensitization = (str, beginLen, endLen = -1) => {
let len = str.length;
if (beginLen == 0) {
endLen = endLen * len + 1;
}
let firstStr = str.substr(0, beginLen);
let lastStr = str.substr(endLen);
let middleStr = str.substring(beginLen, len - Math.abs(endLen)).replace(/[\s\S]/ig, '*');
return `${firstStr}${middleStr}${lastStr}`;
}
//姓名脱敏
desensitization(userName,0)
//手机号脱敏
desensitization(phone,3,-4)
//身份证号脱敏
desensitization(idCard,1,-1)
字符串首字脱敏展示
const maskChineseString=(s)=>s.replace(/^(.)/, "*")
maskChineseString('abc') //*bc
maskChineseString('张三丰') //*三丰
Element的el-time-picker选择了时间点确定后鼠标快速移入选择框选择框再次显示问题
- 通过修改
css
的方法(缺点:会移除显示隐藏的动画)
.el-time-panel {
transition: none !important;
}
- 失去焦点事件内手动执行关闭显示框
setTimeout(() => {
this.$refs.timePicker.pickerVisible = false;
}, 50);
- 最优解
data () {
return {
externalVisible:false
}
},
methods:{
handleOnFocus (ref) {
if(ref.pickerVisible && this.externalVisible) {
ref.pickerVisible = false
ref.blur()
}
},
handleOnBlur (ref) {
ref.picker.$on("dodestroy", () => {
this.externalVisible = false
})
this.externalVisible = true
},
}
根据给定的对象替换数组中的key对应的值
let chartProperties={id:'name',name:'id'};
let arr=[
{
"id": "nav_1",
"name": "首页"
},
{
"id": "nav_2",
"name": "新闻"
},
{
"id": "nav_3",
"name": "产品"
}
];
let newArr=arr.map(obj=>{
for (const key in chartProperties) {
const value=chartProperties[key]
const temp=obj[key]
obj[key]=obj[value]
obj[value]=temp
return obj
}
})
console.log(newArr);
// result
[
{
"id": "首页",
"name": "nav_1"
},
{
"id": "新闻",
"name": "nav_2"
},
{
"id": "产品",
"name": "nav_3"
}
]
方法二
const chartProperties={
name: "id",
id: "name"
}
const data=[
{
"id": "nav_1",
"name": "首页"
},
{
"id": "nav_2",
"name": "新闻"
},
{
"id": "nav_3",
"name": "产品"
}
];;
const {name, id} = chartProperties;
const newData = data.map((item) => ({
name: item[name],
id: item[id]
}));
对象key属性未知数据转换
const chartProperties = {
name: "id",
id: "name",
a: 'name'
}
const data = [
{
"id": "nav_1",
"name": "首页"
},
{
"id": "nav_2",
"name": "新闻"
},
{
"id": "nav_3",
"name": "产品"
}
];;
let keys = Object.keys(chartProperties)
let values = Object.values(chartProperties)
let arr = []
for (let i of data) {
let obj = {}
for (let j of keys) {
obj[j] = i[chartProperties[j]]
}
arr.push(obj)
}
//result
[
{ name: 'nav_1', id: '首页', a: '首页' },
{ name: 'nav_2', id: '新闻', a: '新闻' },
{ name: 'nav_3', id: '产品', a: '产品' }
]
方法二
const result = data.map(item => {
const newItem = {};
Object.keys(chartProperties).forEach(key => {
newItem[key] = item[chartProperties[key]];
});
return newItem;
});
console.log(result);
方法三
const result = data.reduce((arr, item) => {
const newItem = {};
Object.keys(chartProperties).forEach(key => {
newItem[key] = item[chartProperties[key]];
});
arr.push(newItem);
return arr;
}, []);
把vue组件添加到body下
使用场景:祖先元素使用了transform属性影响到了子元素的fixed定位(吸顶效果)
// mounted中添加代码
this.$nextTick(() => {
const body = document.querySelector("body");
if (body.append) {
body.append(this.$el);
} else {
body.appendChild(this.$el);
}
});
遍历多层嵌套数据获取key值等于指定值的对象
/**
*
* @param data 传入的多层嵌套结构数据
* @param modelValue 指定的key的value值
* @param deepSearch(data, 'model', modelValue); 'model' 是指定的key 可自行修改
* @returns
*/
const findItemByModel = (data, modelValue) => {
const deepSearch = (object, key, value) => {
if (object.hasOwnProperty(key) && object[key] === value) return object;
for (let i = 0; i < Object.keys(object).length; i++) {
let child = object[Object.keys(object)[i]];
if (typeof child === "object" && child != null) {
let result = deepSearch(child, key, value);
if (result != null) return result;
}
}
return null;
};
return deepSearch(data, 'model', modelValue);
};
Vue slot使用v-model双向绑定
<template>
<div>
<slot v-bind:value="value" v-on:input="value = $event.target.value"></slot>
</div>
</template>
<!-- Parent.vue -->
<template>
<div>
<Child v-model="value">
<template #default="{ value, updateValue }">
<input :value="value" @input="updateValue($event.target.value)">
</template>
</Child>
</div>
</template>
<script>
import Child from './Child.vue'
export default {
components: {
Child
},
data() {
return {
value: ''
}
}
}
</script>
<!-- Child.vue -->
<template>
<div>
<slot :value="value" @update:value="updateValue">
<!-- 插入内容 -->
</slot>
</div>
</template>
<script>
export default {
props: {
modelValue: String
},
computed: {
value: {
get() {
return this.modelValue
},
set(newValue) {
this.$emit('update:modelValue', newValue)
}
}
},
methods: {
updateValue(newValue) {
this.value = newValue
}
}
}
</script>
Jenkins构建Vue build一直报错问题
node -v
//全局安装yarn并设置镜像
npm install -g yarn -registry=https://registry.npmmirror.com
yarn -v
//在安装包时忽略engines字段的检查。engines字段通常用于指定项目运行所需的Node.js和npm版本,
//如果不忽略这个检查,Yarn可能会因为当前环境不符合这些要求而拒绝安装包
yarn config set ignore-engines true
//安装项目依赖,但是不会生成或更新yarn.lock文件
yarn install --pure-lockfile
yarn run build