vue2+ElementUI开发中遇到的问题的解决办法

664 阅读13分钟

1、项目中用到了Echars图表,需要把页面显示的Echars图表,下载下来

  • (1) 需要下载第三方包:html2canvas

npm install --save html2canvas

  • (2) 在vue页面使用,代码如下
第一步:导入下载的包
// import html2canvas from 'html2canvas'
第二步:开始使用,点击下载按钮,下载Echars图片
// 下载echars图片到本地电脑
// 找到echaers图表对应的dom元素
const echartsIdDom = this.$children[1].$refs.echartsId
// 将echarts图表转换为canvas,并将canvas下载为图片
// 图表转换成canvas
// html2canvas(document.getElementById('download')).then(function(canvas) {
html2canvas(echartsIdDom).then(function(canvas) {
const img = canvas.toDataURL('image/png').replace('image/png', 'image/octet-stream')
// 创建a标签,实现下载
const creatIMg = document.createElement('a')
creatIMg.download = '页面图表.png' // 设置下载的文件名,
creatIMg.href = img // 下载url
document.body.appendChild(creatIMg)
creatIMg.click()
creatIMg.remove() // 下载之后把创建的元素删除
})

2、项目中用到了用到了element ui 中的table组件,发现数据已经更新了,但是页面还是之前的老数据,页面不刷新

(1)用this.set()不管用(2)用this.set() 不管用 (2)用this.forceUpdate() 不管用
(3)最后使用暴力的手段,先把组件删除掉,等新的数据更新后,再把组件重新创建加载出来

data(){
    hackReset: false // 关键点在这里
}

<template v-if="hackReset"> // 关键点在这里
  <el-table-column v-for="(column, colIdx) in tabData[item.name].indicatorDataList" :key="column.key" :prop="column.id" :label="column.name" sortable align="center" width="173">
    <template slot="header">
      <span>{{ column.name }}</span>
      <span v-show="tableArgFlag" class="argFlag">
      <br v-show="column.paramList.length > 0">
      <span v-for="i in column.paramList">{{ i.name }}:{{ i.value }}<br></span>
    </span>
    </template>
    <!--  动态列的值-->
    <template v-if="tabData[item.name].valueDataList.length > colIdx" slot-scope="scope">
      {{ tabData[item.name].valueDataList[colIdx][scope.$index] }}
    </template>
  </el-table-column>
</template>

