前端问题汇总

98 阅读5分钟

1.常用数组方法

.filter()
filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
是否改变原数组:否
是否对空数组进行检测:否
语法:
const arr= [32, 33, 16, 40];
const arr1 = arr.filter(item => item >= 18)
console.log(arr) // [32, 33, 16, 40]
console.log(arr1) // [32, 33, 40]
 
.map()
map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
map() 方法按照原始数组元素顺序依次处理元素。
是否改变原数组:否
是否对空数组进行检测:否
语法:
const arr= [4, 9, 16, 25];
const arr1 = arr.map(item => item+2)
console.log(arr) // [4, 9, 16, 25]
console.log(arr1) // [6, 11, 18, 27]

.forEach()
forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数。
注意: forEach() 对于空数组是不会执行回调函数的。
tips: forEach()中不支持使用break(报错)和return(不能结束循环),有需要时可使用常规的for循环。
语法:
const arr= [4, 9, 16, 25];
const arr1 = [];
arr.forEach(item => arr1.push(item))
console.log(arr) // [4, 9, 16, 25]
console.log(arr1) // [4, 9, 16, 25]
 
.find()
find() 方法返回通过测试(函数内判断)的数组的第一个元素的值。
find() 方法为数组中的每个元素都调用一次函数执行:
当数组中的元素在测试条件时返回 true 时, find() 返回符合条件的元素,之后的值不会再调用执行函数。
如果没有符合条件的元素返回 undefined
注意: find() 对于空数组,函数是不会执行的。
注意: find() 并没有改变数组的原始值。
语法:
const arr= [4, 9, 16, 25];
const b = arr.find(item => item>10)
const c = arr.find(item => item<1)
console.log(arr) // [4, 9, 16, 25]
console.log(b) // 16
console.log(c) // undefined

.findIndex()
findIndex() 方法返回传入一个测试条件(函数)符合条件的数组第一个元素位置。
findIndex() 方法为数组中的每个元素都调用一次函数执行:
当数组中的元素在测试条件时返回 true 时, findIndex() 返回符合条件的元素的索引位置,之后的值不会再调用执行函数。
如果没有符合条件的元素返回 -1
注意: findIndex() 对于空数组,函数是不会执行的。
注意: findIndex() 并没有改变数组的原始值。
语法:
const arr= [4, 9, 16, 25];
const b = arr.findIndex(item => item>10)
const c = arr.findIndex(item => item<1)
console.log(arr) // [4, 9, 16, 25]
console.log(b) // 2
console.log(c) // -1
 
.some()
some() 方法用于检测数组中的元素是否满足指定条件(函数提供)。
some() 方法会依次执行数组的每个元素:
如果有一个元素满足条件,则表达式返回true , 剩余的元素不会再执行检测。
如果没有满足条件的元素,则返回false。
注意: some() 不会对空数组进行检测。
注意: some() 不会改变原始数组。
语法:
const arr= [4, 9, 16, 25];
const b = arr.some(item => item>10)
const c = arr.some(item => item<1)
console.log(arr) // [4, 9, 16, 25]
console.log(b) // true
console.log(c) // false
 
.every()
every() 方法用于检测数组所有元素是否都符合指定条件(通过函数提供)。
every() 方法使用指定函数检测数组中的所有元素:
如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行检测。
如果所有元素都满足条件,则返回 true。
注意: every() 不会对空数组进行检测。
注意: every() 不会改变原始数组。
语法:
const arr= [4, 9, 16, 25];
const b = arr.every(item => item>10)
const c = arr.every(item => item>1)
console.log(arr) // [4, 9, 16, 25]
console.log(b) // false
console.log(c) // true

2.父子组件传值

父组件:
<span @click="handleRun()">调用子组件</span>
<operatingCity v-if="showCity" :showCity="showCity" @setCityValue="getCityValue"/>
 
 data() {
   return {
     showCity: false,
   };
 },
 
 handleRun(){
   this.showCity = true;
 },
 getCityValue(val){
   this.showCity = val;
 }

子组件:
<template>
  <div>
    <el-dialog title="提示" :visible.sync="dialogCity" width="30%">
      <div>
        <span>子组件内容</span>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="handleClose">取 消</el-button>
        <el-button type="primary" @click="handleSubmit">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
export default {
  props: {
    showCity: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      dialogCity: false,
      param: {},
    };
  },
  created() {},
  mounted() {
    this.dialogCity = this.showCity;
  },
  methods: {
    handleSubmit() {
      this.dialogCity = false;
      this.$emit("setCityValue", false);
    },
    handleClose() {
      this.dialogCity = false;
      this.$emit("setCityValue", false);
    },
  },
};
</script>

3.Computed的使用

<template>
  <div class="hello">
    <!-- 写法1 -->
    <div>
      <label v-if="count < 0">111</label>
      <label v-else-if="count === 0">222</label>
      <label v-else-if="count <= 3">333</label>
      <label v-else-if="count < 15">444</label>
      <label v-else>555</label>
    </div>

    <!-- 写法2 -->
    <div>
      <label>{{countMsg}}</label>
    </div>

  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  data() {
    return {
      count: -21,
    };
  },
  methods: {},

  computed: {
    // 写法2
    countMsg() {
      if (this.count < 0) {
        return "111";
      } else if (this.count === 0) {
        return "222";
      } else if (this.count <= 3) {
        return "333";
      } else if (this.count < 15) {
        return "444";
      } else {
        return "555";
      }
    },
  },
};
</script>
<view class="expired" v-if="isExpired(item)">已过期</view>

computed: {
	// 计算过期的状态
	isExpired() {
		return function(item) {
			return new Date(item.expireTime) <= new Date();
		}
	}
	// 使用ES6的解构赋值,优化代码
    // isExpired: () => ({ expireTime }) => new Date(expireTime) < new Date()
},
优化前:
<el-table-column prop="productStatus" label="状态" min-width="120">
  <template slot-scope="scope">
    <span v-if="scope.row.productStatus === 'on_shelves' && scope.row.isSell == 0">停售</span>
    <span v-else-if="scope.row.productStatus === 'on_shelves' && scope.row.isSell == 1">在售</span>
    <span v-else-if="scope.row.productStatus === 'for_sale'">待发售</span>
    <span v-else-if="scope.row.productStatus === 'off_shelves'">已下架</span>
  </template>
</el-table-column>


优化后:
<el-table-column prop="productStatus" label="状态" min-width="120">
  <template slot-scope="scope">
    <span>{{ getStatusMsg(scope.row) }}</span>
  </template>
</el-table-column>

methods: {
  getStatusMsg(row) {
    if (row.productStatus === 'on_shelves' && row.isSell == 0) {
      return '停售';
    } else if (row.productStatus === 'on_shelves' && row.isSell == 1) {
      return '在售';
    } else if (row.productStatus === 'for_sale') {
      return '待发售';
    } else if (row.productStatus === 'off_shelves') {
      return '已下架';
    }
    return '';
  },
}

4.Watch的使用

//1.监听简单数据类型
<template>
  <div>
    <el-input v-model="mergeText"></el-input>
  </div>
</template>

<script>
export default {
  data() {
    return {
      mergeText:'',
    };
  },
  watch:{
    // mergeText值变化即触发
    mergeText(newval,oldVal){
      console.log(this.mergeText,newval,oldVal);
    }
  },
};
</script>

//2.监听复杂数据(深度监听 deep)
<template>
  <div>
    <el-input v-model="obj.text"></el-input>
  </div>
</template>

<script>
export default {
  data() {
    return {
      obj:{
        text:'hello'
      }
    };
  },
  watch:{
    // 监听对象obj的变化
    obj:{
      handler (newVal,oldval) {
        console.log(newVal,oldval)
      },
      deep: true,
      immediate: true
    }
  },
};
</script>

5.NextTick的使用

<template>
  <div class="box">{{msg}}</div>
</template>

<script>
export default {
  name: "index",
  data() {
    return {
      msg: "hello",
    };
  },
  mounted() {
    // console.log(box.innerHTML) // hello
    // 在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
    this.$nextTick(() => {
      console.log(box.innerHTML); // world
    });
    this.msg = "world";
    let box = document.getElementsByClassName("box")[0];
  },
};
</script>

6.Vue中实现函数的防抖和节流

// 防抖
function _debounce(fn, delay = 500) {
  var timer = null;
  return function () {
    var _this = this;
    var args = arguments;
    if (timer) clearTimeout(timer); 
    timer = setTimeout(function () {
      fn.apply(_this, args);
    }, delay);
  };
}

// 节流
function _throttle(fn,delay = 1000){
  var lastTime, timer, delay;
  return function(){
    var _this = this;
    var args = arguments;
    var nowTime = Date.now(); 
    if(lastTime && nowTime - lastTime < delay){
      if (timer) clearTimeout(timer); 
      timer = setTimeout(function(){
        lastTime = nowTime;
        fn.apply(_this,args);
      },delay)
    }else{
      lastTime = nowTime;
      fn.apply(_this,args);
    } 
  }
}  

export {
  _debounce,
  _throttle,
}
<template>
  <div class="about">
    <el-input v-model="inputVal" placeholder="请输入内容" @input="inputChange"></el-input>
  </div>
</template>

<script>
import {_debounce, _throttle} from '@/utils/index.js'
export default {
  data() {
    return {
      inputVal:'',
      count:0,
    };
  },
  methods: {
    // input值改变时触发
    inputChange:_debounce(function(){
      console.log(this.inputVal)
    },1000),
    // 滚动条滚动时触发
    scroll(){
      this.count += 1;
      console.log('scroll触发了'+ this.count +'次')
    }
  },
  mounted() {
    window.addEventListener('scroll', _throttle(this.scroll,5000));
  },
};
</script>

