前端工作总结,避免秃头 技巧(一月份)

2,533 阅读2分钟

有写错的地方,欢迎指正~ 一月部分持续更新中...

概念篇

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.页面缓存导致数据不刷新 ...待补充