有写错的地方,欢迎指正~ 一月部分持续更新中...
概念篇
1.v-model 的本质是语法糖
1.原理
- v-bind绑定一个value值
- v-on指令给当前元素绑定input事件
<input v-model ="inputValue">
<input v-bind:value ="inputValue" v-on:input="inputValue = $event.target.value">`
2.应用中需要注意的事
2.1 普通用法
//1.错误用法 div v-model
<div v-model="testValue"></div>
//2.正确用法
<input v-model="testValue"/>
2.2自定义组件的 v-model
//自定义组件的 v-model 子组件传值自动加入change事件
//父组件
<child v-model="testValue"/>
//子组件 相当于改值内部emit父组件的值
//<input v-on:change ="(val)=>{this.$emil("change",val)" />
<input type="checkbox" v-model="checked" />
model: {
prop: 'checked',
event: 'change'
},
props: {
checked: {
type: Boolean,
default: "",
},
},
2.nextTick 的更新机制以及应用
- Vue 在更新 DOM 时是异步执行的。
- 只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。
- 如果同一个 watcher 被多次触发,只会被推入到队列中一次。
- 这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。
- 在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。
methods: {
updateMessage1: async function () {
await this.$nextTick()
console.log("zzzz") // => '已更新视图'
}
updateMessage2: function () {
this.$nextTick(() =>{
console.log("zzzz") // => '已更新视图'
})
}
}
实践篇
1.表格表头居中样式统一
1.问题场景
//避免繁琐写 align 居中样式
<el-table-column type="index" align="center" label="序号"></el-table-column>
2.解决思路
<el-table border stripe :cell-style="rowClass" :header-cell-style="headClass" >
...
</el-table>
// 表头样式设置
headClass() {
return "text-align: center;"
},
// 表格样式设置
rowClass() {
return "text-align: center;"
},
<el-table border stripe :cell-style="{ 'text-align': 'center' }" :header-cell-style="{'text-align':'center'}" >
...
</el-table>
1.1表格合计的方法
- 第一行(根据序号为0的行)五列合并
<el-table :span-method="salarySpanMethod">
<el-table-column align="center" label="序号" type="index" fixed>
<template slot-scope="scope">
<span>{{ scope.$index === 0 ? "合计" : scope.$index }}</span>
</template>
</el-table-column>
</el-table>
salarySpanMethod({ row, column, rowIndex, columnIndex }) {
if (rowIndex === 0) {
//表格第一行进行合并列
if (columnIndex === 1) {
//第一列输出[1,5],代表该表格向右合并4个单元格
return [1, 5];
} else if (columnIndex < 5) {
//由于第1列要合并第5列,所以第小于5列要删除该单元格
return [0, 0];
}
}
},
2.全局定义element 事件
//el-table hover有详情展示气泡
ElementUI.TableColumn.props.showOverflowTooltip = { type: Boolean, default: true }
//点击蒙层不关闭弹窗
ElementUI.Dialog.props.closeOnClickModal.default = false;
//设置组件默认样式大小
Vue.use(ElementUI, {
size: Cookies.get('size') || 'small'
})
3.表格表头插入自定义操作
1.问题场景
需要对表头进行筛选操作等
2.解决思路1 :头部渲染方法
<el-table-column prop="withdrawalResult" :render-header="renderFilterValue">
...
</el-table>
//渲染筛选值
renderFilterValue(creatElement, { column, $index }) {
return (
<el-dropdown onCommand={this.handleFilterWithdraw }>
<span style='font-size:14px;'>
提现结果<span class='y-filter-icon' />
</span>
<el-dropdown-menu slot='dropdown'>
<el-dropdown-item command='success'>已提现</el-dropdown-item>
<el-dropdown-item command='dealing'>待提现</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
)
},
2.解决思路2 header 插槽
<el-table-column prop="withdrawalResult" fixed="right" width="160">
<template slot="header" slot-scope="scope">
<el-dropdown trigger="click" @command="handleFilterWithdraw">
<div class="el-dropdown-link">
提现结果<span class="y-filter-icon" />
</div>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item v-for="item in dictList.withdrawal_result" :key="item.dicCoding" :command="item.dicCoding">{{ item.dicCodingName }}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
补充说明:官方不推荐使用render 解决思路1
4.全局使用filters
1.问题场景
- 系统多处调用方法过滤数据
2.解决思路
// main.js注册筛选方法
import registerFilter from './utils/filters'
registerFilter(Vue)
//utils/filters'
export const formatRatio = (val) => {
if (!val) {
return '-'
}
let str = Number(val * 100).toFixed(0) + '%'
return str
}
export default (Vue) => {
Vue.filter('formatRatio', formatRatio)
}
//页面使用
<el-table-column prop="lyhrsFoInsure.fundUnitRatio" label="单位比例" >
<template scope="scope">
{{scope.row.lyhrsFoInsure.fundUnitRatio | formatRatio}}
</template>
</el-table-column>
5.页面刷新的方法
1.问题场景
- 1.页面刷新,可采用全局注册方法 使用
- 2.页面刷新的位置问题,不同的位置刷新的部分不同,应该避免再最外层刷新,造成白屏体验
- 3.页面刷新挂在子组件的外层 中 避免其他缓存页面的重载
2.解决思路
//在app 下的 layout 层中
<transition name="move" mode="out-in">
<keep-alive :include="tagsList">
<router-view v-if="isRouterAlive"></router-view>
</keep-alive>
</transition>
export default {
provide() {
return {
reload: this.reload,
}
},
data() {
return {
isRouterAlive: true, //默认为true
}
},
methods: {
reload() {
this.isRouterAlive = false
this.$nextTick(function () {
this.isRouterAlive = true
})
},
},
}
6.父组件向子组件挂载顺序
1.问题场景
- 页面报错 a is no defined
//父组件传值
<button @click="getList"></button>
<child :list="list"/>
data() {
return{
list: {}
}
}
methods: {
getList() {
...
this.list.a = 'zzz'
}
}
//子组件
<div>{{list.a}}</div>
2.解决思路
- 父组件对象中的属性需要定义初始值
3.引发思考
- 父组件和子组件的渲染顺序是如何的?
加载渲染过程
- 父beforeCreate->父created->父beforeMount->
- 子beforeCreate->子created->子beforeMount->子mounted->
- 父mounted
子组件挂载完成后 父组件才挂载完成
##7.页面缓存导致数据不刷新 ...待补充