<style lang="stylus" scoped>
.about{
  width:100%;
  height:800px;
}
</style>

7.Vue中获取当前时间并实时刷新

<template>
  <div>
    {{nowDate}}{{nowWeek}}{{nowTime}}
  </div>
</template>

<script>
export default {
  data() {
    return {
      nowDate: "", // 当前日期
      nowTime: "", // 当前时间
      nowWeek: "", // 当前星期
    };
  },
  methods: {
    dealWithTime(data) {
      // 获取当前时间
      let Y = data.getFullYear();
      let M = data.getMonth() + 1;
      let D = data.getDate();
      let H = data.getHours();
      let Min = data.getMinutes();
      let S = data.getSeconds();
      let W = data.getDay();
      H = H < 10 ? "0" + H : H;
      Min = Min < 10 ? "0" + Min : Min;
      S = S < 10 ? "0" + S : S;
      switch (W) {
        case 0:
          W = "日";
          break;
        case 1:
          W = "一";
          break;
        case 2:
          W = "二";
          break;
        case 3:
          W = "三";
          break;
        case 4:
          W = "四";
          break;
        case 5:
          W = "五";
          break;
        case 6:
          W = "六";
          break;
        default:
          break;
      }
      this.nowDate = Y + "年" + M + "月" + D + "日 ";
      this.nowWeek = "周" + W;
      this.nowTime = H + ":" + Min + ":" + S;
    },
  },
  mounted() {
    // 页面加载完后显示当前时间
    this.dealWithTime(new Date());
    // 定时刷新时间
    this.timer = setInterval(() => {
      this.dealWithTime(new Date()); // 修改数据date
    }, 500);
  },
  destroyed() {
    if (this.timer) {
      // 注意在vue实例销毁前,清除我们的定时器
      clearInterval(this.timer);
    }
  },
};
</script>

8.Vue中iframe的内容加载慢,实现加载(Loading)效果

<template>
  <div style="height:1000px;" v-loading="loading">
    <iframe ref="Iframe" src="https://www.taobao.com/" width="100%" height="100%" frameborder="0">
    </iframe>
  </div>
</template>

<script>
export default {
  data() {
    return {
      loading: false,
    };
  },
  methods: {
    iframeLoad() {
      this.loading = true;
      const iframe = this.$refs.Iframe;
      if (iframe.attachEvent) {
        // IE
        iframe.attachEvent("onload", () => {
          this.loading = false;
        });
      } else {
        // 非IE
        iframe.onload = () => {
          this.loading = false;
        };
      }
    },
  },
  mounted() {
    this.iframeLoad();
  },
};
</script>

9.Vue中动态添加class

//添加单个
:class="name1 == '名称1' ? 'class1' : 'class2'"
//添加多个
:class="[name1 == '名称1' ? 'class1' : 'class2', name2 == '名称2' ? 'new1' : 'new2']"

10.Vue中时间格式转化

/*
1.转换带T的时间格式
举例:formDateT('2019-01-01T08:01:01') 
结果:2019-01-01 08:01:01
*/ 
export const formDateT = (data) => {
  if (!data) return;
  let dates = new Date(data).toJSON();
  return new Date(+new Date(dates) + 8 * 3600 * 1000)
    .toISOString()
    .replace(/T/g, " ")
    .replace(/.[\d]{3}Z/, "");
};

/*
2.计算两个时间相差的天、小时、分、秒
举例:timediff("2022-01-06 05:18:34", "2022-01-06 07:10:34")
结果:0天1小时52分0秒
*/
export const timediff = (startDate, endDate) => {
  if (!startDate || !endDate) return;
  //时间差的毫秒数
  let date3 = new Date(endDate).getTime() - new Date(startDate).getTime();
  //计算出相差天数
  let days = Math.floor(date3 / (24 * 3600 * 1000));
  //计算出小时数
  let leave1 = date3 % (24 * 3600 * 1000); //计算天数后剩余的毫秒数
  let hours = Math.floor(leave1 / (3600 * 1000));
  //计算相差分钟数
  let leave2 = leave1 % (3600 * 1000); //计算小时数后剩余的毫秒数
  let minutes = Math.floor(leave2 / (60 * 1000));
  //计算相差秒数
  let leave3 = leave2 % (60 * 1000); //计算分钟数后剩余的毫秒数
  let seconds = Math.round(leave3 / 1000);

  return days + "天" + hours + "小时" + minutes + "分" + seconds + "秒";
};

/*
3.时间戳转换成,yyyy-mm-dd hh:ii:ss格式
举例:formatDate(1641417514502)
结果:2022-01-06 05:18:34
*/
export const formatDate = (date) => {
  if (!date) return;
  let time = new Date(date);
  return (
    time.getFullYear() +
    "-" +
    (time.getMonth() + 1).toString().padStart(2, "0") +
    "-" +
    time.getDate().toString().padStart(2, "0") +
    "\xa0" +
    time.getHours().toString().padStart(2, "0") +
    ":" +
    time.getMinutes().toString().padStart(2, "0") +
    ":" +
    time.getSeconds().toString().padStart(2, "0")
  );
};

11.Element-ui中表格(Table)** 实现跨页多选数据——功能实现**

解决方案
1.在table一定要定义以下事件和列表属性:
row-key //写在table标签上
reserve-selection // 写在有选择框的那一列上

<el-table @selection-change="handleSelectionChange" :row-key="getRowKeys">
  ......
 </el-table>  //写在table标签上
 
 <el-table-column type="selection" :reserve-selection="true" width="40" align="center">
</el-table-column>   // 写在有选择框的那一列上 type 必须为 selection

2、在data上定义row-key绑定的
getRowKeys(row) {
    return row.id;
},

3、把勾选的数据传到后台所以在methods定义
handleSelectionChange(val) {
    this.multipleSelection = val;//勾选放在multipleSelection数组中
},

注:此时问题已解决,但是怎样进行清空已经选择的数据呢,代码如下。
使用后怎样清空数据
1、在表格上操作dom元素,设置ref属性
 <el-table @selection-change="handleSelectionChange" ref="multiTable" :row-key="getRowKeys">
  ......
 </el-table>

2、清空数据
在你点完确定后,调用此方法。比如是弹框,有个确定按钮,绑定的click事件为confirm,在methods里写confirm方法。
confirm(){
this.dialogvisible=false //关闭弹框
this.$refs.multiTable.clearSelection() //清除选中的数据
}
注:也可以在弹框刚打开的时候进行清空,在这里加个判断,判断是否有选中的数据,如果有执行this.$refs.multiTable.clearSelection() ,如果没有就不用清空。

12.Element-ui中表格(Table)实现表头、表格内容,任意格都可编辑实现

<template>
  <div class="app-container">
    <el-table :data="tableData" @cell-click="handleCellClick" @header-click="handleHeaderClick" :cell-class-name="cellClassName" style="width: 90%;align: center;cursor: pointer;" :header-cell-style="{ height: '50px' }" :row-style="{ height: '50px' }">
      <el-table-column :label="item.propName" :property="item.prop" v-for="item in tableColumnList" :key="item.prop" align="center">
        <template slot-scope="scope">
          <span>{{scope.row[scope.column.property]}}</span>
        </template>
      </el-table-column>
      <el-table-column label="添加项目流程" width="120" prop="addTableHeaderName" align="center" />
    </el-table>
    <el-dialog :visible.sync="dialogForHeader" title="修改项目流程名称" width="800">
      <el-form ref="form" :model="tableHeader" label-width="80px">
        <el-form-item label="表头名称">
          <el-input v-model="tableHeader.tableHeaderName" placeholder="请输入表头名称" />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="handleHeaderSubmit">确 定</el-button>
        <el-button @click="handleHeaderCancel">取 消</el-button>
      </div>
    </el-dialog>

    <el-dialog :visible.sync="dialogForTable" title="修改项目流程内容" width="800">
      <el-form ref="form" :model="tableCell" label-width="120px">
        <el-form-item label="流程内容名称">
          <el-input v-model="tableCell.tableCellData" placeholder="流程内容名称" />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="handleCellSubmit">确 定</el-button>
        <el-button @click="handleCellCancel">取 消</el-button>
      </div>
    </el-dialog>
  </div>
</template>
  
