Vue + elementUI使用中总结,包括踩坑(更新中)

40 篇文章 6 订阅

el-table表格中实现动态添加输入框

利用vue的新特性,slot-scope来解决

<el-table-column prop="reportName" label="报告名称">
     <template slot-scope="scope">
         <el-input v-model="scope.row.reportName" @blur="confirmData" clearable></el-input>
     </template>
</el-table-column>

Vue中引入插入图片方法

使用require引入图片路径

   <img :src="item.url" class="item-img"/>
export default {
        name: "SideBar",
        data(){
          return{
              itemList: [
                {name: 'temperature', title: '温、湿度', no: 1, url: require('../../assets/images/wenshidu-icon.png')},    
                ]
          }
        }
}

Vue中引入背景图片方法

使用require引入背景图片路径,跟url拼接起来

    <el-menu-item v-for="(item, index) in itemList" :key="index" :index="item.name" class="menu-item body-bgcolor" :style="{background: item.bgUrl}">
export default {
        name: "SideBar",
        data(){
          return{
              itemList: [
                {'name': 'temperature', 'title': '温、湿度', 'bgUrl': 'url(' + require('../../assets/images/wenshidu-icon.png') + ')',},             
                ]
          }
        }
}

el-menu设置默认选中项

使用自带的:default-active

<el-menu ref="sidebarMenu" class="menu" router :default-active="navSelected">
	<el-menu-item></<el-menu-item>
</el-menu>
export default {
        name: "SideBar",
        data(){
          return{
              navSelected: 'temperature'
          }
        }
}

el-menu导航上下切换选中项

这个方法自己想的,主要是利用了route的meta属性,给每一项都设置了一个序号

{
      name: 'functions',
      path: '/functions',
      component: () => import('@/views/module/functions'),
      redirect: '/functions/temperature',
      children: [
        {
          name: 'temperature',
          path: '/functions/temperature',
          component: () => import('@/views/module/functions/temperature'),
          meta: {
            title: '温、湿度',
            no: 1
          }
        }]
  }
<template>
  <div class="side-bar">
    <el-row span="24">
      <el-menu ref="sidebarMenu" class="menu" router :default-active="navSelected">
        <i class="up-button" @click="scrollUp"></i>
        <el-menu-item v-for="(item, index) in itemList" :key="index" :index="item.name" :class="{'menu-item': true, 'body-bgcolor': true, 'active-state': no == item.no}">
          <img :src="item.url" class="item-img"/>
          <span slot="title" :class="item.name" >{{ item.title }}</span>
      </el-menu-item>
        <i class="down-button" @click="scrollDown"></i>
      </el-menu>
    </el-row>
  </div>