methods: {
   myFun(){
       this.$api.indexBrowser.BatchqueryIndicatorValueData(paramsData).then((res) => {
           if (res.code === '200') {
               // 为了解决修改参数按钮中的item位置互换后,表格动态列不刷新的现象,数据修改的时候,删除动态列组件
                this.hackReset = false // 关键点在这里
                this.$nextTick(() => {
                  这里处理数据更新成后台返回的数据。。。。。。
                  this.hackReset = true // 关键点在这里
                })
           }
       }
   }

}

image.png

3、使用elementui,第一个table在父组件,第二个table在子组件,最终实现2个table表格的横向联动

父组件的table 和 子组件的table 都是第一列固定的情况,不固定应该也可以实现
在父组件中的代码如下:

<template>
    <子组件 :tableWrapAllRowsData="tableWrapAllRowsData"></子组件>
</template>
<script>
    data() {
    return {
      tableWrapAllRowsData: 0, // 页面包裹table表格所有行的div,距离屏幕左侧距离
      }
  },
 mounted() {
    // 给window添加一个滚动监听事件 ==> 实现页面表格和统计特征表格的联动效果需要的代码
    window.addEventListener('scroll', this.handleScroll, true)
  },
  
  methods: {
    handleScroll() {
      // 找到父组件对应的table表格,获取滚动的时候,滚动的距离 
      this.tableWrapAllRowsData = document.querySelector('.el-table__body').getBoundingClientRect().left
    },
 }
</script>
 

在子组件中的代码如下:

props: {
    // 页面和统计特征页面的表格联动,传递的是页面table内容数据滚动的距离
    tableWrapAllRowsData: {
      type: Number,
      default: 0
    }
  },
  
watch: {
    tableWrapAllRowsData: {
      deep: true,
      immediate: true,
      handler(newVal, oldVal) {
        // 找到当前子组件对应的table表格
        const needMoveDOM = document.querySelectorAll('.el-table__body')
        if (needMoveDOM.length >= 3) {
          // 父组件table表格滚动的距离 + 统计特征页面tables表格前3列的值+中间的间隙的距离,才是统计特征页面tables表格动态列滚动的距离
          needMoveDOM[2].style.left = (Number(newVal) - 498) + 'px' // 为子组件table表格进行赋值操作
          needMoveDOM[2].style.position = 'relative' // 为子组件table表格进行赋值
        }
      }
    }
},
mounted(){
   /** 子组件初始化的时候,设置子组件不滚动 **/
    const needMoveDOM = document.querySelectorAll('.el-table__body')
    if (this.tableWrapAllRowsData === 0) {
      // 父组件table表格滚动的距离 才是统计特征页面tables表格动态列滚动的距离
      needMoveDOM[2].style.left = (Number(this.tableWrapAllRowsData)) + 'px'
      needMoveDOM[2].style.position = 'relative'
    } else {
      // 解决父组件表格滚动一定距离后,关闭统计特征页面,然后在打开统计页面,统计特征页面的动态列,动态列显示位置错位的问题
      // 父组件table表格滚动的距离 + 统计特征页面tables表格前3列的值+中间的间隙的距离,才是统计特征页面tables表格动态列滚动的距离
      needMoveDOM[2].style.left = (Number(this.tableWrapAllRowsData) - 498) + 'px'
      needMoveDOM[2].style.position = 'relative'
    } 
}

4、git中如何将一个分支的某几个文件合并到另一个分支

例如:我需要把test分支上的2个文件,合并到stage分支上

image.png

例如执行命令:git checkout test -- src/views/.../.../a.vue src/views/.../.../b.vue

5、elementUI组件表格排序的重置与清除

<template>
  <div id="rank">
      <el-button @click="resetTable">重置排序</el-button>
      <el-button @click="clearTable">清除排序</el-button>
      <el-table
      ref="tableList"
      :data="tableData"
      style="width: 100%"
      :default-sort = "{prop: 'date', order: 'descending'}"
      >
      <el-table-column
        prop="date"
        label="日期"
        sortable
        width="180">
      </el-table-column>
      <el-table-column
        prop="age"
        label="年龄"
        sortable
        width="180">
      </el-table-column>
      <el-table-column
        prop="address"
        label="地址"
        :formatter="formatter">
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
export default {
  name: 'rank',
  data(){
    return {
      tableData: [{
          date: '2016-05-02',
          age: '11',
          address: '上海市普陀区金沙江路 1518 弄'
        }, {
          date: '2016-05-04',
          age: '12',
          address: '上海市普陀区金沙江路 1517 弄'
        }, {
          date: '2016-05-01',
          age: '13',
          address: '上海市普陀区金沙江路 1519 弄'
        }, {
          date: '2016-05-03',
          age: '14',
          address: '上海市普陀区金沙江路 1516 弄'
        }]
    }
  },
  methods:{
    formatter(row, column) {
      return row.address;
    },
    resetTable(){
      this.$refs.tableList.sort('date','descending')
    },
    clearTable(){
      this.$refs.tableList.clearSort()
    }
  }
}
</script>

官方文档方法

image.png

6、elementUI中,表格数据需要用for循环出来,方便加减节点的方法(动态表格)

<template>
    <el-table :data="tableData" style="width: 100%">
        <el-table-column
            :prop="item.porp"
            :label="item.label"
            width="180"
            v-for="item in data"
            :key="item.key"></el-table-column>
    </el-table>
</template>

<script>
export default {
    data() {
        return {
            // 表格表头的值,其中porp是和下面表格列的值中对象的key一一对应的
            data: [
                { label: "编码1日期", porp: "date"},
                { label: "编码2名字", porp: "name"},
                { label: "编码3住址", porp: "address"},
            ],
            // 表格列的值
            tableData: [{
                date: '2016-05-02',
                name: '王小虎',
                address: '上海市普陀区金沙江路 1518 弄'
                }, {
                date: '2016-05-04',
                name: '王小虎',
                address: '上海市普陀区金沙江路 1517 弄'
                }, {
                date: '2016-05-01',
                name: '王小虎',
                address: '上海市普陀区金沙江路 1519 弄'
                }, {
                date: '2016-05-03',
                name: '王小虎',
                address: '上海市普陀区金沙江路 1516 弄'
            }]
        }
    }
}
</script>

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

7、Echars中堆叠柱状图,鼠标划过默认显示全部,实现只显示鼠标位置的柱状图信息

// 在option选项中加入下面的代码即可,老板本的Echars这么调整
option = {
     tooltip:{
         trigger: 'item'
    },
}

8、elementUI中,点击按钮,实现tree控件上移和下移

<template>
    <el-tree :data="data" :props="defaultProps" @node-click="handleNodeClick" ref="tree"></el-tree>
    <el-button type="primary" @click="moveUp">上移</el-button>
    <el-button type="primary" @click="moveDown">下移</el-button>
</template>

<script>
    export default {
        data() { 
            return {
                data: [
                    { label: '一级 1',
                      children: [{ 
                          label: '二级 1-1',
                          children: [{ 
                              label: '三级 1-1-1' }] 
                          }]
                    },
                    { label: '一级 2', 
                      children: [{ 
                          label: '二级 2-1', 
                          children: [{ 
                              label: '三级 2-1-1' 
                          }] 
                        }, 
                        { label: '二级 2-2', 
                          children: [{
                                label: '三级 2-2-1' 
                           }]
                      }] 
                    }, 
                    { label: '一级 3',
                      children: [{ 
                          label: '二级 3-1', 
                          children: [{ label: '三级 3-1-1' }] 
                          }, 
                          { label: '二级 3-2', 
                            children: [{ label: '三级 3-2-1' }] 
                      }] 
                    }
               ], 
               defaultProps: { 
                    children: 'children', 
                    label: 'label' } 
              };
        }, 
        methods: { 
          handleNodeClick(data) { 
              console.log(data); 
          },
          //节点上移
          moveUp: function () {
            let node = this.$refs.tree.getCurrentNode();
            console.log(node.id);
            if (!node) {
              this.$message({
                message: '请先点击选择节点',
                type: 'warning'
              })
              return
            } 
              // 获取当前点击的节点的父节点中,所有的子节点
              let pchildNodes = this.$refs.tree.getNode(node.assetId).parent.childNodes
              let currentId = -1
              // 获取当前点击的节点在父节点的位置,即索引
              for (let i = 0; i < pchildNodes.length; i++) {
                if (pchildNodes[i].data.assetId == node.assetId) {
                 currentId = i
                }
              }
              // 当前点击的节点是第一个
              if(currentId == 0){
                this.$message({
                  message: '处于顶端,不能继续上移',
                  type: 'warning'
                })
                return
              }
              let upid = currentId - 1 // 当前节点需要向上移动的位置,即索引
              pchildNodes.spliece(upid, 0, pchildNodes[currentId])
              // 对当前点击的节点,他的父节点中包含的所有子节点,进行位置的互换
              pchildNodes.spliece(currentId + 1, 1)
        },
        //节点下移
        moveUp: function () {
          let node = this.$refs.tree.getCurrentNode();
          console.log(node.id);
          if (!node) {
            this.$message({
              message: '请先点击选择节点',
              type: 'warning'
            })
            return
          } 
          let pchildNodesLength = this.$refs.tree.getNode(node.assetId).parent.childNodes.length - 1
          if (node.level === 1 && node.orderNo === pchildNodesLength) {
              this.$message({
              message: '禁止向下移动最后一个根节点',
              type: 'warning'
            })
          } else {
              // 获取当前点击的节点的父节点中,所有的子节点
              let pchildNodes = this.$refs.tree.getNode(node.assetId).parent.childNodes
              let currentId = -1
              // 获取当前点击的节点在父节点的位置,即索引
              for (let i = 0; i < pchildNodes.length; i++) {
                if (pchildNodes[i].data.assetId == node.assetId) {
                 currentId = i
                }
              }
              // 当前点击的节点是最后一个
              if(currentId == pchildNodesLength){
                this.$message({
                  message: '处于底端,不能继续下移',
                  type: 'warning'
                })
                return
              }
              let upid = currentId + 2 // 当前节点需要向下移动的位置,即索引
              pchildNodes.spliece(upid, 0, pchildNodes[currentId])
              // 对当前点击的节点,他的父节点中包含的所有子节点,进行位置的互换
              pchildNodes.spliece(currentId, 1)
          }
        },
    }
</script>

9、elementUI中, 为Table动态列动态设置宽度

element UI中的table设置列的宽度是width属性,如下:
<el-table-column prop="date" label="日期"  width="180"> </el-table-column>
但是我的列是动态的,不能直接这样设置
解决办法如下图所示:

image.png

10、elementUI中, 为Table表格无数据的时候,显示一张图片的办法

<template>
    <el-table
      :data="tableData"
      style="width: 100%">
      <!-- 主要代码在这里,写在table里面,第一个el-table-column的上面 ==> 开始 -->
      <template>
          <div style="height: 300px; padding-top: 50px;">
              <img src="../../../assets/images/nodata.png" alt="暂无数据">
              <span>暂无数据</span>
          </div>
      </template>
       <!-- 主要代码在这里 ==> 结束 -->
      <el-table-column
        prop="date"
        label="日期"
        width="180">
      </el-table-column>
      <el-table-column
        prop="name"
        label="姓名"
        width="180">
      </el-table-column>
      <el-table-column
        prop="address"
        label="地址">
      </el-table-column>
    </el-table>
  </template>
  <script>
       data() {
        return {
          tableData: [{
            date: '2016-05-02',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1518 弄'
          }, {
            date: '2016-05-04',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1517 弄'
          }, {
            date: '2016-05-01',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1519 弄'
          }, {
            date: '2016-05-03',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1516 弄'
          }]
        }
      }
  </script>

11、Vue3.0 setup 里使用 vuex,需要用到component才行

import { useStore }  from '@store' // 默认去找store文件夹下的index.js文件
import { getCurrentInstance, computed } from "vue"

setup () {
    const store = useStore() // 获取store 实例
    // const { ctx } = getCurrentInstance() // 获取当前组件实例,
    // console.log(ctx.$router.currentRoute.value)
    // 使用state和getter,需要computed来保持响应性
    const count  = computed( () => store.state.count) // 获取到vuex中的值,给组件使用
    return {
        count // 组件中 count 会随着其他的地方的 count 变化而自动相应变化
    }
}

12、Elementui中,Pagination 分页 实现左右各一半的布局,默认都是在左侧

html代码

css代码

13、elementUI中, Table表格显示的是树形数据,实现第一层级显示索引号

<tempalte>
    <!-- 表格中索引的列 -->
    <el-table-column prop="oneIndex" label="序号" width="50" align="center"> </el-table-column>
</template>
watch:{
    // 监视表格数据的变化,为第一层级添加左侧的展示索引,data是父组件传递过来的表格数据
    data(newVal){
        for (i=0; i< newVal.length; i++) {
            // 数据在第一次层级展示
            if (newVal[i]._level === 1) {
                // 为第一次层级添加一个属性:oneIndex,用来显示索引
                newVal[i].oneIndex = i + 1
            }
        }
    }
}
<style lang="scss">
    // .first__column__center__only是在table上新增的属性,防止全局污染,实现序列号这一列,表头和列都居中显示
    .first__column__center__only{
        .el-table__fixed {
            .el-table__fixed-header-wrapper {
                table {
                    thead {
                        tr:first-child th:first-child {
                            padding-left: 0px;
                        }
                    }
                }
            }
            
            .el-table__fixed-body-wrapper {
                table {
                    tbody {
                        tr {
                            td:first-child {
                                padding-left: 0px;
                            }
                        } 
                    }
                }
            }
        }
    }
</style>

14、动态实现elementUI中的el-table某列数据不同样式(比如颜色动态展示)

<template>
  <div id="app">
    <!-- 需求:三国人物表格,要求不同的国别展示不同的颜色(魏国红色、蜀国黑色、吴国蓝色) -->
    <el-table :data="tableData" style="width: 100%">
      <el-table-column prop="name" label="姓名" width="180"> </el-table-column>
      <el-table-column prop="nation" label="国别" width="180"> 
        <!-- 思路通过模板插槽,获取对应的数据,通过vue动态style的方法,动态显示不同的颜色,这种方式更加灵活 -->
        <template scope="scope">
          <!-- 意思是:给这个div绑定动态样式,
          颜色color的属性值为getColorByNation()这个方法的返回值,
          所以只需要通过传过去的scope 对方法的返回值做动态设置即可
          关键点就在这里-->
          <div :style="{color:getColorByNation(scope),fontSize:getSizeByNation(scope),fontWeight:'bold'}">{{scope.row.nation}}</div>
        </template>
      </el-table-column>
      <el-table-column prop="bornPlace" label="出生地方"> </el-table-column>
    </el-table>
  </div>
</template>

<script>
export default {
  name: "app",
  data() {
    return {
      tableData: [
        {
          name: "刘备",
          nation: "蜀国",
          bornPlace: "涿郡涿县(河北省涿州市)",
        },
        {
          name: "曹操",
          nation: "魏国",
          bornPlace: "沛国谯县(安徽省亳州市)",
        },
        {
          name: "孙权",
          nation: "吴国",
          bornPlace: "吴郡富春县(浙江省杭州市富阳区)",
        },
        {
          name: "关羽",
          nation: "蜀国",
          bornPlace: "河东郡解县(山西省运城市盐湖区解州镇)",
        },
      ],
    };
  },
  methods: {
    // 关键点就在这里 ==》 动态设置颜色
    getColorByNation(scope){
      console.log(scope); // 打印一下传过来的scope是对应表格不同行的整行的数据,如下有图片: 
      if(scope.row.nation == "魏国"){
        return "red"
      }else if(scope.row.nation == "蜀国"){
        return "black"
      }else if(scope.row.nation == "吴国"){
        return "blue"
      }
    },
    // 关键点就在这里 ==》 动态设置字体大小
    getSizeByNation(scope){
      if(scope.row.nation == "魏国"){
        return "14px"
      }else if(scope.row.nation == "蜀国"){
        return "18px"
      }else if(scope.row.nation == "吴国"){
        return "24px"
      }
    }
  },
};
</script> 

15、ElementUI -- 表单嵌套表格,v-for生成的表单项实现表单验证

参考一:ElementUI -- 表单嵌套表格,v-for生成的表单项实现表单验证。
参考二:elementui中的form表单中嵌套表格,表格中又校验input框
参考三:Vue中对From表单中的Table表格中的输入项进行验证
1、截图实现的效果是 第一个表单里面 又套了 第二个表单,在第二个表单中套入了表格
2、在最外面写了一个clss样式累,为了防止全局污染而写的

image.png
3、实现表单中嵌套表格的时候,为了显示验证,保证表格的美观,修改的css代码如下:

<style lang="scss">
    secondFormAndTable {
        .el-form-item__content {
            display: flex !important;
            width: 100% !important;
            // 主要代码在这里 开始
            .el-table__header tr, el-table__header th {
                padding: 0;
                height: 35px;
                line-height: 35px;
            }
            .el-table__body tr, el-table__body td {
                padding: 20px 0 3px 0;
                height: 40px;
                line-height: 40px;
            }
            // 主要代码在这里 结束
        }
    }
</style>

16、element UI tabel表格改变边框颜色

1.改变最外层边框

style中不能有scoped 为了防止全局污染,可以用一个父css样式包裹住

 .el-table td, .el-table th.is-leaf,.el-table--border, .el-table--group{
        border-color: black;
    }
 .el-table--border::after, .el-table--group::after, .el-table::before{
        background-color: black;
    }

2.添加属性:cell-style=“cellStyle” 改变表格里面的边框颜色
3.添加属性:header-cell-style="{color:‘black’,borderColor:‘black’}",改变表头的边框颜色
 <el-table :cell-style="cellStyle" :header-cell-style="{ color: 'black', borderColor: 'black' }"  height="200" :data="tableData" style="width: 100%" border >
     <el-table-column prop="date" label="序号" width="180" align="center">
     </el-table-column>
     <el-table-column prop="name" label="参数名称" width="180" align="center">
     </el-table-column>
</el-table>
 methods: {
    cellStyle({ row, column, rowIndex, columnIndex }) {
      return "height:35px!important; border-color:black!important; color:#000000!important; padding:0px!important; height:40px!important";
    },
 }

17、element UI tabel表格中表格列是动态的,设置动态表格列的宽度

例子是带有2级表头的,1级表头的也是可以一样的操作
html代码: image.png
js代码:
image.png

18、js 递归实现过滤数组

过滤要求:让数组元素中isShow为false的过滤掉,如果第一级的isShow为false,就直接不递归了

  • 数据如下
let a = [{
        id: 1,
        isShow: false,
        child: [{
            id: 2,
            isShow: true
        }]
    },
    {
        id: 3,
        isShow: true,
        child: [{
            id: 4,
            isShow: true
        }, {
            id: 5,
            isShow: false
        }]
    }
]

  • 解决方法如下:
const detailChild = (child) => {
    if (!child) return []
    return child.filter((item) => {
        if (item.isShow) {
            item.child = detailChild(item.child)
        }
        return item.isShow
    })
}

let b = a.filter((item) => {
    if (item.isShow && item.child && item.child.length) {
        item.child = detailChild(item.child)
    }

    return item.isShow
})

console.log(b)

19、element UI中 DatePicker 日期选择器,只有T-1的日期可以点击,T和T++后的日期禁止点击

T是今天的当前时间

<el-date-picker 
    v-model="value1" 
    type="date"
    placeholder="选择日期"
    :picker-options="limitData"> 
</el-date-picker>


<script> 
   export default {
       data() { 
           return {  
               value1: '', 
               limitData: {
                   disabledDate (time) {
                       return time.getTime() > Date.now() - 3600 * 1000 * 24
                   }
               },
           } 
       } 
   } </script>

20、element UI中 DatePicker 日期选择器,需要选择一个时间范围【设置选择的开始时间不能大于结束时间,同时2个时间中只有T-1的日期可以点击,T和T++后的日期禁止点击

T是今天的当前时间

  • 代码如下:
<el-form-item>
  <el-date-picker
    v-model="startTime"
    type="date"
    value-format="yyyy-MM-dd"
    placeholder="开始日期"
    :picker-options="pickerOptionsStart"
    clearable
  ></el-date-picker>
</el-form-item>
<el-form-item>
  <el-date-picker
    v-model="endTime"
    type="date"
    value-format="yyyy-MM-dd"
    placeholder="结束日期"
    :picker-options="pickerOptionsEnd"
    clearable
  ></el-date-picker>
</el-form-item>

data() {
    return {
      startTime: '', // 时间段开始时间
      endTime: '', // 时间段结束时间
      pickerOptionsStart: {
        /** 禁止选择 */
        disabledDate: time => {
          let endDateVal = this.endTime;
          if (endDateVal) {
            return time.getTime() > new Date(endDateVal).getTime()
          } else {
            return time.getTime() > Date.now() - 3600 * 1000 * 24
          }
        }
      },
      pickerOptionsEnd: {
        /** 禁止选择 */
        disabledDate: time => {
          let beginDateVal = this.startTime;
          if (beginDateVal) {
            return time.getTime() < new Date(beginDateVal).getTime() || time.getTime() > Date.now() - 3600 * 1000 * 24
          } else {
            return time.getTime() > Date.now() - 3600 * 1000 * 24
          }
        }
      },
    },
}


  • 页面效果如下:

image.png

image.png

21、element UI中 Table表格组件中表格显示索引,同时索引随着分页一起变动,例如:表格每页显示10条,点击了第二页,表格索引显示为11-20,这是只有一个层级的实现方法

image.png currentPage是点击点击的页数, pageSize是每页显示多少条数据

22、element UI中 Table表格组件中,前端自己实现排序的时候,只支持number类型的数值来进行排序,对于字符串的排序会出现表格数据排序后,错乱的问题,所以后台只需要把带有%的数据,直接返回为number类型的,由前端自己进行添加%的操作

image.png

23、后台接口返回Blob类型数据,如何转换Json数据类型,拿到里面的url,然后单独打开一个浏览器页面

// 定义JSON数据
let data = { "name": "小明" };
// 转换成字符串数组
let string = JSON.stringify(data);
// 转换成Blob类型数据
let blobData = new Blob([string]);

console.log(blobData) // 打印Blob结果: Blob { size: 17, type: "" }

// 将blob类型的数据转变成 json数据类型
let reader = new FileReader(); // 创建读取文件对象
reader.readAsText(blobData, 'utf-8'); // 设置读取的数据以及返回的数据类型为utf-8
reader.addEventListener("loadend", function () { // 
  let res = JSON.parse(reader.result); // 返回的数据
  console.log(res,'返回结果数据') // { name: "小明" }
  // 如果返回的是url,单独打开一个浏览器页面
  // window.open(url)
});

相关链接一
相关链接二

24、使用elementui中的【Collapse 折叠面板】,可以让其在页面拖着跑,用自定义指令实现

html页面

image.png vue自定义指令

image.png

image.png

25、在vue项目中使用svg图标

点击查看相关链接

svg图标可以随字体一样变色、大小可更改且不失真;应用在项目中不仅可以摆脱img图片占用内存大的问题,还可以减少代码量,优化系统。
使用字体图标的步骤如下:

  1. 安装svg-sprite-loader插件
npm install svg-sprite-loader
  1. 自定义svg-icon组件
    componets文件夹下建立一个svgIcon组件,内容如下:
<template>
  <svg :class="svgClass" aria-hidden="true" v-on="$listeners">
    <use :xlink:href="iconName" />
  </svg>
</template>
<script>
export default {
  name: 'SvgIcon',
  props: {
    iconClass: {
      type: String,
      required: true,
    },
    className: {
      type: String,
      default: '',
    },
  },
  computed: {
    // 图标名称
    iconName() {
      return `#icon-${this.iconClass}`;
    },
    // 样式类名
    svgClass() {
      if (this.className) {
        return `svg-icon ${this.className}`;
      }
      return 'svg-icon';
    },
  },
  data() {
    return {
    };
  },
};
</script>
<style scoped>
.svg-icon{
  width: 1em;
  height: 1em;
  fill: currentColor; /* 图标填充颜色,currentColor是一个变量,表示当前元素的color值,如当前无指定,则从父元素继承 */
  overflow: hidden;
}
</style>

3、在src目录下新建文件夹icons放置svg图标文件,并在index.js中注册svgIcon为全局组件
建目录如下:svg图标及index.js

image.png

index.js文件代码

// 引入vue
import Vue from 'vue';
// 引入svgIcon组件
import SvgIcon from '@/components/SvgIcon.vue';
// 注册为全局组件
Vue.component('svg-icon', SvgIcon);
// 引入当前svg目录下的文件、不遍历子目录、匹配以'.svg'为结尾的文件
const req = require.context('./svg', false, /\.svg$/);
// 相当于 req.keys().forEach(key => req(key)), req.keys()是匹配到的svg文件的路径数组
const requireAll = (requireContext) => requireContext.keys().map(requireContext);
// 得到一个完整解析的module数组
requireAll(req);

这个打印reqreq.keys()的结果

image.png

  1. 配置vue.config.js
const path = require('path');
// 在vue.config.js中没有配置 resolve 方法, 需要自定义一个
function resolve(dir) {
  return path.join(__dirname, dir);
}
module.exports = {
  chainWebpack: (config) => {
    // set svg-sprite-loader
    config.module.rules.delete('svg'); // 重点:删除默认配置中处理svg
    config.module
      .rule('svg-sprite-loader')
      .test(/\.svg$/)
      .include
      .add(resolve('src/icons')) // 处理svg目录
      .end()
      .use('svg-sprite-loader')
      .loader('svg-sprite-loader')
      .options({
        symbolId: 'icon-[name]',
      });
  },
};

  1. 在页面中使用svg图标
<svg-icon :iconClass="'alarm'"></svg-icon>

image.png

26、ElementUI -表单嵌套表格,实现表单和表格都能验证,第15项也有相同功能

点击查看相关链接

<template>
  <div>
    <el-form :model="forms" ref="forms" :rules="rules">
      <el-table :data="forms.voList">
        <el-table-column
        label="商品名称">
          <template slot-scope="scope">
            <el-form-item :prop="'voList.'+scope.$index+'.goodsName'">
              <el-input v-model="scope.row.goodsName"></el-input>
            </el-form-item>
          </template>
        </el-table-column>
        <el-table-column
          label="商品编码">
          <template slot-scope="scope">
            <el-form-item :prop="'voList.'+scope.$index+'.goodsCode'">
              <el-input v-model="scope.row.goodsCode"></el-input>
            </el-form-item>
          </template>
        </el-table-column>
        <el-table-column
          label="价格">
          <template slot-scope="scope">
            <el-form-item :prop="'voList.'+scope.$index+'.unitPrice'" :rules="rules.unitPrice">
              <el-input v-model="scope.row.unitPrice"></el-input>
            </el-form-item>
          </template>
        </el-table-column>
        <el-table-column
          label="数量">
          <template slot-scope="scope">
            <el-form-item :prop="'voList.'+scope.$index+'.num'" :rules="rules.unitPrice">
              <el-input v-model="scope.row.num"></el-input>
            </el-form-item>
          </template>
        </el-table-column>
      </el-table>
    </el-form>
    <el-button type="primary" @click="save">批量开票</el-button>
  </div>
</template>

<script>
export default {
  name: "table",
  data(){
    return {
      // 表单数据
      forms:{
        id:1,
        documentNo:null,
        buyerName:"服务技术",
        buyerDp:"42118XXXXXXXXXX72X",
        buyerBankAccount:"招商银行4890284",
        buyerAddressPhone:"深圳市宝安区110112",
        buyerEmail:null,
        buyerPhone:null,
        buyerType:"01",
        remarks:"这是备注",
        total:350.9,
        // 表单里面要有表格数据才行
        voList:[
          {
            goodsName:"黄金",
            goodsCode:"44021940",
            specification:null,
            unit:"克",
            num:1,
            unitPrice:291.37,
            taxRate:0.17,
            taxAmount:49.53,
            favouredPolicy:"0",
            zeroTaxRate:"",
            hsbz:"1"
          },
          {
            goodsName:"花生",
            goodsCode:"4574511",
            specification:null,
            unit:"斤",
            num:1,
            unitPrice:8.55,
            taxRate:0.17,
            taxAmount:1.45,
            favouredPolicy:"0",
            zeroTaxRate:"",
            hsbz:"1"
          }
        ]
      },
      // 表单验证,验证的是表单里面表格的数据
      rules:{
        num:[{required:true,message:'数量不能为空',trigger:'blur'}],
        unitPrice:[{required:true,message:'单价不能为空',trigger:'blur'}]
      }
    }
  },
  methods:{
    save(){
      this.$refs['forms'].validate((valid)=>{
        if(valid){
          console.log(1)
        }
      })
    }
  }
}
</script>
<style scoped lang="scss">

</style>

27、vue中后端返回文件流,前端全部下载或者部分下载

点击查看相关链接

点击查看相关链接

28、elementUI 表格刷新后保持行高亮显示

点击查看相关链接

29、vue+element ui实现表格拖拽功能

点击查看相关链接

sortablejs中文官网

30、vue中实现下载,前端调用接口,后端返回的是流,前端处理办法

接口的写法:

image.png

// 前提是调用接口后,接口返回的数据格式是2进制流,前端把流处理成文件,进行下载
// res是接口返回的数据
// let blob = new Blob([res.data], {type: ''})
let blob = new Blob([res.data])
// 或者指定下载的文件类型,例如:excel文件 
//let blob = new Blob([res.data],{
//    type: 'application/vnd.ms-excel'
//})
// 判断方式一: 先判断非IE下载
if('download' in document.createElement('a')){
    // 动态加载a标签,实现下载
    let aDom = document.createElement('a')
    let href = window.URL.createObjectURL(blob) // 下载链接
    aDom.href = href
    aDom.download = XXXX // XXXX是下载的文件名字
    document.body.appendChild(aDom)
    aDom.click() // 强制触发a标签的点击事件
    document.body.removeChild(aDom) // 移除a标签
    window.URL.revokeObjectURL(href)// 释放blob对象
} else {
    // IE下载
    navigator.msSaveBlob(blob, XXXX) // XXXX是下载的文件名字
}

// 判断方式二: 先判断IE下载
if(window.navigator.msSaveOrOpenBlob){
    // IE下载
    navigator.msSaveBlob(blob, XXXX) // XXXX是下载的文件名字
} else{
    // 动态加载a标签,实现下载
    let aDom = document.createElement('a')
    let href = window.URL.createObjectURL(blob) // 下载链接
    aDom.href = href
    aDom.download = XXXX // XXXX是下载的文件名字
    document.body.appendChild(aDom)
    aDom.click() // 强制触发a标签的点击事件
    document.body.removeChild(aDom) // 移除a标签
    window.URL.revokeObjectURL(href)// 释放blob对象
}


31、element中table表格跨分页多选及回显的实现

<template>
  <div>
  <!-- 表格 -->
    <el-table @selection-change="handleSelectionChange" :row-key="getRowKeys">
      <el-table-column type="selection" width="50" align="center" :reserve-selection="true"> 
      </el-table-column>
    </el-table>
    <!-- 分页 -->
    <el-pagination>...</el-pagination>
  </div>
</template>
<script>
export default {
  data() {
    return {
      multipleSelection: [], // 表格选中
      getRowKeys(row) {//记录每行的key值
        return row.id;
      },
      select_number: -1, //表格select选中的数据的总条数
      select_Id: [], //表格select复选框选中的id
    }
  },
  methods: {
    handleSelectionChange(rows) {
      this.multipleSelection = rows;
      this.select_number = this.multipleSelection.length;
      this.select_Id = [];
      if (rows) {
        rows.forEach((row) => {
          if (row) {
            this.select_Id.push(row.id);
          }
        });
      }
    },
  }
}

32、element中form表单中嵌套table表格,同时table表格是动态的

33、element中修改日期选择框的样式

日期组件中必须有 popper-class="date_style"这个属性
这个属性可以用来包裹改变日期下拉框的样式,防止样式污染

image.png

日期组件中输入框样式的调整,.all_echars_date_picker 是包裹日期组件的div的类名,上图有标明 image.png

日期组件中下拉库框样式的调
单独写一个style样式,因为日期组件中下拉库,默认挂在了body下面

image.png

image.png

image.png

image.png

image.png

最终效果如下

image.png

34、css 边框添加四个角效果

html部分

<div class="loginbody">
  <div class="border_corner border_corner_left_top"></div>
  <div class="border_corner border_corner_right_top"></div>
  <div class="border_corner border_corner_left_bottom"></div>
  <div class="border_corner border_corner_right_bottom"></div>

  <--other……………………-->
</div>

css部分

 .loginbody{
    border: 1px solid #21a7e1;
    box-shadow: 5px 5px 10px 10px  rgba(24,68,124,0.4);
    padding-top:20px;
    border-radius: 6px;
    position: relative;
  }

  /*四个角框*/
  .border_corner{
    z-index: 2500;
    position: absolute;
    width: 19px;
    height: 19px;
    background: rgba(0,0,0,0);
    border: 4px solid #1fa5f1;
  }
  .border_corner_left_top{
    top: -2px;
    left: -2px;
    border-right: none;
    border-bottom: none;
    border-top-left-radius: 6px;
  }
  .border_corner_right_top{
    top: -2px;
    right: -2px;
    border-left: none;
    border-bottom: none;
    border-top-right-radius: 6px;
  }
  .border_corner_left_bottom{
    bottom: -2px;
    left: -2px;
    border-right: none;
    border-top: none;
    border-bottom-left-radius: 6px;
  }
  .border_corner_right_bottom{
    bottom: -2px;
    right: -2px;
    border-left: none;
    border-top: none;
    border-bottom-right-radius: 6px;
  }

最终效果

image.png

35、vue2中实现禁止浏览器的前进后退按钮点击跳转页面

  • vue2中main.js的入口文件中:

image.png

  • vue2中路由中的index.js文件中:(或者路由的全局前置守卫borferEach钩子中设置也可以)

image.png image.png

36、vue2中实现element ui table scrollTop 滚动到行头或行尾

滚动到第一行:

this.$refs.table.bodyWrapper.scrollTop =0

滚动到最后一行:

this.$refs.table.bodyWrapper.scrollTop =this.$refs.table.bodyWrapper.scrollHeight

32、vue2中实现elementUI Table 合并第一列相同的数据

// template部分
<el-table :data="indexShardLocation"
   border
   :span-method="objectSpanMethod"
   style="width: 100%">
   <el-table-column 
       prop="index_name"
       label="索引名"
       width="240">
   </el-table-column>
</el-table>

// mothod部分
flitterData (arr) {
  let spanOneArr = []
  let concatOne = 0
  arr.forEach((item, index) => {
    if (index === 0) {
      spanOneArr.push(1);
    } else {
      // 第一列中 name同名,就是要进行合并
      if (item.name === arr[index - 1].name) { //第一列需合并相同内容的判断条件
        spanOneArr[concatOne] += 1;
        spanOneArr.push(0);
      } else {
        spanOneArr.push(1);
        concatOne = index;
      };
    }
  });
  return {
    one: spanOneArr,
  }
},

// 合并表格列的方法
objectSpanMethod ({ row, column, rowIndex, columnIndex }) {
  // 第一列合并
  if (columnIndex === 0) {
    // this.tableData  修改
    const _row = (this.flitterData(this.indexShardLocation).one)[rowIndex];
    const _col = _row > 0 ? 1 : 0;
    return {
      rowspan: _row,
      colspan: _col
    };
  }
},