<script>
export default {
  data() {
    return {
      tableCellIndex: 0,
      TableColumnIndex: 0,
      tableCell: { tableCellData: "" },
      dialogForTable: false,
      num: 6,
      tableHeader: { tableHeaderName: "", property: "" },
      dialogForHeader: false,
      // 扩展:将tableColumnList和tableData当作字符串传给后端
      // 1.数组转化成字符串:JSON.stringify(tableData)
      // 2.字符串转化成数组:JSON.parse(tableData);
      tableColumnList: [
        { prop: "0", propName: "编号" },
        { prop: "1", propName: "名字" },
        { prop: "2", propName: "保质期" },
        { prop: "3", propName: "特点1" },
        { prop: "4", propName: "特点2" },
        { prop: "5", propName: "特点3" },
      ],
      tableData: [
        {
          0: "2016-05-01",
          1: "王小虎1",
          2: "上海市普陀区金沙江路 1518 弄",
          3: "2016-05-02",
          4: "王小虎",
          5: "上海市普陀区金沙江路 1518 弄",
        },
        {
          0: "2016-05-02",
          1: "王小虎2",
          2: "上海市普陀区金沙江路 1518 弄",
          3: "2016-05-02",
          4: "王小虎",
          5: "上海市普陀区金沙江路 1518 弄",
        },
        {
          0: "2016-05-03",
          1: "王小虎3",
          2: "上海市普陀区金沙江路 1518 弄",
          3: "2016-05-02",
          4: "王小虎",
          5: "上海市普陀区金沙江路 1518 弄",
        },
        {
          0: "2016-05-04",
          1: "王小虎4",
          2: "上海市普陀区金沙江路 1518 弄",
          3: "2016-05-02",
          4: "王小虎",
          5: "上海市普陀区金沙江路 1518 弄",
        },
        {
          0: "2016-05-05",
          1: "王小虎5",
          2: "上海市普陀区金沙江路 1518 弄",
          3: "2016-05-06",
          4: "王小虎",
          5: "上海市普陀区金沙江路 1518 弄",
        },
        {
          0: "2016-05-07",
          1: "王小虎6",
          2: "上海市普陀区金沙江路 1518 弄",
          3: "2016-05-02",
          4: "王小虎",
          5: "上海市普陀区金沙江路 1518 弄",
        },
      ],
    };
  },
  methods: {
    // 给每一行数据添加index,用来定位修改单元格
    cellClassName({ row, column, rowIndex, columnIndex }) {
      row.index = rowIndex;
      column.index = columnIndex;
    },
    // 修改表头
    handleHeaderClick(val) {
      if (val.property == "addTableHeaderName") {
        this.tableColumnList.push({
          prop: this.num.toString(),
          propName: "点击编辑项目流程名称",
        });
        for (let i = 0; i < this.tableData.length; i++) {
          this.$set(this.tableData[i], [parseInt(this.num)], "请添加内容");
        }
        this.num = this.num + 1;
      } else {
        this.tableHeader.tableHeaderName = val.label;
        this.tableHeader.property = val.property;
        this.dialogForHeader = true;
      }
    },
    // 修改单元格
    handleCellClick(row, column) {
      this.tableCellIndex = row.index;
      this.TableColumnIndex = column.index;
      this.tableCell.tableCellData = row[this.TableColumnIndex];
      this.dialogForTable = true;
    },
    handleHeaderSubmit() {
      this.tableColumnList.map((item, index) => {
        if (item.prop === this.tableHeader.property) {
          item.propName = this.tableHeader.tableHeaderName;
        }
      });
      this.dialogForHeader = false;
    },
    handleCellSubmit() {
      this.tableData[Number(this.tableCellIndex)][
        Number(this.TableColumnIndex)
      ] = this.tableCell.tableCellData;
      this.rush();
      this.dialogForTable = false;
    },
    //强制刷新数据
    rush() {
      this.$set(this.tableData);
    },
    handleHeaderCancel() {
      this.dialogForHeader = false;
    },
    handleCellCancel() {
      this.dialogForTable = false;
    },
  },
};
</script>

13.Element-ui中表格(Table)单元格内添加换行转义符

<template>
  <div class="home">
    <el-table :data="tableData" border style="width: 80%">
      <el-table-column align="center" prop="number" label="编号" width="180"></el-table-column>
      <el-table-column align="center" prop="name" label="姓名" width="180"></el-table-column>
      <el-table-column align="center" prop="address" label="地址"></el-table-column>
    </el-table>
  </div>
</template>

<script>
export default {
  data() {
    return {
      tableData: [
        {
          number: "20160503",
          name: "王小虎",
          address: "2016-05-03" + "\n" + "武汉市江夏区文化大道",
        },
        {
          number: "20160504",
          name: "张小虎",
          address: "2019-05-04" + "\n" + "武汉市洪山区洪山侧路",
        },
        {
          number: "20160501",
          name: "李小虎",
          address: "2020-05-01" + "\n" + "南京市建邺区白龙江东街",
        },
        {
          number: "20160502",
          name: "宋小虎",
          address: "2021-05-02" + "\n" + "南京市江宁区水阁路",
        },
      ],
    };
  },
};
</script>

<style lang="scss" scoped>
.home {
  ::v-deep .el-table {
    .cell {
      white-space: pre-line;
    }
  }
}
</style>

14.Element-ui中表格(Table)组件中滚动条样式修改

//1.修改单个滚动条样式
<style lang="scss" scoped>
.el-table {
	/deep/ .el-table__body-wrapper::-webkit-scrollbar {
	    width: 10px; /*滚动条宽度*/
	    height: 10px; /*滚动条高度*/
	}
	/*定义滚动条轨道 内阴影+圆角*/
	/deep/ .el-table__body-wrapper::-webkit-scrollbar-track {
	    box-shadow: 0px 1px 3px #071e4a inset; /*滚动条的背景区域的内阴影*/
	    border-radius: 10px; /*滚动条的背景区域的圆角*/
	    background-color: #071e4a; /*滚动条的背景颜色*/
	}
	/*定义滑块 内阴影+圆角*/
	/deep/ .el-table__body-wrapper::-webkit-scrollbar-thumb {
	    box-shadow: 0px 1px 3px #00a0e9 inset; /*滚动条的内阴影*/
	    border-radius: 10px; /*滚动条的圆角*/
	    background-color: #00a0e9; /*滚动条的背景颜色*/
	}
}
</style>

//2.修改全局滚动条样式(推荐)
<style lang="scss">
::-webkit-scrollbar {
  width: 6px;
  height: 8px;
  background-color: #ebeef5;
}
::-webkit-scrollbar-thumb {
  box-shadow: inset 0 0 6px rgba(0, 0, 0, .3);
  -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, .3);
  background-color: #ccc;
}
::-webkit-scrollbar-track{
  box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
  border-radius: 3px;
  background: rgba(255, 255, 255, 1);
}
</style>

15.Element-ui中表格 (Table) 组件中动态合并单元格

<template>
  <div class>
    <el-table
      :data="listData"
      :span-method="objectSpanMethod"
      border
      class="tableArea"
      style="width: 40%;"
    >
      <el-table-column label="商品类别" prop="productType" align="center" width="200"></el-table-column>
      <el-table-column label="商品数量" prop="amount" align="center"></el-table-column>
      <el-table-column label="商品价格" prop="price" align="center"></el-table-column>
      <el-table-column label="商品名称" prop="productName" width="200px" align="center"></el-table-column>
      <el-table-column label="更新时间" prop="updateTime" align="center"></el-table-column>
    </el-table>
  </div>
</template>
<script>
export default {
  data() {
    return {
      listData: [],
      testArr1: [],
      testArr2: [],
      testPosition1: 0,
      testPosition2: 0,
    };
  },
  methods: {
    // 获取数据
    queryData() {
      this.listData = [
        {
          id: "201808300001",
          productType: "纺织品",
          amount: 20,
          productName: "上衣",
          price: "80",
          updateTime: "2018-08-30",
        },
        {
          id: "201808300002",
          productType: "纺织品",
          amount: 20,
          productName: "裤子",
          price: "76",
          updateTime: "2018-08-31",
        },
        {
          id: "201808300003",
          productType: "皮制品",
          amount: 100,
          productName: "挎包",
          price: "150",
          updateTime: "2018-08-31",
        },

        {
          id: "201808300004",
          productType: "皮制品",
          amount: 180,
          productName: "鞋子",
          price: "76",
          updateTime: "2018-08-29",
        },
        {
          id: "201808300005",
          productType: "绸缎",
          amount: 80,
          productName: "旗袍",
          price: "106",
          updateTime: "2018-08-31",
        },
        {
          id: "201808300006",
          productType: "纺织品",
          amount: 20,
          productName: "短裙",
          price: "36",
          updateTime: "2018-08-30",
        },
        {
          id: "201808300007",
          productType: "纺织品",
          amount: 80,
          productName: "短袖",
          price: "36",
          updateTime: "2018-08-30",
        },
        {
          id: "201808300008",
          productType: "纺织品",
          amount: 20,
          productName: "短袖",
          price: "36",
          updateTime: "2018-08-30",
        },
        {
          id: "201808300009",
          productType: "皮制品",
          amount: 20,
          productName: "钱包",
          price: "60",
          updateTime: "2018-08-30",
        },
        {
          id: "201808300011",
          productType: "纺织品",
          amount: 90,
          productName: "手套",
          price: "60",
          updateTime: "2018-08-30",
        },
        {
          id: "201808300012",
          productType: "纺织品",
          amount: 90,
          productName: "袜子",
          price: "36",
          updateTime: "2018-08-30",
        },
        {
          id: "201808300013",
          productType: "饮料",
          amount: 100,
          productName: "雪碧",
          price: "5",
          updateTime: "2018-08-31",
        },
        {
          id: "201808300013",
          productType: "纺织品",
          amount: 100,
          productName: "风衣",
          price: "50",
          updateTime: "2018-08-31",
        },
      ];

      this.rowspan(this.testArr1, this.testPosition1, "productType");
      this.rowspan(this.testArr2, this.testPosition2, "amount");
    },
    rowspan(spanArr, position, spanName) {
      this.listData.forEach((item, index) => {
        if (index === 0) {
          spanArr.push(1);
          position = 0;
        } else {
          if (
            this.listData[index][spanName] ===
            this.listData[index - 1][spanName]
          ) {
            spanArr[position] += 1;
            spanArr.push(0);
          } else {
            spanArr.push(1);
            position = index;
          }
        }
      });
    },
    // 表格合并行
    objectSpanMethod({ row, column, rowIndex, columnIndex }) {
      if (columnIndex === 0) {
        const _row = this.testArr1[rowIndex];
        const _col = _row > 0 ? 1 : 0;
        return {
          rowspan: _row,
          colspan: _col,
        };
      }
      if (columnIndex === 1) {
        const _row = this.testArr2[rowIndex];
        const _col = _row > 0 ? 1 : 0;
        return {
          rowspan: _row,
          colspan: _col,
        };
      }
    },
  },
  mounted() {
    this.queryData();
  },
};
</script>

