【vue备忘】使用require引入图片、$emit、public文件夹、$refs以及视图不更新等问题
常用小技巧
this.$el[vue3]
在vue3中,获取组件的元素DOM节点,可以直接使用this.$el(它指的是当前组件的的元素)。比如一个组件:
<template>
<div
class="progress-bar"
>
<div
class="progress-btn-wrapper"
@touchstart.prevent="onTouchStart"
@touchmove.prevent="onTouchMove"
@touchend.prevent="onTouchEnd"
>
</div>
</div>
</div>
</template>
这时候,使用this.$el获取的就是整个div.progress-bar这个DOM元素。
const progressBtnWidth = 16
onTouchMove(e) {
const barWidth = this.$el.clientWidth - progressBtnWidth
}
上面获取的就是div.progress-bar的DOM元素宽度。但是值得注意的是:
this.$el是在mounted中才会出现的,在created的时候是没有的。
区分生产环境与开发环境
const debug = process.env.NODE_ENV !== 'production';
const url = debug ? localUrl : onlineUrl;
// true就是本地开发环境,是false就是线上环境
// 如果是线上的环境
process.env.NODE_ENV === "development"
在组件中的Img标签引用本地图片
在组件中,需要引用本地图片资源,这个跟传统开发是有所区别的,如
<template>
<img :src="localImg">
</template>
<script type="text/ecmascript-6">
data() {
return {
localImg: require('../loading/myimg.jpg')
}
},
</script>
其中,目录结构是 src>components>loading>loading.vue, myimg.jpg
vue文件和图片是同级目录 ../ 就是指的components目录
在vue3中使用@指代src目录:
loading: require('@/assets/images/default.png')
require是webpack提供的方法,他会自己判断是生成引用图片还是转化为base64格式的图片。
如果在HTML中引入同级目录下的图片(如在loading.vue中):
<img width="24" height="24" src="./loading.gif">
其中 loading组件目录下有loading.vue和loading.gif两个子文件。
require是vue-cli中的方法,在vite中是无法使用的,在vite中替代的方式:https://www.jb51.net/article/281969.htm
this.$emit向外发送事件
子组件向父组件发送事件
// children.vue
this.$emit('created', 参数1, 参数2...);
// father.vue
<children @created="getParams" />
methods: {
getParams(参数1, 参数2) { ... }
}
如果父组件仅仅接收子组件的参数,那么父组件监听的时候,触发的方法只写方法名 ,不能加()否侧就接收不到传过来的数据了。
如果父组件接收事件的函数也要使用父组件的参数,那么就需要:
// child
this.$emit('freeDrop', child_args);
// father
<div v-for="(item, index) in datas" ...>
<child @freeDrop="changeImg($event, index)">
</div>
methods:{
changeImg(child_args, father_index) {
console.log(child_args子组件传递的参数, father_index父组件传递的index参数)
}
}
父组件用$event代表change事件对象,后面传递父元素自己的参数。index代表了父组件自己的第一个参数。
this.$refs获取DOM以及组件
1、如果获取的是一个DOM元素
<div ref="box">...</div>
this.$refs.box.style.color = 'red';
这时候this.$refs.box获取的就是div这个DOM元素
2、如果引用的是一个组件
<scroll ref="list"></scroll>
// this.$refs.list获取这个组件的实例,并执行组件的open()方法
this.$refs.list.open();
如果需要获取组件的DOM结构呢?
this.$refs.list.$el.style.top = '...'
public文件夹
放置在public
文件夹的静态资源都会被简单的复制,而不经过 webpack。你需要通过绝对路径来引用它们。
在vue.config中,设置publicPath
module.exports = {
// 打包文件的路径,设置为空,那么打包后的路径就是
// script src="js/xxx"(js之前就是publicPath)
publicPath:'',
}
在public/index.html中,通过<%= BASE_URL %>设置链接前缀(BASE_URL即是publicPath)
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
如果要在组件中使用,那么需要通过process.env.BASE_URL获得 (官方解释链接)
<iframe :src="`${publicPath}iframe/loading/index.html`" frameborder="0"></iframe>
// 然后在组件的JS中
data() {
return {
// 引用public文件夹的路径
publicPath: process.env.BASE_URL
}
}
Vue数据视图不更新
在一个组件实例中,只有在data里初始化的数据才是响应的,Vue不能检测到对象属性的添加或删除,没有在data里声明的属性不是响应的。Vue不允许在已经创建的实例上动态添加根级响应式属性
数组数据变动,使用某些方法操作数组,变动数据时,有些方法无法被vue监测。
push(),pop(),shift(),unshift(),splice(),sort(),reverse()
可被vue检测到,而filter()
,concat()
,slice()
。这些不会改变原始数组,但总是返回一个新数组。则不会被检测到,可以用新数组替换旧数组。
vue不能检测以下变动的数组:
- 当你利用索引直接设置一个项时,
vm.items[indexOfItem] = newValue
当你修改数组的长度时,例如:
vm.items.length = newLength
<li class="sliders-li"
v-for="(item, index) in slider"
:key="'sld' + index"
:data-fold="`${isFolds[index]}`"
>
props: {
slider: {
type: Array,
default() {
return []
}
}
},
data() {
return {
isFolds: []
}
},
created() {
this.setItemsFolds();
},
methods: {
setItemsFolds() {
setTimeout(() => {
this.slider.forEach(() => {
this.isFolds.push(false);
});
}, 200);
},
toggleFoldItem(index) {
let now = this.isFolds[index];
// 如果使用this.isFolds[index] = !now 那么就不会被响应到!
this.isFolds.splice(index, 1, !now);
console.log(this.isFolds)
}
}
或者使用 this.$forceUpdate(); 强制更新视图。
eslint检查忽略
// 忽略下方代码的eslint检查:
/* eslint-disable */
alert(‘foo’);
// 针对某一行禁用eslint检查:
alert(‘foo’); // eslint-disable-line
// 文件中禁用多项eslint规则的检查:
/* eslint-disable no-alert, no-console */
alert(‘foo’);
console.log(‘bar’);
v-for直接循环数字,固定循环次数
<li class="item"
v-for="index of nums"
:key="index"
>
data() {
return {
nums: 8
}
}
// 或者直接:
v-for="index of 8"
vue中数据的深拷贝
当组件间传递对象时,由于此对象的引用类型指向的都是一个地址(除了基本类型跟null,对象之间的赋值,只是将地址指向同一个,而不是真正意义上的拷贝)。如
// 变量 var和let的结果相同
var e = 1;
var f = e;
f = 10;
console.log(e); // 1
// 数组
var a = [1,2,3];
var b = a;
b.push(4); // b中添加了一个4
console.log(a) // a变成了[1,2,3,4]
// 对象
let c = {x: 1, y: 2};
let d = c;
d.z = 100;
console.log(c) // {x: 1, y: 2, z: 100}
这就是由于对象类型直接赋值,只是将引用指向同一个地址,导致修改了obj会导致obj2也被修改。
所以let arr = this.data; arr.forEach(item => { item.xx = xx; }) 结果发现this.data中的xx属性也改变了。
要避免这种情况,就要使用一点点技巧,对数据进行深度拷贝。
// 对象
var obj={};
// this.maindata 是在data中注册的对象
bj=JSON.parse(JSON.stringify(this.maindata));
// 数组: 使用解构赋值
let arr = [...this.mainArr]
npm常用操作
npm查询版本
npm -v
npm安装模块
【npm install xxx】利用 npm 安装xxx模块到当前命令行所在目录;
【npm install -g xxx】利用npm安装全局模块xxx;
npm卸载模块
【npm uninstall xxx】删除xxx模块;
【npm uninstall -g xxx】删除全局模块xxx;
本地安装时将模块写入package.json中
【npm install xxx】安装但不写入package.json;
【npm install xxx –save】 安装并写入package.json的”dependencies”中;
【npm install xxx --save-dev】 安装并写入package.json的”devDependencies”中
npm 安装淘宝镜像
npm install -g cnpm --registry=https://registry.npm.taobao.org
npm查看源
npm config get registry
改为镜像源
// 改为官方镜像源
npm config set registry https://registry.npmjs.org/
// 改为淘宝镜像源
npm config set registry http://registry.npm.taobao.org/