1.表格宽度问题
通过ELement-UI设置宽度时,使用width 是固定的,min-width 会把剩余宽度按比例分配给设置了 min-width 的列.但是这里遇到一个问题,就是在小屏幕刷新页面可以适配,把小屏幕拖拽到大屏幕也可以适配,但是把大屏幕拖拽到小屏幕就不可以适配了。因此解决方案是:在每个表格外面加上el-row,el-col标签,这样就可以适配上面的这几个问题了。出现这种情况的原因是因为设置min-width在大屏幕会自适应,突然调到小屏幕就不会立马生效,因此可以把两个表格宽度设置成百分比或者使用el-row和el-col,这样就可以解决问题了。
2.在引用组件时使用v-model
v-model在组件中使用时,相当于input事件和value值传给子组件,在子组件中默认使用value接收父组件传过来的值,在子组件创建时,把this.show = this.value;关闭时this.show = false;并且要在子组件使用watch监听器监视value值,这样做的目的是防止子组件改变父组件的值,进而报错,因此才这样做,监听器中就是把变化后的值赋值给show,例如:this.show = val;
<!-- 信息弹窗 -->
<TagInfo v-if="showTagInfo" v-model="showTagInfo" :row="row" @getTableList="handleUpdate"></TagInfo>
上面引用这个组件,下面是它这个组件:
<el-drawer
title="弹窗信息"
:visible.sync="show"
:direction="direction"
@closed="close"
custom-class="dialog-wrap"
size="600px"
>
<el-form
label-width="100px"
:rules="editDialogRules"
:model="editDialogForm"
ref="editDialogForm"
>
<el-col :span="14">
<el-form-item label="商品名称:">{{editDialogForm.goodsName}}</el-form-item>
</el-col>
</el-drawer>
<script>
props:{
value: {
type: Boolean,
default: false,
},
row:{
type:Object,
default:{},
}
},
watch:{
value(val) {
this.show = val;
this.resetForm("editDialogForm");
}
},
created() {
this.show = this.value;
},
close() {
this.show = false;
this.$emit("input", false);
this.$emit("close", false);
},
</script>
3.注册全局组件
在main.js中使用这个,当然前提是在components文件夹下,创建不同文件夹,并在对应的文件夹下创建index.vue组件。这样可以循环注册多个组件。
// 注册全局组件
const components = require.context('./components', true, /index\.vue$/);
components.keys().forEach(item => {
const fileItem = components(item).default
// 如果组件内定义name 则需要全局引用的
if (fileItem.name) {
Vue.component(fileItem.name, fileItem)
}
})
4.文件导出的三种方法:前端可以不直接点击通过浏览器进行下载
1>完整的封装一个下载接收流的代码:
//封裝接收流的函數
exportData(oParam) {
oParam.url = oParam.url || "";
oParam.name = oParam.name || "下载文件" + Date.now();
oParam.type = oParam.type || "1";
if (!oParam.url) return false;
if (oParam.type === "1") {
let x = new XMLHttpRequest();
x.open("GET", oParam.url, true);
x.responseType = "blob";
x.onload = function (e) {
let urlData = window.URL.createObjectURL(x.response);
let a = document.createElement("a");
a.href = urlData;
a.download =
oParam.name + oParam.url.substring(oParam.url.lastIndexOf(".") + 1);
a.click();
};
x.send();
} else {
let x = document.createElement("a");
x.href = oParam.url;
x.download = "";
x.style.display = "none";
document.body.appendChild(x);
x.click();
document.body.removeChild(x);
}
},
2>导出文件的js代码
downloadWithBlob(url) {
const elt = document.createElement('a');
elt.setAttribute('href', url);
elt.setAttribute('download', 'file.csv');
elt.style.display = 'none';
document.body.appendChild(elt);
elt.click();
},
3>导出文件
//导出商品信息文件
exportFile(result) {
if (!result) {
console.log("下载失败,解析数据为空!");
return;
}
// 创建a标签,并隐藏改a标签
let link = document.createElement("a");
link.style.display = "none";
// a标签的href属性指定下载链接
link.href = result;
//setAttribute() 方法添加指定的属性,并为其赋指定的值。
link.setAttribute('download', 'file.png');
document.body.appendChild(link);
link.click();
},
5.vue中this.$nextTick()的用法
this.$nextTick 将回调延迟到下次DOM更新循环之后执行。在修改数据之后立即使用它,然后等待DOM更新。 this.$nextTick 跟全局方法 vue.nextTick 一样,不同的是,回调的 this 自动绑定到调用它的实例上。 总的来说,假设我们更改了某个 dom 元素内部的文本,而这时候我们想直接打印这个更改之后的文本是需要 dom 更新之后才会实现的,就像我们把将要打印输出的代码放在 setTimeout(fn, 0) 中
<template>
<button ref="tar"
type="button"
name="button"
@click="testClick">{{content}}</button>
</template>
<script>
export default {
data () {
return {
content: '初始值'
}
}
methods: {
testClick(){
this.content = '改变了的值'
// 这时候直接打印的话,由于dom元素还没更新
// 因此打印出来的还是未改变之前的值
console.log(this.$refs.tar.innerText) // 初始值
}
}
}
</script>
this.$nextTick这个方法作用是,当数据被修改后使用这个方法,会回调获取更新后的dom再渲染出来
methods:{
testClick() {
this.content = '改变了的值'
this.$nextTick(() => {
// dom元素更新后执行,因此这里能正确打印更改之后的值
console.log(this.$refs.tar.innerText) // 改变了的值
})
}
}
this.$nextTick()方法主要是用在随数据改变而改变的dom应用场景中,vue中数据和dom渲染由于是异步的, 所以,要让dom结构随数据改变这样的操作都应该放进this.$nextTick()的回调函数中。
created()中使用的方法时,dom还没有渲染,如果此时在该钩子函数中进行dom赋值数据(或者其它dom操作)时无异于徒劳,所以,此时this.$nextTick()就会被大量使用,而与created()对应的是mounted()的钩子函数则是在dom完全渲染后才开始渲染数据,所以在mounted()中操作dom基本不会存在渲染问题。
使用场景:
1>Vue生命周期的created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中,原因是在created()钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操作无异于徒劳,所以此处一定要将DOM操作的js代码放进Vue.nextTick()的回调函数中。与之对应的就是mounted钩子函数,因为该钩子函数执行时所有的DOM挂载已完成。
2>当项目中你想在改变DOM元素的数据后基于新的dom做点什么,对新DOM一系列的js操作都需要放进Vue.nextTick()的回调函数中; 通俗的理解是:更改数据后当你想立即使用js操作新的视图的时候需要使用它.
3>在使用某个第三方插件时 ,希望在vue生成的某些dom动态发生变化时重新应用该插件,也会用到该方法,这时候就需要在 $nextTick 的回调函数中执行重新应用插件的方法。
Vue.nextTick(callback) 使用原理: 原因是,Vue是异步执行dom更新的,一旦观察到数据变化,Vue就会开启一个队列,然后把在同一个事件循环 (event loop) 当中观察到数据变化的 watcher 推送进这个队列。如果这个watcher被触发多次,只会被推送到队列一次。这种缓冲行为可以有效的去掉重复数据造成的不必要的计算和DOm操作。而在下一个事件循环时,Vue会清空队列,并进行必要的DOM更新。
当你设置 vm.someData = 'new value',DOM 并不会马上更新,而是在异步队列被清除,也就是下一个事件循环开始时执行更新时才会进行必要的DOM更新。如果此时你想要根据更新的 DOM 状态去做某些事情,就会出现问题x。为了在数据变化之后等待 Vue 完成更新 DOM ,可以在数据变化之后立即使用 Vue.nextTick(callback) 。这样回调函数在 DOM 更新完成后就会调用。