16.Element-ui中选择器(Select)解决数据量大导致渲染慢、页面卡顿的问题

// utils.js
function _debounce(fn, delay = 300) {
  var timer = null;
  return function () {
    var _this = this;
    var args = arguments;
    if (timer) clearTimeout(timer); 
    timer = setTimeout(function () {
      fn.apply(_this, args);
    }, delay);
  };
}
export {
  _debounce
}
<template>
  <div class="content">
    <el-select 
      v-model="chooseValue" clearable filterable :filter-method="filterMethod" 
      v-el-select-loadmore="loadMore(rangeNumber)"
      @visible-change="visibleChange">
      <el-option
        v-for="(item, index) in options.slice(0, rangeNumber)"
        :key="index"
        :label="item.label"
        :value="item.value">
      </el-option>
    </el-select>
  </div>
</template>
 
<script>
import {_debounce} from '@/utils/index.js'
export default {
  data() {
    return {
      chooseValue: "",
      options: [],
      rangeNumber: 10,
      resOptions:[],
    };
  },
  methods: { 
    // 模拟获取大量数据
    getList() {
      // 测试数据15000条数据, 这里数据多少条无所谓,options.slice(0, rangeNumber)方法只会默认加载初始的10条数据
      for (let i = 0; i < 25000; i++) {
        this.resOptions.push({label: "选择"+i,value:"选择"+i});
      } 
    },
    loadMore(n) {
      // n是默认初始展示的条数会在渲染的时候就可以获取,具体可以打log查看
      // elementui下拉超过7条才会出滚动条,如果初始不出滚动条无法触发loadMore方法
      return () => (this.rangeNumber += 5); // 每次滚动到底部可以新增条数  可自定义
    },
    // 筛选方法
    filterMethod:_debounce(function(filterVal){
      if(filterVal){
        let filterArr = this.resOptions.filter((item)=>{
          return item.label.toLowerCase().includes(filterVal.toLowerCase())
        })
        this.options = filterArr;
      }else{
        this.options = this.resOptions;
      }
    },500),
    // 下拉框出现时,调用过滤方法
    visibleChange(flag){
      if(flag){
        this.filterMethod()
      }
    },
  },
  beforeMount() {
    this.getList();
  },
  directives:{
    'el-select-loadmore':(el, binding) => {
      // 获取element-ui定义好的scroll盒子
      const SELECTWRAP_DOM = el.querySelector(".el-select-dropdown .el-select-dropdown__wrap");
      if(SELECTWRAP_DOM){
        SELECTWRAP_DOM.addEventListener("scroll", function () {
          /**
           * scrollHeight 获取元素内容高度(只读)
           * scrollTop 获取或者设置元素的偏移值,
           *  常用于:计算滚动条的位置, 当一个元素的容器没有产生垂直方向的滚动条, 那它的scrollTop的值默认为0.
           * clientHeight 读取元素的可见高度(只读)
           * 如果元素滚动到底, 下面等式返回true, 没有则返回false:
           * ele.scrollHeight - ele.scrollTop === ele.clientHeight;
           */
          const condition = this.scrollHeight - this.scrollTop <= this.clientHeight;
          if (condition) binding.value();
        });
      }
    },
  }
};
</script>

17.Element-ui中树形控件(Tree)实现只显示某一层级复选框且单选

<template>
  <div class="wrap">
    <el-tree :data="treeData" ref="tree" show-checkbox :check-strictly="true" node-key="id" :props="defaultProps" @check-change="treeCheckedChange">
    </el-tree>
  </div>
</template>

<script>
export default {
  data() {
    return {
      defaultProps: {
        children: "children",
        label: "label",
      },
      treeData: [],
      testdata: [
        {
          id: 1,
          label: "一级 1",
          children: [
            {
              id: 3,
              label: "二级 1-1",
              children: [
                {
                  id: 7,
                  label: "二级 1-1-1",
                },
              ],
            },
          ],
        },
        {
          id: 2,
          label: "一级 2",
          children: [
            {
              id: 4,
              label: "二级 2-1",
              children: [
                {
                  id: 5,
                  label: "三级 2-1-1",
                },
                {
                  id: 6,
                  label: "三级 2-1-2",
                },
              ],
            },
          ],
        },
      ],
    };
  },
  methods: {
    formatData(params) {
      let data = params;
      data.map((item) => {
        if (item.hasOwnProperty("children")) {
          item.disabled = true;
          this.formatData(item.children);
        }
      });
      return data;
    },
    treeCheckedChange(data, isChecked) {
      if (isChecked) {
        const checked = [data.id]; // id为tree的node-key属性
        this.$refs.tree.setCheckedKeys(checked);
      }
    },
  },
  mounted() {
    this.treeData = this.formatData(this.testdata);
  },
};
</script>

<style lang="scss" scoped>
.wrap {
  /deep/.el-checkbox__input.is-disabled {
    display: none;
  }
}
</style>

18.Element-ui中树形控件(Tree) 搜索目标子节点展示

<template>
    <div>
        <el-input
                placeholder="输入关键字进行过滤"
                v-model="filterText">
        </el-input>

        <div style="display: flex;justify-content: space-around">
            <div>
                <p style="color: red">修改后的查询</p>
                <el-tree :data="data1"
                         default-expand-all
                         ref="tree">
                </el-tree>
            </div>
            <div>
                <p style="color: red">element-ui 提供的查询</p>
                <el-tree :data="data1"
                         default-expand-all
                         :filter-node-method="filterNode"
                         ref="tree1">
                </el-tree>
            </div>
        </div>
    </div>
</template>
<script>
    export default {
        data() {
            return {
                filterText: '',
                data1: [{
                    id: 100,
                    label: '1263',
                    children: [
                        {
                            id: 100,
                            label: '852',
                        }, {
                            id: 111,
                            label: '369',
                        }, {
                            id: 852,
                            label: 'ki',
                            children: [
                                {
                                    id: 96,
                                    label: 'pp',
                                }
                            ]
                        },
                    ]
                }, {
                    id: 1,
                    label: '一级 1',
                    children: [{
                        id: 4,
                        label: 'gf',
                        children: [{
                            id: 23,
                            label: 'lk',
                            children: [
                                {
                                    id: 9,
                                    label: 'abnc'
                                }, {
                                    id: 11,
                                    label: 'abnc43'
                                }, {
                                    id: 10,
                                    label: '三级 1-1-2'
                                }
                            ]
                        }]
                    }]
                }, {
                    id: 2,
                    label: '一级 2',
                    children: [{
                        id: 5,
                        label: '二级 2-1',
                    }, {
                        id: 6,
                        label: '二级 2-2',
                    }]
                }, {
                    id: 3,
                    label: '一级 3',
                    children: [{
                        id: 56,
                        label: 'test',
                        children: [
                            {
                                id: 7,
                                label: '二级 3-1'
                            }, {
                                id: 8,
                                label: '二级 3-2'
                            }
                        ]
                    }]
                }],
            }
        },
        watch: {
            filterText(val) {
                this.filter(val)
                this.$refs.tree1.filter(val);
            }
        },
        methods: {
            /**
             * 遍历节点
             **/
            filterNode(value, data, node) {
                if (data.label.indexOf(value) !== -1) {
                    return true
                }
            },

            /**
             * 递归遍历设置那些节点展示,那些节点不展示
             **/
            filter(value) {
                const traverse = (node) => {
                    const childNodes = node.root ? node.root.childNodes : node.childNodes;

                    childNodes.forEach((child) => {
                        child.visible = this.filterNode(value, child.data, child);

                        traverse(child);
                    });

                    // node.visible为真,子节点也为真,就进行递归遍历设置子节点内容为展示状态
                    if (node.visible && node.childNodes.length) {
                        this.findChildNodes(node.childNodes);
                    }

                    if (!node.visible && childNodes.length) {
                        let allHidden = true;
                        allHidden = !childNodes.some(child => child.visible);

                        if (node.root) {
                            node.root.visible = allHidden === false;
                        } else {
                            node.visible = allHidden === false;
                        }
                    }
                    if (!value) return;

                    if (node.visible && !node.isLeaf) node.expand();
                };

                traverse(this.$refs.tree.store);
            },

            /**
             * 递归循环子节点
             * 设置过滤目标节点下面的子节点为展示状态
             **/
            findChildNodes(data){
                for (let item of data) {
                    item.visible = true;
                    if (item.childNodes.length) {
                        return this.findChildNodes(item.childNodes);
                    }
                }
            }
        },
    }
</script>

19.Element-ui中级联选择器 (Cascader)组装数据

<template>
  <div>
    <span>单选选择任意一级选项</span>
    <el-cascader v-model="areaId" :options="options" :props="areaProps" clearable></el-cascader>
    <span>{{areaId}}</span>
  </div>
</template>

<script>
export default {
  data() {
    return {
      areaId: "yizhi",
      areaProps: {
        label: "areaName",
        value: "areaId",
        children: "child",
        checkStrictly: true,
        emitPath: false,
      },
      options: [
        {
          areaId: "zhinan",
          areaName: "指南",
          child: [
            {
              areaId: "shejiyuanze",
              areaName: "设计原则",
              child: [
                {
                  areaId: "yizhi",
                  areaName: "一致",
                },
                {
                  areaId: "fankui",
                  areaName: "反馈",
                },
                {
                  areaId: "xiaolv",
                  areaName: "效率",
                },
                {
                  areaId: "kekong",
                  areaName: "可控",
                },
              ],
            },
            {
              areaId: "daohang",
              areaName: "导航",
              child: [
                {
                  areaId: "cexiangdaohang",
                  areaName: "侧向导航",
                },
                {
                  areaId: "dingbudaohang",
                  areaName: "顶部导航",
                },
              ],
            },
          ],
        },
      ],
    };
  },
};
</script>