</template>
export default {
        name: "SideBar",
        data(){
          return{
              no: 1,
              navSelected: 'temperature',
              itemList: [
                {name: 'temperature', title: '温、湿度', no: 1, url: require('../../assets/images/wenshidu-icon.png')
                }]
          }
        },
		methods: {
          scrollUp(){
            console.log('当前no', this.$route.meta.no)
            if(this.$route.meta.no !== 1){
              console.log('切换上一项')
              this.no = this.$route.meta.no - 1
              this.changeFunction()
            }
          },
          scrollDown(){
            console.log('当前no', this.$route.meta.no)
            if(this.$route.meta.no !== 8){
              console.log('切换下一项')
              this.no = this.$route.meta.no + 1
              this.changeFunction()
            }
          },
          changeFunction(){
            console.log('切换功能')
            let selectItem = this.itemList.find(item => item.no == this.no)
            console.log('selectItem', selectItem)
            let path = selectItem.name
            console.log('path', path)
            this.$router.push('/functions/' + path)
          }
        }

el-menu导航上下切换选中项(升级版:初始状态摆放不下全部的)

方法也是自己想的,通过不同状态下,调整整个导航的marginTop值,并且用v-if来控制元素的显示与隐藏

<template>
  <div class="side-bar">
    <el-row span="24" class="sidebar-wrap">
<!--      <i class="up-button" @click="scrollUp"></i>-->
      <el-menu ref="sidebarMenu" class="menu" router :default-active="navSelected" :style="menuStyle">
        <el-menu-item v-for="(item, index) in itemList" :key="index" :index="item.name" class="menu-item body-bgcolor" :class="{'active-state': no == item.no}"
        :style="item.itemStyle" v-if="item.isShow">
          <img :src="item.url" class="item-img"/>
          <span slot="title" :class="item.name" >{{ item.title }}</span>
        </el-menu-item>
      </el-menu>
<!--      <i class="down-button" @click="scrollDown"></i>-->
    </el-row>
  </div>
</template>

<script>
    export default {
        name: "SideBar",
        data(){
          return{
              no: 1,
              navSelected: 'temperature',
              menuStyle: '',
              itemList: [
                {name: '1', title: '1', no: 1, url: require('../../assets/images/1-icon.png'), itemStyle: {marginTop:'10px'}, isShow: true},
                {name: '2', title: '2', no: 2, url: require('../../assets/images/2-icon.png'), itemStyle: {marginTop:'10px'}, isShow: true},
                {name: '3', title: '3', no: 3, url: require('../../assets/images/3-icon.png'),itemStyle: {marginTop:'10px'}, isShow: true},
                {name: '4', title: '4', no: 4, url: require('../../assets/images/4-icon.png'), itemStyle: {marginTop:'10px'}, isShow: true},
                {name: '5', title: '5', no: 5, url: require('../../assets/images/5-icon.png'), itemStyle: {marginTop:'10px'}, isShow: true},
                {name: '6', title: '6', no: 6, url: require('../../assets/images/6.png'), itemStyle: {marginTop:'10px'}, isShow: true},
                {name: '7', title: '7', no: 7, url: require('../../assets/images/7.png'), itemStyle: {marginTop:'10px'}, isShow: true},
                {name: '8', title: '8', no: 8, url: require('../../assets/images/8-icon.png'), itemStyle: {marginTop:'10px'}, isShow: true},
                {name: '9', title: '9', no: 9, url: require('../../assets/images/9-icon.png'), itemStyle: {marginTop:'40px'}, isShow: true},
              ]
          }
        },
        mounted(){
        },
        methods: {
          scrollUp(){
            console.log('当前no', this.$route.meta.no)
            if(this.$route.meta.no !== 1){
              console.log('切换上一项')
              this.no = this.$route.meta.no - 1
              this.changeFunction()
              console.log('menuStyle', this.menuStyle)
              if(this.$route.meta.no === 8 && this.menuStyle !== 0){
                this.menuStyle = {marginTop: 0}
                console.log('menuStyle', this.menuStyle)
              }
              // if(this.$route.meta.no === 9){
              //   this.itemList.forEach((item) => {
              //     if(item.no == 9){
              //       // item.itemStyle = {marginTop:'40px'}
              //     }else if(item.no == 1){
              //       item.isShow = true
              //     }
              //   })
              //   this.menuStyle = {marginTop:'10px'}
              // }
              if(this.$route.meta.no === 2){
                this.itemList.forEach((item) => {
                  if(item.no == 9){
                    item.itemStyle = {marginTop:'10px'}
                    item.isShow = false
                  }else if(item.no == 1){
                    item.isShow = true
                  }
                })
              }
            }
          },
          scrollDown(){
            console.log('当前no', this.$route.meta.no)
            if(this.$route.meta.no !== 9){
              console.log('切换下一项')
              this.no = this.$route.meta.no + 1
              if(this.$route.meta.no === 8){
                // this.menuStyle = {marginTop:'-110px'}
                console.log('menuStyle', this.menuStyle)
                this.itemList.forEach((item) => {
                  if(item.no == 9){
                    item.isShow = true
                    item.itemStyle = {marginTop:'10px'}
                  }else if(item.no == 1){
                    item.isShow = false
                  }
                })
              }
              this.changeFunction()
            }
          },
          changeFunction(){
            console.log('切换功能')
            let selectItem = this.itemList.find(item => item.no == this.no)
            console.log('selectItem', selectItem)
            let path = selectItem.name
            console.log('path', path)
            this.$router.push('/functions/' + path)
            this.navSelected = path
          }
        }
    }
</script>

<style scoped>

</style>

父组件调用子组件中的方法

在父组件中引入子组件,并且为子组件设置ref值,和id一样,调用时候直接用$refs获取子组件调用其方法

<i class="up-button" @click="scrollUp"></i>
<side-bar ref="navbar"></side-bar>
<i class="down-button" @click="scrollDown"></i>
scrollUp(){
            this.$refs.navbar.scrollUp()
          },
          scrollDown(){
            this.$refs.navbar.scrollDown()
          }

利用路由实现子组件调用父组件的方法(路由可以当成组件使用props和$emit)

子组件:

this.$emit('unsolvedNum', this.unsolvedTableData.length)

父组件:

<router-view @unsolvedNum="updateNum"></router-view>
updateNum(num){
              console.log('num', num)
            this.num = num
          },

解决el-table表格对不齐问题

/*解决表格对不齐问题*/
.el-table th.gutter{
  display: table-cell !important;
}

隐藏(或设置)el-table表格滚动条

/*隐藏表格滚动条*/
.el-table__body-wrapper::-webkit-scrollbar{
  width: 0; /*宽度为0隐藏*/
}

设置鼠标划过el-menu的选项时,和选中时的样式

.el-menu-item:hover,
.el-menu-item.is-active {
  background: url('../../images/select-item-bg.png') no-repeat !important;
}

v-bind绑定的class和普通的类不冲突,默认的class会保留

<div class="title" :class="{'active': isActive, 'line': isLine}">Hello World</div>

.number是让输入框的值变成数字类型,.lazy当输入框失去焦点时更新数据

父组件调用子组件的方法时候,如果获取不到子组件可以尝试使用延时:原因是子组件的初始化操作还未完成

但是最好不要利用延时,因为你没法保证每次都能这个时间加载完成

父子组件的生命周期执行顺序如下:
父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted

<OnedayChart ref="oneday"></OnedayChart>
		  console.log('$refs', this.$refs)
          console.log('oneday', this.$refs.oneday)
            setTimeout(() => {
              console.log('n$refs', this.$refs)
              console.log('noneday', this.$refs.oneday)
            }, 1000)
          // this.$nextTick(() => {
          //   console.log('n$refs', this.$refs)
          //   console.log('noneday', this.$refs.oneday)
          // })

el-dialog的弹窗的关闭按钮失效

尝试多次,再加上查看文档例子,终于找到了原因,将dialog放在里面了,需要将触发的地方,按钮或者其他放在dialog的外面

el-dialog弹窗被遮罩挡住

设置 append-to-body属性为true
在这里插入图片描述

<el-dialog title="修改密码" :visible.sync="dialogFormVisible" width="25%" append-to-body>

路由守卫和使用白名单

const whiteList = ['/index', 'test', 'login']

// 通过路由守卫阻止单点登录
router.beforeEach((to, from, next) => {
  console.log('判断是否单点登录', to.path)
  const username = sessionStorage.getItem('username')
  if(!username){
    if(whiteList.indexOf(to.path) !== -1){
      console.log("白名单")
      next()
    }else{
      Message.warning('请先登录后再操作')
      next('/login')
    }
  }
  next()
})

vue中使用全局变量

一般$root获取根节点的方式不推荐
在src目录下新建一个global文件夹,创建一个index.js文件,将需要使用的变量定义在里面

const keyOn = false

export default {
  keyOn
}

在其他js或vue组件中引用时,导入进去
使用时注意是个对象,里面的值是属性

import global from '@/global'

global.keyOn = true

解决 cnpm : 无法加载文件 C:\Users\hp\AppData\Roaming\npm\cnpm.ps1,因为在此系统上禁止运行脚本

解决方式:

1、在系统中搜索框 输入 Windos PowerShell

2、点击“管理员身份运行”

3、输入“ set-ExecutionPolicy RemoteSigned”回车

4、根据提示,输入A,回车

5、再次回到cnpm -v执行成功
方法来自:https://blog.csdn.net/chengjingxuang123/article/details/105470815/

弹框后el-input自动聚焦

el-input文档中有autofocus属性,但是弹框后就不能自动聚焦了,初步看可能是el-input包裹着input,或者是弹框的遮罩,有时间研究看看原因

解决方案:利用js的focus方法
直接执行 this.$refs.input.focus()
可能会报错,因为元素未渲染完成

<el-input type="text" ref="tagInput" v-model="rfid"></el-input>
addTag(){
      this.tagInfoVisible = true
      this.$nextTick(() => {
        this.$refs.tagInput.focus()
      })
    },

el-table翻页序号接着上一页

<el-table-column prop="NO" type="index" label="序号" width="50">
     <template slot-scope="scope">
       <span>{{(currentPage - 1) * pageSize + scope.$index + 1}}</span>
     </template>
</el-table-column>
data(){
    return {
      currentPage: 1,
      pageSize: 10
    }
}

elementui阻止自带点击事件的组件事件冒泡

在该组件外面加一层div,@click.stop

<div @click.stop>
	// replace(/[<br>]/g,'')是将所有<br>替换为空
	<el-checkbox :label="field.colName.replace(/[<br>]/g,'')"></el-checkbox>
</div>

解决vuex页面刷新数据丢失问题

一种是存储时候利用sessionStorage,刷新时从sessionStorage取出再存入vuex中
另一种方法是
如果存储数据较少,可以在app.vue中添加

  //===========================下面是解决刷新页面丢失vuex数据
  created() {
    //在页面加载时读取sessionStorage里的状态信息
    if (sessionStorage.getItem('store')) {
      this.$store.replaceState(Object.assign({}, this.$store.state, JSON.parse(sessionStorage.getItem('store'))));
    }

    //在页面刷新时将vuex里的信息保存到sessionStorage里
    window.addEventListener('beforeunload', () => {
      sessionStorage.setItem('store', JSON.stringify(this.$store.state));
    });
  }

参考文章:解决vuex页面刷新数据丢失问题(简单有效)

解决弹框表单提示验证错误

el-form中添加属性

:validate-on-rule-change="false" // 打开弹窗不进行表单验证

点击空白处关闭弹窗取消提示

active=‘cancel’说明点击的是取消按钮,active=‘close’说明点击的是空白处

this.$confirm('此操作将进行删除操作, 是否继续?', '提示', {
              cancelButtonClass: "btn-custom-cancel",
              confirmButtonText: '确定',
              cancelButtonText: '取消',
              type: 'warning',
              distinguishCancelAndClose: true,
            }).then(() => {
              this.sendCommand(type)
            }).catch(active => {
              console.log(active) 
              if(active === 'cancel'){
                this.$message({
                  type: 'info',
                  message: '已取消删除操作'
                })
              }
            })

Js 修改对象数组里的对象属性名

// array为数组,old_name为修改前属性名,new_name为修改后属性名
JSON.parse(JSON.stringify(array).replace(/old_name/g, 'new_name')) 

解释:
1、JSON.stringify() 把json对象 转成 json字符串
2、使用正则的 replace() 方法替换属性名
3、JSON.parse() 再把json字符串 转成 json对象
参考文章:
Js 修改对象数组里的对象属性名

el-input无法获取焦点

设置延时,时间可以为0

<el-input ref="fileName" v-model="fileName"></el-input>
setTimeout(() => {
        this.$refs.fileName.focus()
      },0)

合法文件名校验

check(){
	let reg = new RegExp('[\\\\/:*?\"<>|]')
      if (reg.test(this.fileName)) {
        let flag = false
        this.$message.error('文件名包含非法字符,请修改!')
        return flag
      }
}

隐藏滚动条

谷歌浏览器Chrome

ul::-webkit-scrollbar {
    display: none;
  }

火狐浏览器Firefox

	overflow-y: scroll;
    scrollbar-color: transparent transparent;
    scrollbar-track-color: transparent;
    -ms-scrollbar-track-color: transparent;

报错Cannot read property ‘getBoundingClientRect‘ of undefined

原因在移除监听器时没有加true参数

// 页面销毁前
    beforeDestroy() {
      window.removeEventListener('scroll', this.handleScroll, true)
    },

参考:Cannot read property ‘getBoundingClientRect‘ of undefined

从一个数组中删除另一个数组方法

// 数组arr1中包含数组arr2
arr1 = arr1.filter((item) => {
 return arr2.every(val => {
     return item.id !== val;
   })
})

对象数组去重方法

let obj = {}
this.warningList = newArr.reduce((item, next) => {
   obj[next.happentime] ? '' : obj[next.happentime] = true && item.push(next);
   return item
 }, [])

如果大家想一起交流学习,共同进步,欢迎搜索公众号“是日前端”,输入关键词如:前端基础,获取资料,资料刚开始整理,目前还在完善中,点击交流群按钮进交流群,群里仅限技术交流、面试交流等,需要其它相关资料可以群里说,后续交流群人数增多会考虑特色内容,再次感谢大家的支持~

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值