1. 如何在新项目使用svg-icon组件
是什么?
SVG是一种可缩放矢量图形(英语:Scalable Vector Graphics,SVG)是基于可扩展标记语言(XML),用于描述二维矢量图形的图形格式。SVG由W3C制定,是一个开放标准。
简单的理解,它是图形的另一种格式例如它和常见的图片格式.png、.jpg、.gif等是一类。
学习网站:https://www.runoob.com/svg/svg-tutorial.html
作用:
SVG在既能满足现有图片的功能的前提下,又是矢量图,在可访问性上面也非常不错,并且有利于SEO和无障碍,在性能和维护性方面也比icon font要出色许多
使用:
步骤1:安装依赖npm i svg-sprite-loader@4.1.3
步骤2:
配置 vue.config.js
const path = require('path') function resolve (dir) { return path.join(__dirname, dir) }
补充一个配置{ }
{ // 省略其他... chainWebpack (config) { // set svg-sprite-loader config.module .rule('svg') .exclude.add(resolve('src/icons')) .end() config.module .rule('icons') .test(/\.svg$/) .include.add(resolve('src/icons')) .end() .use('svg-sprite-loader') .loader('svg-sprite-loader') .options({ symbolId: 'icon-[name]' }) .end() } }
步骤3:复制/创建文件
(1) src/icons
src/icons - /svg # 保存图标 - /index.js # 注册全局组件
(2) 组件
componets/SvgIcon/index.vue
(3)validate.js
utils/validate.js
(4)在main.js中引入
import '@/icons'
(5)使用
使用格式 。这里的文件名就是在src/icons/svg下的文件名
2.在created钩子里发请求导致数据显示异常
出现场景举例:
可以使用vue调试工具查看组件有没有被销毁
在编辑时,只有第一次点编辑时,才能正确显示。随后再点编辑,数据显示不正确了
原因:
现在的代码中,获取详情这个动作在子组件的created中发出的,而created钩子只会执行一次:后续点击关闭弹层时,子组件被没有销毁,它只是隐藏了。
解决方案1:使用v-if
在关闭弹层时,把子组件销毁,再打开时重新创建(重新创建created重发请求)
优点是简单高效事少,缺点是性能消耗问题,频繁的创建销毁组件
解决方案2: 使用ref
在父组件中通过引用找到子组件
在父组件中,每次打开弹层时,找到子组件,要求它去发请求获取详情
优点是性能比v-if好,缺点是父组件直接操作子组件,逻辑不通顺,个人不喜
解决方案3:监听 watch
思路是监听某个值(变量)的变化,如果这个值变化了,就发送请求重新刷新页面
3.子组件抛出事件在父组件执行逻辑
业务场景举例:在子组件中关闭弹层
思路:子传父
步骤1:在子组件内抛出事件
<el-button @click="hCancel">取消</el-button> // 用户点击了取消 hCancel() { // 通知父组件去关闭弹层 this.$emit('close') }
步骤2:在父组件中给子组件添加事件监听
1. <son组件 @close="hClose"/> 2.
步骤3:父组件执行回调函数,关闭弹窗
1. // 收到子组件中的close事件 2. hClose() { 3. this.showDialog = false 4. },
4.举一反三-表单验证-同级部门不重复问题
场景举例:
后台项目中,添加部门名称,做表单验证时,如要添加的名称已经存在(且是同级情况下),应该不能校验成功。
思路:典型的用js手段,对数据(数组)进行逻辑运算问题。
在某个部门上点击**编辑**时:被占用的名字列表 = 当前部门的兄弟部门 - 它自己的名字
代码实现(代码不重要,解决问题的思路重要):
const validName = (rule, value, callback) => { // 思路:被占用的名字是这个部门的子部门 let existNameList = this.originList.filter(item => item.pid === this.id).map(item => item.name) console.log('validName.... , 当前被校验的名字是', value) // const existNameList = ['财务核算部', '薪资核算部'] // 如果是编辑,则被占用的名字 = 兄弟-自己 if (this.isEdit) { // 1. 找到当前被编辑的元素 const dept = this.originList.find(item => item.id === this.id) // 2. 取出pid(它的父级是谁) const pid = dept.pid // 3. 过滤: 同一个父级,不包括自己; map: 只要需要名字 existNameList = this.originList.filter(item => item.pid === pid && item.id !== this.id).map(item => item.name) } console.log('被占用的名字列表', existNameList) if (existNameList.includes(value)) { callback(new Error('名字' + value + '已经被占用了')) } else { callback() } }
5.表单校验-表单数据不被清空问题
业务场景:
编辑部门时, 故意清空某些必填项,让表单触发校验项失败,然后,点击添加子部门,发现表单内容及校验项仍在。(如果在子组件使用了v-if,上面的问题不会出现)
解决思路:1.点击取消、确定、直接点击x号,都应该清空表单数据
2.resetFields是element-ui中的el-form组件提供一个api,它的作用是
重置表单数据
清空校验结果(页面上红色的提示)
可以在关闭弹窗时调用此方法,或点击按钮时调用,或父组件直接ref调用子组件此方法。
this.$refs.随便起名.resetFields()
6.(使用监听)清空表单数据的bug
场景举例:
- 选中a部门,进行编辑,故意让编辑出错,在表单上出现错误
- 点击取消
- 再次对a部门进行编辑,发现数据没有显示出来
原因分析:
上面的操作中,前后两次编辑的是同一个部门,所以子组件内对id的watch并没有执行,导致内容为空
解决思路:
直接在父组件调用子组件的请求以刷新页面
hEdit(id) { //强制让子组件去发请求获取详情 this.$nextTick(() => { // 调用子组件的loadDetail方法 this.$refs.refDeptDialog.loadDetail() }) }
7.props的传递是异步的
父传子时,props的传值过程是异步的。如果需要获取同步之后的最新的props数据,要使用$nextTick()
dispatch也是异步的
// 父组件 <son ref="refSon" :id="num" /> <button @click="changeID">修改id</button> data() { return { num: 1 } } methods: { changeID(){ this.num = 2 console.log(this.$refs.refSon.id) // 1 } } //子组件 props: ['id']