20.Element-ui中表格(Table) 多选改为单选功能 

<template>
  <el-table :data="tableData" :row-key="row => row.id" :highlight-current-row="highlightCurrentRow" @row-click="handleRowClick">
    <!-- 将 type 属性设为 'selection' 的列移除,并在第一列中使用自定义的 radio 组件来实现单选功能 -->
    <el-table-column width="55" align="center">
      <template slot-scope="scope">
        <el-radio v-model="selectedRowId" :label="scope.row.id">
          <span class="radio-no-label"></span>
        </el-radio>
      </template>
    </el-table-column>
    <el-table-column prop="name" label="姓名"></el-table-column>
    <el-table-column prop="age" label="年龄"></el-table-column>
    <el-table-column prop="sex" label="性别"></el-table-column>
  </el-table>
</template>

<script>
export default {
  data() {
    return {
      tableData: [
        { id: 1, name: "张三", age: 18, sex: "男" },
        { id: 2, name: "李四", age: 20, sex: "女" },
        { id: 3, name: "王五", age: 22, sex: "男" },
      ],
      selectedRowId: null,
      highlightCurrentRow: true,
    };
  },
  methods: {
    // 处理行点击事件,将点击的行数据更新为选中的行数据
    handleRowClick(row) {
      this.selectedRowId = row.id;
    },
  },
};
</script>

<style scoped>
.radio-no-label {
  display: none;
}
</style>

21.vue实现日历备忘录

<template>
  <div class="vue-calendar">
    <div class="calendar-title">
      <div>
        <p>
          <i class="icon-arrow-left-year calendar-icon" @click="lastYear"><<</i>
          <i class="icon-arrow-left calendar-icon" @click="lastMonth"><</i>
        </p>
        <p>
          <span>{{ year }} 年 </span>
          <span> {{ month + 1 }} 月</span>
        </p>
        <p>
          <i class="icon-arrow-right calendar-icon" @click="nextMonth">></i>
          <i class="icon-arrow-right-year calendar-icon" @click="nextYear">>></i>
        </p>
      </div>
    </div>
    <table id="table">
      <thead>
      <tr>
        <th v-for="item in weekArray" :key="item">{{ item }}</th>
      </tr>
      </thead>
      <tbody>
      <tr v-for="(item, index) in dateArr" :key="index">
        <td v-for="(val, num) in item" :key="num" @click="handle(val)"
            :class="{'today':setClassToday(val)}">

          <span :class="`${val.class}`">{{ val.day }}</span>

          <div v-for="(textItem, index) in infoArr" :key="index">
            <template v-if="textItem.day === val.day && textItem.month === val.month && textItem.year === val.year">
              <span v-show="textItem.count">({{ textItem.count }} 条)</span>
              <div>
                <p v-for="(value, num) in textItem.taskCalendarList" :key="num">
                  {{ value }}
                </p>
              </div>
            </template>
          </div>
        </td>
      </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
export default {
  name: 'calendar',
  data() {
    return {
      activeIndex: null,
      dateArr: [],
      weekArray: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
      month: new Date().getMonth(),
      year: new Date().getFullYear(),
      day: new Date().getDate(),
      currentDate: new Date(),
      infoArr: [
        {
          year: new Date().getFullYear(),
          month: new Date().getMonth() + 1,
          day: 14,
          count: 5,
          taskCalendarList: ['07:00 嗷嗷嗷', '08:00 酷酷酷', '13:35 水水水水水', '18:20 斤斤计较', '20:00 噢噢噢噢']
        }
      ]
    }
  },
  mounted() {
    this.createDate()
  },
  methods: {
    /**
     * 日期计算逻辑
     **/
    createDate() {
      this.dateArr = [];
      let arr = [];
      let count = 0;
      let date = new Date(this.year, this.month);

      // setMonth(4) === 5月份,4 + 1 = 6月份
      // setDate(0) 为 setMonth(4) 设置月份的上个月的最后一天
      // 如:当前为5月份,setMonth(4 + 1)为6月份,setDate(0)设置的就是5月份的最后一天
      date.setMonth(this.month + 1);
      date.setDate(0);

      let lastDay = date.getDate(); // 获取最后一天

      // 按当前月份共有多少天循环创建数组
      for (let i = 0; i < lastDay; i++) {
        date.setDate(i + 1); // 设置date,用于获取星期

        // 每7条数据生成一个数组
        if (count < 6) {
          count = date.getDay() === 0 ? 6 : date.getDay() - 1; // 一周中的某一天作为数组的下标,因为每月1号的周数不一样。0 是星期天

          arr[count] = {day: i + 1, week: date.getDay(), month: this.month + 1, year: this.year};
        }

        if (arr.length === 7 || i === lastDay - 1) {
          this.dateArr.push(arr); // 生成二维数组
          count = 0; // 置0,从新开始
          arr = [];
        }
      }

      /**
       *  表格第一行,计算上个月日期
       **/
      let firstWeek = null;
      let firstArr = this.dateArr[0];
      date.setDate(0);

      // 计算第一行数组还需要循环几次填充满
      for (let item of firstArr) {
        if (item) {
          firstWeek = item.week === 0 ? 6 : item.week - 1; // 计算还差几列没有数据
          break;
        }
      }

      let day = date.getDate();
      // 循环填充满第一列数组
      for (let i = firstWeek; i > 0; i--) {
        date.setDate(day--);
        firstArr[date.getDay() - 1] = {
          day: date.getDate(),
          week: date.getDay(),
          month: this.month,
          year: this.month === 0 ? this.year - 1 : this.year,
          class: 'not-current-month',
        };
      }

      /**
       *  表格最后一行,计算下个月日期
       **/
      let lastDate = new Date(this.year, this.month + 1);
      let lastWeek = null; // 获取最后一个周数
      let lastArr = this.dateArr[this.dateArr.length - 1];
      let lastDateArray = []; // 用于新增一行数组

      // 计算最后一行数组还需要循环几次填充满
      for (let i = 0; i < 7; i++) {
        if (typeof lastArr[i] === "undefined") {
          lastWeek = 7 - lastArr[i - 1].week; // 计算还差几列没有数据
          break;
        }
      }

      if (lastWeek > 0) {
        // 循环填充满最后一行数组
        for (let i = 0; i < lastWeek; i++) {
          lastDate.setDate(i + 1);
          lastArr[lastDate.getDay() === 0 ? 6 : lastDate.getDay() - 1] = {
            day: lastDate.getDate(),
            week: lastDate.getDay(),
            month: this.month + 2,
            year: this.month + 2 === 12 ? this.year + 1 : this.year,
            class: 'not-current-month',
          };
        }
      }

      // dateArr新增一行数组
      if (this.dateArr.length < 6) {
        for (let i = 0; i < 7; i++) {
          lastDate.setDate(lastWeek + i + 1);
          lastDateArray.push({
            day: lastDate.getDate(),
            week: lastDate.getDay(),
            class: 'not-current-month',
            month: this.month + 2,
            year: this.month + 2 === 12 ? this.year + 1 : this.year
          });
        }
      }
      if (lastDateArray.length > 0) {
        this.dateArr.push(lastDateArray);
      }
    },

    /**
     * 当天日期设置高亮
     **/
    setClassToday(val) {
      return val.month === (this.currentDate.getMonth() + 1) && val.day === this.day && val.year === this.currentDate.getFullYear();
    },

    /**
     * 日期点击事件
     **/
    handle(val) {
      this.activeIndex = val.day;
      // 点击灰色的日期,跳转月份
      if (val.class === 'not-current-month') {
        if (val.month > this.month) {
          this.nextMonth()
        } else {
          this.lastMonth()
        }
      }
    },

    /**
     * 上个月
     **/
    lastMonth() {
      this.month--;
      if (this.month === -1) {
        this.month = 11;
        this.year--;
      }
      this.$nextTick(() => {
        this.createDate()
      })
    },

    /**
     * 下个月
     **/
    nextMonth() {
      this.month++;
      if (this.month === 12) {
        this.month = 0;
        this.year++
      }
      this.$nextTick(() => {
        this.createDate()
      })
    },

    /**
     * 下一年
     **/
    nextYear() {
      this.year += 1;
      this.$nextTick(() => {
        this.createDate()
      })
    },

    /**
     * 上一年
     **/
    lastYear() {
      this.year -= 1;
      this.$nextTick(() => {
        this.createDate()
      })
    }
  }
}
</script>

<style lang="scss">
.vue-calendar {
  height: 800px;

  .calendar-icon {
    cursor: pointer;
  }

  .icon-arrow-right-year {
    margin-left: 20px;
  }

  .icon-arrow-left-year {
    margin-right: 20px;
  }

  .calendar-title {
    font-size: 20px;
    text-align: center;
    margin-bottom: 10px;

    & > div {
      padding: 10px;
      display: flex;
      align-items: center;
      justify-content: space-between;
    }
  }

  #table {
    height: 100%;
    width: 100%;
    border-collapse: collapse;

    thead {
      text-align: center;

      tr {
        border: 1px #e2e2e2 solid;
        height: 50px;
      }
    }

    tbody {
      text-align: center;

      .today {
        background: #fb0;
        color: #ffffff;
      }

      td {
        cursor: pointer;
        width: 210px;
        border: 1px #e2e2e2 solid;
        padding: 0;
        font-size: 20px;
        position: relative;

        &:not(.today):hover {
          background: #e2e2e2;
        }

        & > span {
          position: absolute;
          top: 0;
          left: 10px;
        }

        .not-current-month {
          color: #c0c4cc;
        }

        div {
          height: 75%;
          position: absolute;
          width: 100%;
          bottom: 0;

          span {
            font-size: 20px;
            position: absolute;
            left: 30px;
            top: -32px;
          }

          div {
            position: relative;
            /*left: 23px;*/
            width: 100%;
            height: 100%;
            overflow: auto;

            p {
              white-space: nowrap;
              overflow: hidden;
              text-overflow: ellipsis;
              margin-bottom: 10px;
              font-size: 13px;
            }
          }
        }
      }
    }
  }
}
</style>

