<el-table v-if="showTable" ref="table" :data="datas" :header-cell-style="this.$store.state.rowStyle" @selection-change="handleSelectionChange" border style="height:93%;" >//上面设置ref,在script中可以通过this.$ref获取this.$nextTick(()=>{ //父组件获取子组件table相当于dom,更新渲染表格的数据 this.$refs.table.doLayout()})
ref有三种用法
1. 加载普通元素上,用this.$ref.[name]获取到的是dom元素
2. ref加在子组件上,用this.$ref.[name]获取到的是组件实例,可以使用组件的所有方法
3. 如何利用 v-for 和 ref 获取一组数组或者dom 节点
注意:
1、ref 需要在dom渲染完成后才会有,在使用的时候确保dom已经渲染完成。比如在生命周期 mounted(){} 钩子中调用,或者在 this.$nextTick(()=>{}) 中调用。
2、如果ref 是循环出来的,有多个重名,那么ref的值会是一个数组 ,此时要拿到单个的ref 只需要循环就可以了
this.$nextTick
一、示例
先来一个示例了解下关于Vue中的DOM更新以及nextTick的作用。
模板
<button @click="changeMsg">
Change the Message
Vue****实例
new Vue({
el: '.app',
data: {
msg: 'Hello Vue.',
msg1: '',
msg2: '',
msg3: ''
},
methods: {
changeMsg() {
this.msg = "Hello world."
this.msg1 = this.$refs.msgDiv.innerHTML
this.$nextTick(() => {
this.msg2 = this.$refs.msgDiv.innerHTML
})
this.msg3 = this.$refs.msgDiv.innerHTML
}
}
})
点击前
点击后
从图中可以得知:msg1和msg3显示的内容还是变换之前的,而msg2显示的内容是变换之后的。其根本原因是因为Vue中DOM更新是异步的(详细解释在后面)。
二、应用场景
下面了解下nextTick的主要应用的场景及原因。
- 在Vue生命周期的created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中
在created()钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操作无异于徒劳,所以此处一定要将DOM操作的js代码放进Vue.nextTick()的回调函数中。与之对应的就是mounted()钩子函数,因为该钩子函数执行时所有的DOM挂载和渲染都已完成,此时在该钩子函数中进行任何DOM操作都不会有问题 。
- 在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的DOM结构的时候,这个操作都应该放进Vue.nextTick()的回调函数中。
.sync的修饰符
在vue的组件通信props中,一般情况,数据都是单向的,子组件不会更改父组件的值
不使用sync的情况
{{dd}}//调用子组件 <A :aData='dd'></A>import A from '../TestComponentData/A';export default { inject:['userInfo'], components:{ A // A: () => import('../TestComponentData/A') }, data(){ return { dd:'这是父级传给子级的数据' }}}
子组件中:
<template> <div> {{aData}} <button @click="changeData"> Change the Data </button> </div></template><script>export default { props:['aData'], methods:{ changeData(){ this.aData = '子集改变了父级的数据'; } }}</script>
点击按钮前显示:
点击按钮后显示:
父级中的dd没有改变
使用sync修饰符
父组件调用子组件时
{{dd}}<A :aData.sync='dd'></A>
子组件
<template> <div> {{aData}} <button @click="changeData"> Change the Data </button> </div></template><script>export default { props:['aData'], methods:{ changeData(){ this.aData = '子集改变了父级的数据'; this.$emit('update:aData',this.aData); } }}</script>
点击按钮前显示:
点击按钮后显示:
父级中的dd也改变了
Vue值拷贝
// 活动促销tableHdData: [],// 打折促销tableDzData: [],// 值拷贝 _this.tableHdData = JSON.parse(JSON.stringify(res.data.goods_list)); _this.tableDzData = JSON.parse(JSON.stringify(res.data.rate_goods));
捕获异常
this.$axios({ method: "post", url: "/admin/Audit_Bill/level_save", data: _data }).then(res => { console.log(res); this.$message1(res.data.msg); this.handleNodeClick(this.list.id); this.set_level = false; }).catch(err => { //这里打印err没有用不会显示出来,打印err.response会有内容 console.log(err.response); // 状态码 console.log(err.response.status) if(err.response.status == 400){ this.$message1(err.response.data.msg); } });
Vue中img动态拼接:src图片地址
data(){
return{
gatherInfo: {
title: '库存汇总信息',
img1: 'k1',
img2: 'k2',
img3: 'k3',
},
}
}
//获取图片地址
getImgUrl (img) {
//在vue的js引入图片,就需要使用require("路径")进来
return require("@/assets/images/inventory/" + img+ ".png");
},
el-table多了会卡顿
使用pl-table
Umy-ui
uView UI
是uni-app生态最优秀的UI框架
watch: {
obj: {
handler(newName, oldName) {
console.log('obj.a changed');
},
immediate: true,
deep: true
}
}
watch 里面还有一个属性 deep,默认值是 false,代表是否深度监听,比如我们 data 里有一个obj属性
immediate:true代表如果在 wacth 里声明了 firstName 之后,就会立即先去执行里面的handler方法,如果为 false就跟我们以前的效果一样,不会在绑定的时候就执行。
可以使用watch来进行路由的监听
watch: {
changeShowType(value) {
console.log("-----"+value);
},
'$route'(to,from){
console.log(to); //to__表示去往的界面
console.log(from); //from__表示来自于哪个界面
if(to.path=="/shop/detail"){
console.log("商品详情");
}
}
}
Vue的table滚动加载
安装:
npm install --save el-table-infinite-scroll
全局引入:
import Vue from 'vue';
import elTableInfiniteScroll from 'el-table-infinite-scroll';
Vue.use(elTableInfiniteScroll);
局部引入:
完整实例
.el-table { width: 100%; }<el-table
:data="sku_data"
border
sortable
//是否禁用 boolean
infinite-scroll-disabled='scroll_disable'
v-el-table-infinite-scroll="load"
//是否立即执行加载方法boolean
infinite-scroll-immediate='false'
//触发加载距离阈值 px
infinite-scroll-distance='30'
//节流延时 ms
infinite-scroll-delay='300'
height="350"
style="height: 400px;overflow:auto"
class="table-attr"
:header-cell-style="rowStyle"
<el-alert v-if="isflag"
title="正在努力加载中..."
type="success"
center
:closable="false"
style="width:97%"
show-icon>
<el-alert v-if="isMore"
title="没有更多啦!"
type="warning"
center
style="width:97%"
show-icon>
scroll_disable:false,
isMore: false,
isflag: false
//load加载方法
load() {
this.isflag = true;
if(this.sku_total == this.sku_data.length){
this.isMore = true;
this.isflag = false;
this.scroll_disable = true;
this.timer = null;
this.timer = setTimeout( () => {
this.isMore = false;
}, 2000);
}
if (this.isflag && !this.isMore) {
this.getSKUData();
}
},
getSKUData(){
this.$axios({
method: "get",
url: "/admin/good/return_info",
params: {
id: this.$route.query.id,
pageSize:5,
page:++this.current_page
}
})
.then(res => {
res.data.data.sku.forEach((e,i) => {
this.sku_data.push(e)
let index = (this.current_page-1)*5 + i;
// this.attr_info[index] = Object.assign({}, this.attr_info[0]);
//将动态列传给
this.attr_info[index] = res.data.attr[i];
this.isflag = false;
})
})
}
beforeRouteEnter无效
有可能是因为router没有配置页面或者配置错误
beforeRouteEnter(to, from, next) {
next((vm) => {
vm.reload();
});
},
reload之后mounted会重新调用
//子组件中
inject: ["reload"],
<button
type="button"
class="btn-primary refresh"
@click="this.reload"
round
父组件
reload() {
this.isRouterAlive = false;
this.$nextTick(function () {
this.isRouterAlive = true;
});
}
动画
#div_digg {
bottom: 0px; margin: 0px; position: fixed; right: 0.5rem;
animation: jumping 5s ease-in-out; animation-iteration-count: infinite;
}
数组删除
this.choose_dynamicPart.splice(index, 1);
this.choose_dynamicPartId.splice(index, 1)
provide和inject
父组件
provide() {
return {
reload: this.reload,
updateTag: this.updateTagsValue,
getTabs:this.getTabs,
updateTabs:this.updateTabs
};
}
reload() {
// this.search_data=[]
this.isRouterAlive = false;
this.$nextTick(function() {
this.isRouterAlive = true;
});
},
updateTagsValue(name){
this.TabsValue = name;
},
getTabs(){
return this.Tabs;
},
updateTabs(tabs){
this.Tabs = tabs;
},
子组件
inject: ["reload","updateTag","getTabs","updateTabs"],
this.updateTag('ValetOrder');
this.Tabs = this.getTabs();
数据初始化
初始化 data 中的 footData 数据
Object.assign(this.options.data().footData);
初始化全部的 data数据
Object.assign(this.options.data());
this.nextTick(()=> {
this.select_all_goods.forEach(row => {
this.refs.singleTable.toggleRowSelection(this.goods_datas.find(item => {
return row.good_itemid == item.good_itemid; // 注意这里寻找的字段要唯一
}), true);
});
this.goods_child = [];
});
})
.catch(err => {});
cookies
JavaScript操作cookies是项目中常用的功能,几乎所有浏览器都支持原生的cookies并且后端接口可以直接写入cookies,这点相对于localStore来说也算个小优势,而现在大多数情况下项目开发会选择vue框架,因为vue框架开发效率搞,也更易于后期的升级迭代和维护。那么好的工具来了,vue-cookies主要用于vue项目中操作cookie。
image
安装
npm install vue-cookies --save
引入使用
方式一(全局引入):
import Vue from 'Vue'
import VueCookies from 'vue-cookies'
Vue.use(VueCookies)
方式二(局部引入,如果是小范围使用推荐局部引入的方式):
import VueCookies from 'vue-cookies'
Api function 方法
一下为全局引入的使用,如果是局部引入则this对象改成引入的VueCookies
设置 cookie:
this.$cookies.set(keyName, time)
删除cookie:
this.$cookies.remove(keyName)
获取cookie:
this.$cookies.get(keyName)
获取所有cookie:
this.$cookies.keys()
监测cookie是否存在:
this.$cookies.isKey(keyName)