22.vue实现点击全屏效果,可具体让某个容器全屏

<template>
  <div>
    <el-button type="primary" @click="screen">全屏</el-button>
    <div id="con_lf_top_div" style="background: #ffffff;">
      <el-button type="primary">111</el-button>
      <el-button type="primary">222</el-button>
    </div>
  </div>
</template>

<script>
export default {
  name: "indexAss",

  data() {
    return {
      fullscreen: false,
    };
  },

  methods: {
    screen() {
      // let element = document.documentElement; //设置后就是我们平时的整个页面全屏效果
      let element = document.getElementById("con_lf_top_div"); //设置后就是   id==con_lf_top_div 的容器全屏
      if (this.fullscreen) {
        if (document.exitFullscreen) {
          document.exitFullscreen();
        } else if (document.webkitCancelFullScreen) {
          document.webkitCancelFullScreen();
        } else if (document.mozCancelFullScreen) {
          document.mozCancelFullScreen();
        } else if (document.msExitFullscreen) {
          document.msExitFullscreen();
        }
      } else {
        if (element.requestFullscreen) {
          element.requestFullscreen();
        } else if (element.webkitRequestFullScreen) {
          element.webkitRequestFullScreen();
        } else if (element.mozRequestFullScreen) {
          element.mozRequestFullScreen();
        } else if (element.msRequestFullscreen) {
          // IE11
          element.msRequestFullscreen();
        }
      }
      this.fullscreen = !this.fullscreen;
    },
  },
};
</script>

23.vue中实现滚动时钟效果

<template>
  <div class="wraper">
    <div class="column" :style="{transform: `translateY(${-lineHeight*index6}px)`}">
      <div class="num" v-for="(item, index) in arr6" :key="index">{{ item }}</div>
    </div>
 
    <div class="column" :style="{transform: `translateY(${-lineHeight*index5}px)`}">
      <div class="num" v-for="(item, index) in arr5" :key="index">{{ item }}</div>
    </div>
 
    <div>:</div>
 
    <div class="column" :style="{transform: `translateY(${-lineHeight*index4}px)`}">
      <div class="num" v-for="(item, index) in arr4" :key="index">{{ item }}</div>
    </div>
 
    <div class="column" :style="{transform: `translateY(${-lineHeight*index3}px)`}">
      <div class="num" v-for="(item, index) in arr3" :key="index">{{ item }}</div>
    </div>
 
    <div>:</div>
 
    <div class="column" :style="{transform: `translateY(${-lineHeight*index2}px)`}">
      <div class="num" v-for="(item, index) in arr2" :key="index">{{ item }}</div>
    </div>
 
    <div class="column" :style="{transform: `translateY(${-lineHeight*index1}px)`}">
      <div class="num" v-for="(item, index) in arr1" :key="index">{{ item }}</div>
    </div>
  </div>
</template>
 
<script>
  export default {
    data() {
      return {
        lineHeight: 64, //跟字体大小和wraper的高度相关!
        // 秒
        arr1: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
        index1: 0, //就是获取真实时间后的起始数字
        arr2: [0, 1, 2, 3, 4, 5],
        index2: 0,
        // 分
        arr3: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
        index3: 0,
        arr4: [0, 1, 2, 3, 4, 5],
        index4: 0,
        // 时
        arr5: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
        index5: 0,
        arr6: [0, 1, 2],
        index6: 0,
      }
    },
    created() {
      this.getTime()
    },
    watch: {
      index5(newVal) {
        // 超过24小时
        if (this.index6 === 2 && newVal===4) {
          console.log('out')
          for (let i=1; i<7; i++) {
            this[`index${i}`] = 0
          }
        }
      }
    },
    methods: {
      getTime() {
        const date = new Date()
        let hour = this.bu0(date.getHours())
        let minute = this.bu0(date.getMinutes())
        let second = this.bu0(date.getSeconds())
 
        // 测试用
        // let hour = ['1', '9']
        // let minute = ['5', '9']
        // let second = ['5', '5']
 
        // 秒
        this.index1 = +second[1]
        this.index2 = +second[0]
        // 分
        this.index3 = +minute[1]
        this.index4 = +minute[0]
        // 时
        this.index5 = +hour[1]
        this.index6 = +hour[0]
 
        this.turnSecond(this.arr1.length)
      },
      bu0(num) {
        let str
        if (num < 10) str = `0${num}`
        else str = `${num}`
        return str.split('')
      },
      turnSecond (length) {
        setInterval(()=> {
          if (this.index1 === length-1) {
            // console.log(1)
            // 通知前一位移动
            this.turnOther( 2, this.arr2.length)
            this.index1 = -1
          }
          this.index1++
        }, 1000)
      },
      turnOther(type, length) {
        // type代表第几组数列,例如2,就是从右往左第二列
        if (this[`index${type}`] === length-1) {
          // console.log(type)
          // 通知前一位移动
          let next = type+1
          this.turnOther( next, this[`arr${next}`].length)
 
          this[`index${type}`] = -1
        }
        this[`index${type}`]++
      }
    }
  }
</script>
 
<style scoped>
  .wraper {
    text-align: center;
    background: #ffffff;
    height: 64px;
    font-size: 48px;
    font-weight: bolder;
    letter-spacing: 7px;
    margin-top: 7px;
    display: flex;
    justify-content: center;
    overflow:hidden;
 
  }
  .column {
    transition: transform 300ms;
  }
  .num {
    height: 64px;
  }
</style>

24.vue表单校验

<template>
  <el-form ref="submitForm" :model="form" :rules="rules">
    <el-form-item label="用户名" prop="username">
      <el-input v-model="form.username"></el-input>
    </el-form-item>
    <el-form-item label="密码" prop="password">
      <el-input type="password" v-model="form.password"></el-input>
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="validateUser">校验-全部字段</el-button>
      <el-button type="primary" @click="validateUsername">校验-用户名字段</el-button>
    </el-form-item>
  </el-form>
</template>

<script>
export default {
  data() {
    return {
      form: {
        username: "",
        password: "",
      },
      rules: {
        username: [
          { required: true, message: "请输入用户名", trigger: "blur" },
        ],
        password: [{ required: true, message: "请输入密码", trigger: "blur" }],
      },
    };
  },
  methods: {
    validateUser() {
      // 校验用户名和密码字段
      this.$refs.submitForm.validate((valid) => {
        if (valid) {
          this.$message.success("校验密码登录成功");
        }
      });
    },
    validateUsername() {
      // 校验用户名字段,不检验密码字段
      this.$refs.submitForm.validateField("username", (valid) => {
        if (!valid) {
          this.$message.success("不校验密码登录");
        }
      });
    },
  },
};
</script>

25.vue弹框和分页查询(高频使用)

<template>
  <div>
    <el-button type="primary" @click="handleOpenDialog">弹框-表格</el-button>
    <el-dialog title="提示" :visible.sync="dialogVisible" width="60%">
      <el-form :inline="true" class="demo-form-inline" size="medium">
        <el-form-item label="名称">
          <el-input v-model="searchInput" placeholder="请输入" @keyup.enter.native="handleQueryForm"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button size="small" type="primary" @click="handleQueryForm">查询</el-button>
        </el-form-item>
      </el-form>
      <!-- 普通表格 -->
      <el-table :data="dataTable" :row-key="getRowKey" border height="400px" style="width: 100%">
        <el-table-column label="序号" width="60" align="center">
          <template v-slot="scope">{{ ( pageParam.pageNum - 1) * pageParam.pageSize + (scope.$index + 1) }}</template>
        </el-table-column>
        <el-table-column label="编号" prop="merchantCode" align="center"></el-table-column>
        <el-table-column label="名称" prop="merchantName" align="center"></el-table-column>
      </el-table>
      <!-- 单选表格 -->
      <!-- <el-table ref="multiTable" :data="dataTable" @row-click="handleRowClick" :row-key="getRowKey" :highlight-current-row="true" border height="400px" style="width: 100%">
        <el-table-column width="60" align="center">
          <template slot-scope="scope">
            <el-radio v-model="radio" :label="scope.row.merchantId">
              <span></span>
            </el-radio>
          </template>
        </el-table-column>
        <el-table-column label="商家编号" prop="merchantCode" align="center"></el-table-column>
        <el-table-column label="商家名称" prop="merchantName" align="center"></el-table-column>
      </el-table> -->
      <!-- 多选表格 -->
      <!-- <el-table ref="multiTable" :data="dataTable" @selection-change="handleSelectionChange" :row-key="getRowKey" border height="400px" style="width: 100%">
        <el-table-column type="selection" width="60" :reserve-selection="true" align="center"></el-table-column>
        <el-table-column label="编号" prop="merchantCode" align="center"></el-table-column>
        <el-table-column label="名称" prop="merchantName" align="center"></el-table-column>
      </el-table> -->
      <div class="pagination">
        <el-pagination :current-page="pageParam.pageNum" :page-size="pageParam.pageSize" :page-sizes="[10, 20, 50, 100, 200, 1000]" :total="pageParam.total" background layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange" @current-change="handleCurrentChange"></el-pagination>
      </div>
      <span slot="footer">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="dialogVisible = false">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
export default {
  data() {
    return {
      dialogVisible: false, // 弹框
      pageParam: {
        pageNum: 1,
        pageSize: 10,
        total: 0,
      },
      dataTable: [], // 表格的数据
      selectedRows: [], // 选中的行
      searchInput: "", // 输入框查询条件
      radio: null, // 单选按钮
    };
  },
  created() {},
  methods: {
    // 点击按钮弹框
    handleOpenDialog() {
      this.initQuery();
      this.dialogVisible = true;
    },
    initQuery() {
      // 打开弹窗时重置radio状态
      // this.radio = null;
      // 打开弹窗时重置勾选状态
      // this.$refs.multiTable && this.$refs.multiTable.clearSelection();
      this.pageParam.pageNum = 1;
      this.handleQueryForm();
    },
    // 查询表格
    handleQueryForm() {
      let requestData = {
        pageNum: this.pageParam.pageNum,
        pageSize: this.pageParam.pageSize,
        param: {
          merchantName: this.searchInput,
        },
      };
      this.$http
        .requestPost({
          url: "/customer/merchant/page",
          param: requestData,
        })
        .then((res) => {
          this.dataTable = res.data.list;
          this.pageParam.total = res.data.total;
        })
        .catch((err) => {
          console.log(err);
        });
    },
    // pageSize改变时会触发
    handleSizeChange(size) {
      this.pageParam.pageNum = 1;
      this.pageParam.pageSize = size;
      this.handleQueryForm();
    },
    // currentPage改变时会触发
    handleCurrentChange(page) {
      this.pageParam.pageNum = page;
      this.handleQueryForm();
    },
    // 行数据的Key,用来优化Table的渲染
    getRowKey(row) {
      return row.merchantId;
    },
    // 当某一行被点击时会触发该事件
    handleRowClick(row) {
      // 更新选中状态
      this.radio = row.merchantId;
      this.selectedRows = row;
      console.log("单选======", this.selectedRows);
    },
    // 当选择项发生变化时会触发该事件
    handleSelectionChange(row) {
      this.selectedRows = row;
      console.log("多选======", this.selectedRows);
    },
  },
};
</script>

<style lang="scss" scoped>
</style>

26.vue中导出Execl

async handleReport(){
  var res;
  let param = {
    year: this.inquire.year,
    month: this.inquire.month
  }
  // res将文件转成Blob二进制流
  res = await zyExportDetails(param, "post")
  try{
    this.$public.downloadFile(res);
    this.$message.success("导出成功!");
    }catch(error){
      console.log(error)
      this.$message.error("导出失败!");
    }
},
// 流文件下载
function downloadFile(res) {
    var blob = res.data;
    console.log(res)
    // FileReader主要用于将文件内容读入内存
    var reader = new FileReader();
    console.log(reader)
    reader.readAsDataURL(blob);
    // onload当读取操作成功完成时调用
    reader.onload = function(e) {
        var a = document.createElement('a');
        // 获取文件名fileName
        var fileName = res.headers.filename;
        a.download = fileName;
        a.href = e.target.result;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
    }
}

export default {
    downloadFile,
}

27.用axios跨域调用的接口

<template>
  <div class="container">
    <el-form :inline="true" size="medium">
      <el-form-item label="名称">
        <el-input v-model="searchInput" placeholder="请输入"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button size="small" type="primary" @click="handleQueryForm">查询</el-button>
      </el-form-item>
    </el-form>
    <!-- 普通表格 -->
    <el-table :data="dataTable" border height="400px" style="width: 100%">
      <el-table-column label="序号" width="60" align="center" type="index"></el-table-column>
      <el-table-column label="编号" prop="merchantCode" align="center"></el-table-column>
      <el-table-column label="名称" prop="merchantName" align="center"></el-table-column>
    </el-table>
    <div class="pagination">
      <el-pagination :current-page="pageParam.pageNum" :page-size="pageParam.pageSize" :page-sizes="[10, 20, 50, 100, 200, 1000]" :total="pageParam.total" background layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange" @current-change="handleCurrentChange"></el-pagination>
    </div>
  </div>
</template>
 
<script>
import axios from "axios";
export default {
  data() {
    return {
      pageParam: {
        pageNum: 1,
        pageSize: 10,
        total: 0,
      },
      dataTable: [], // 表格的数据
      searchInput: "", // 输入框查询条件
    };
  },
  created() {
    this.initQuery();
  },
  methods: {
    initQuery() {
      this.pageParam.pageNum = 1;
      this.handleQueryForm();
    },
    // 查询表格
    handleQueryForm() {
      let requestData = {
        pageNum: this.pageParam.pageNum,
        pageSize: this.pageParam.pageSize,
        param: {
          merchantName: this.searchInput,
        },
      };
      axios({
        method: "post",
        url: "http://dev-manager-api.638yipin.uyaoku.com/management/customer/merchant/page",
        data: requestData,
        responseType: "application/json;charset=utf-8",
        headers: { Authorization: "d817b9e319fe46a189b642c137ea196b" },
      }).then((res) => {
        this.dataTable = res.data.data.list;
        this.pageParam.total = res.data.data.total;
      });
    },
    // pageSize改变时会触发
    handleSizeChange(size) {
      this.pageParam.pageNum = 1;
      this.pageParam.pageSize = size;
      this.handleQueryForm();
    },
    // currentPage改变时会触发
    handleCurrentChange(page) {
      this.pageParam.pageNum = page;
      this.handleQueryForm();
    },
  },
};
</script>
 
<style lang="scss" scoped>
.container {
  padding: 20px;
}
.pagination {
  margin-top: 10px;
  text-align: end;
}
</style>

28.vue封装普通表格+分页+操作栏(高频)

<template>
  <div class="container">
    <el-form :inline="true" size="medium">
      <el-form-item label="名称">
        <el-input v-model="searchInput" placeholder="请输入"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button size="small" type="primary" @click="fetchData">查询</el-button>
      </el-form-item>
    </el-form>
    <!-- 普通表格 -->
    <TableList :tableData="dataTable" :tableHeader="tableHeader" :pageNum="pageParam.pageNum" :total="pageParam.total" :isShowPage="true" :isShowIndex="true">
      <!-- #operation 插槽对应的名称(列配置项声明的插槽名称) data插槽返回的行数据  -->
      <template #operation='{data}'>
        <el-button size="mini" icon="el-icon-edit" @click="handleEdit(data)" type="success">编辑</el-button>
      </template>
    </TableList>
  </div>
</template>
 
<script>
import axios from "axios";
import TableList from "@/components/TableList";
export default {
  components: {
    TableList,
  },
  data() {
    return {
      pageParam: {
        pageNum: 1,
        pageSize: 10,
        total: 0,
      },
      tableHeader: [
        {
          label: "编号",
          prop: "merchantCode",
        },
        {
          label: "名称",
          prop: "merchantName",
        },
        {
          label: "操作",
          type: "slot", //slot插槽
          slotName: "operation", //插槽名称(html表格组件内声明此插槽)
        },
      ],
      dataTable: [], // 表格的数据
      searchInput: "", // 输入框查询条件
    };
  },
  created() {
    this.initQuery();
  },
  methods: {
    initQuery() {
      this.pageParam.pageNum = 1;
      this.fetchData();
    },
    // 查询表格
    fetchData() {
      let requestData = {
        pageNum: this.pageParam.pageNum,
        pageSize: this.pageParam.pageSize,
        param: {
          merchantName: this.searchInput,
        },
      };
      axios({
        method: "post",
        url: "http://dev-manager-api.638yipin.uyaoku.com/management/customer/merchant/page",
        data: requestData,
        responseType: "application/json;charset=utf-8",
        headers: { Authorization: "53ea34b9a74c4660b4a982f24699f243" },
      }).then((res) => {
        this.dataTable = res.data.data.list;
        this.pageParam.total = res.data.data.total;
      });
    },
    //表格每页数量改变触发
    setSize(size) {
      this.pageParam.pageNum = 1;
      this.pageParam.pageSize = size;
      this.fetchData();
    },
    //表格当前页数改变触发
    setPage(page) {
      this.pageParam.pageNum = page;
      this.fetchData();
    },
    // 编辑按钮
    handleEdit(row) {
      console.log("row======", row);
    },
  },
};
</script>
 
<style lang="scss" scoped>
.container {
  padding: 20px;
}
</style>
<template>
  <div id="tables">
    <!-- table 表格 -->
    <el-table id="ou" size="mini" :cell-style="{ textAlign: 'center' }" :header-cell-style="{ background: '#4e9aef', color: '#fff', textAlign: 'center' }" :border="true" :data="tableData" ref="multipleTable" style="width: 100%" max-height="400px">
      <el-table-column v-if="isShowIndex" type="index" label="序号" width="50"></el-table-column>
      <el-table-column v-for="(item, index) in tableHeader" :key="index" :prop="item.prop" :label="item.label" :min-width="item.width">
        <template v-if="item.type === 'slot'" #default="{ row }">
          <slot :name="item.slotName" :data="row"></slot>
        </template>
      </el-table-column>
    </el-table>
    <!-- table end -->
    <!-- 分页器 -->
    <div class="pagination" v-if="isShowPage">
      <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="pageNum" :page-sizes="[10, 20, 50, 100]" :page-size="10" layout="total, sizes, prev, pager, next, jumper" :total="total">
      </el-pagination>
    </div>
  </div>
</template>
 
<script>
export default {
  props: {
    // 表格数据
    tableData: {
      type: Array,
      default: () => [],
    },
    // 表格头部
    tableHeader: {
      type: Array,
      default: () => [],
    },
    // 分页器页数
    pageNum: {
      type: Number,
      default: 0,
    },
    // 总条数
    total: {
      type: Number,
      default: 0,
    },
    // 是否显示分页器
    isShowPage: {
      type: Boolean,
      default: true,
    },
    // 是否显示表格序号
    isShowIndex: {
      type: Boolean,
      default: true,
    },
  },
  data() {
    return {};
  },
  methods: {
    //每页条数
    handleSizeChange(val) {
      this.$parent.setSize(val);
    },
    //当前页数/页数切换
    handleCurrentChange(val) {
      this.$parent.setPage(val);
    },
  },
};
</script>
 
<style scoped lang="scss">
.pagination {
  margin-top: 10px;
  text-align: end;
}
</style>

29.uniapp刷新前一个页面的数据

setTimeout(() => {
	let pages = getCurrentPages(); //获取所有页面栈实例列表
	let prevPage = pages[pages.length - 2]; //上一页页面实例
	prevPage.$vm.initData(); //$vm后面是需要调用的上一个页面的方法和对象
	uni.navigateBack({
		delta:1
	})
}, 1500)

30.uniapp在小程序和app使用视频播放组件

// 小程序
<!-- enable-play-gesture:双击暂停或播放   show-mute-btn:静音按钮 -->
<!-- #ifdef MP-WEIXIN  -->
<video style="width:100%;height:100%;" :src="videoAddress" :show-mute-btn="true" :enable-play-gesture="true" title="名医科普"></video>
<!-- #endif -->

// app
<!-- #ifdef APP-PLUS -->
<view v-if="videoAddress">
  <!-- 处理video在APP中层级过高问题 -->
  <view style="width:100%;height:100%;" v-html="videoContent"></view>
</view>
<!-- #endif -->

data(){
    return{
        videoAddress:'',  // 小程序:字段是.map4格式
        videoContent: '',  // app:video标签转html  
    }
}

methods:{
    getVideoDetail(){
        this.videoAddress = res.videoAddress;
	    this.videoContent = res.videoAddress ? `<video src="${res.videoAddress}" controls style="width:100%;height:400px;z-index: 1;" mode="aspectFill"></video>` : '';
    }
}    

31.uniapp自定义弹框

<u-popup v-model="modelShow" :maskCloseAble="false" mode="center" width="540rpx" border-radius="20">
	<view style="padding: 20rpx;">
    <view style="font-size: 32rpx;text-align: center;font-weight: bold;">服务协议和隐私政策</view>
    <view style="font-size: 28rpx;margin-top: 20rpx;">
    请你务必审慎阅读,充分理解“服务协议”和“隐私政策”各条款,包括但不限于:为了向你提供即时通讯、内容分享等服务,我们需要收集你的设备信息、操作日志等个人信息。你可以在“设置”中查看、变更、删除个人信息并管理你的授权。<br/>你可阅读
    <text style="color:#2979ff;">《服务协议》</text><text style="color:#2979ff;">《隐私政策》</text>
    了解详细信息。如你同意,请点击“同意”开始接收我们的服务。
    </view>
    <view style="display: flex;justify-content: space-between;padding: 20rpx;font-size: 28rpx;margin: 10rpx 0 10rpx 0;">
      <view style="width: 200rpx;height: 60rpx;border-radius: 32rpx;text-align: center;color: #6d9fe8;background: #fff;border: 1px solid #6d9fe8;line-height: 60rpx;">暂不使用</view>
      <view style="width: 200rpx;height: 60rpx;border-radius: 32rpx;text-align: center;color: #fff;background: #6d9fe8;line-height: 60rpx;">同意</view>
    </view>
    </view>
</u-popup>

32.响应式布局-媒体查询

// 1.设置 meta 标签
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">

// 2.使用 @media 设置样式
// 屏幕大于 1024px 或小于 1440px 时应用该样式
@media screen and (min-width: 1024px) and (max-width: 1440px) { 
  ...
}

// 3.依据要求并结合屏幕尺寸设置布局分界点
// 屏幕大于 1440px 时应用该样式
@media screen and (min-width: 1441px) { 
  ...
}
// 屏幕大于 1024px 或小于 1440px 时应用该样式
@media screen and (min-width: 1024px) and (max-width: 1440px) { 
  ...
}

// https://www.strerr.com/screen.html  手机屏幕尺寸大全
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <!-- 浏览器需要下面一行才能正确响应响应式布局 -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />

    <style>
      /* 公共样式 */
      body {
        margin: 0;
        padding: 0;
      }

      /* 移动端样式 */
      @media (max-width: 767px) {
        .container {
          background: #f0f8ff;
        }

        .title {
          font-size: 24px;
          text-align: center;
        }
      }

      /* PC 端样式 */
      @media (min-width: 768px) {
        .container {
          background: #ffffff;
        }

        .title {
          font-size: 36px;
          text-align: center;
        }
      }
    </style>
  </head>
  <body>
    <div class="container">
      <h1 class="title">PC/Mobile Demo</h1>
    </div>
  </body>
</html>

33.uniapp添加隐私协议弹框

// 打开项目的manifest.json文件,切换到“App启动界面配置”,在“Android启动界面样式”中勾选“使用原生隐私政策提示框”
// 勾选后会在项目中自动添加androidPrivacy.json文件

{
    "version" : "1",
    "prompt" : "template",
    "title" : "用户协议和隐私政策",
    "message" : "  请你务必审慎阅读、充分理解“用户协议”和“隐私政策”各条款,包括但不限于:为了更好的向你提供服务,我们需要收集你的设备标识、操作日志等信息用于分析、优化应用性能。<br/>  你可阅读<a href="static\htmls\userAgreement.html?type=1" >《用户协议》</a>和<a href="static\htmls\userAgreement.html?type=2">《隐私政策》</a>了解详细信息。如果你同意,请点击下面按钮开始接受我们的服务。",
    "buttonAccept" : "同意",
    "buttonRefuse" : "暂不使用",
    "hrefLoader" : "system|default",
    "second" : {
        "title" : "确认提示",
        "message" : "  进入应用前,你需先同意<a href="static\htmls\userAgreement.html?type=1">《用户协议》</a>和<a href="static\htmls\userAgreement.html?type=2">《隐私政策》</a>,否则将退出应用。",
        "buttonAccept" : "同意并继续",
        "buttonRefuse" : "退出应用"
    },
    "styles" : {
        "backgroundColor" : "#fff",
        "borderRadius" : "5px",
        "title" : {
            "color" : "#000"
        },
        "buttonAccept" : {
            "color" : "#fff"
        },
        "buttonRefuse" : {
            "color" : "#cccccc"
        }
    }
}
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>用户协议&隐私政策</title>
        <meta
            content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no"
            name="viewport" />
        <style type="text/css">
            * {
                margin: 0;
                padding: 0;
            }
            #title {
                width: 100vw;
                height: 50px;
                /* background-color: #FFFFFF; */
                display: flex;
                align-items: center;
                justify-content: center;
            }

            #text {
                border: none;
                width: 100vw;
                height: 100vh;
                box-sizing: border-box;
                padding: 20px;
                background-color: #ffffff;
                color: #333333;
                font-size: 14px;
                line-height: 20px;
            }
        </style>
    </head>
    <body>
        <div id="title"></div>
        <div disabled="true" id="text"></div>
    </body>
</html>
<script type="text/javascript">
    const url = "https://user-api.638yipin.com/mine/setting/protocol/";

    let type = 1;

    function parseQueryString(url) {
		const urlKey = url.split('?')[1]
		const objKeyValue = {}
		if (!urlKey) return objKeyValue
		const urlObj = urlKey.split('&')
		for (let i = 0; i < urlObj.length; i++) {
			objKeyValue[urlObj[i].split('=')[0]] = decodeURI(urlObj[i].split('=')[1])
		}
		return objKeyValue
	}

	const urlParams = parseQueryString(window.location.href)
    type = urlParams.type;
    const httpRequest = new XMLHttpRequest(); //第一步:创建需要的对象
    httpRequest.open("GET", url + type, true); //第二步:打开连接/***发送json格式文件必须设置请求头 ;如下 - */
    // httpRequest.setRequestHeader('Content-type',
    // 	'application/json') //设置请求头 注:post方式必须设置请求头(在建立连接后设置请求头
    httpRequest.send(); //发送请求
    // 获取数据后的处理程序
    httpRequest.onreadystatechange = function () {
        //请求后的回调接口,可将请求成功后要执行的程序写在其中
        // console.log(httpRequest);
        if (httpRequest.readyState == 4 && httpRequest.status == 200) {
            //验证请求是否发送成功
            const res = JSON.parse(httpRequest.responseText); //获取到服务端返回的数据
            // console.log(res);
            if (res.message == "OK") {
                document.getElementById("text").innerHTML =
                    res.data.protocolContent;
                document.getElementById("title").innerHTML =
                    res.data.protocolName;
            }
        }
    };
</script>

34.处理video在App中层级过高的问题

<!-- #ifdef MP-WEIXIN -->
<!-- enable-play-gesture:双击暂停或播放   show-mute-btn:静音按钮 -->
<view class="video_wrapper">
	<video style="width:100%;height:400rpx;" :poster="content.messageTopCover" object-fit="cover" :src="content.topVideo" :show-mute-btn="true" :enable-play-gesture="true"></video>
</view>
<!-- #endif -->
<!-- #ifdef APP-PLUS -->
<view class="video_wrapper">
<!-- 处理video在APP中层级过高问题 -->
	<view class="video-box" v-html="content.topVideoApp"></view>
</view>
<!-- #endif -->

this.content.topVideoApp = `<video src="${topVideo}" poster="${messageTopCover}" object-fit="cover" controls width="100%" height="720rpx" style="width:100%;height:100%; z-index: 1;" mode="aspectFill"></video>`;