Vue从入门到荒废-常见问题及解决方案[基于Vue2]
一、在VSCode中,文件名字大小写更新之后; 重新引入会报错
报错信息
Already included file name …
报错原因
因为文件在VSCode中已经存在并缓存了;所以报这个错误
解决方案
快捷键:Ctrl + shift + P,打开:“命令面板”,输入:重新加载
二、出现ESLint循环依赖错误
报错信息
Dependency cycle via @/components/CheckedBusDialog:13eslintimport/no-cycle
报错原因
在components下的组件,引入components的其他组件,只能一个个引入。不同同时引入多个;
import { CheckedBusForBid, CheckedBusForPerform } from '@/components'
解决方案
一个个分别引入
import CheckedBusForBid from '@/components/CheckedBusForBid'
import CheckedBusForPerform from '@/components/CheckedBusForPerform'
三、出现ESLint的简写错误
报错信息
Expected property shorthand
报错原因
引入组件的时候,别称与组件名不能完全一致,否则会出现这个错误
解决方案
(1)不起别称 或(2)取一个不同名字的别称
四、【重点】input标签无法同时使用v-model与v-decorator(两者之间有冲突)
报错信息
使用v-decorator校验数据之后,v-model就无法双向绑定数据了。
报错原因
ant-design-vue 1.0(适用于vue 2.0版本),在form表单中,使用v-for遍历list,并且用到了a-input标签,在a-input中无法同时使用v-model(双向绑定), v-decorator(双向绑定,校验信息);因为有必填校验,因此,最终使用v-decorator,不使用v-model; 但list无法回显。
解决方案
- 先在data()中定义list的初始值,不然,页面不能显示
// 合同名称List contractList: [{ contractName: undefined, }],
- 在template中的form中,遍历contractList, 用div元素,包裹元素
注:<div v-for="(item, index) in contractList" :key="index"> <a-row> <a-form-item // custom-horizontal-layout 来控制当前<a-form-item>为水平布局 class="custom-horizontal-layout left-col" // 这样显示合同名称1:`` 包裹 :label="`合同名称${index+1}:`" > <a-input // :disabled, 利用vue函数来控制是否只读或可以输入 :disabled="disabledByAppKey()" class="form-item" // 对输入的值,进行处理【index表示list下标,$event表示输入的事件】 @input="handleInputChange(index, 'contractName', $event)" // `contractList[${index}].contractName` 来表示唯一性,使用`${index}`也能表示唯一性; rules.contractNameCheck,在rules中定义的contractNameCheck的rule规则 v-decorator="[`contractList[${index}].contractName`, rules.contractNameCheck]" /> // 添加合同的图标元素 通过@click来监听事件,添加合同名称 <a-icon type="plus-circle" style="margin-left: 22px; font-size: 25px" @click="addContract()"/> // 删除合同的图标元素 通过@click来监听事件,删除合同名称 <a-icon // 当元素数量大于1时,才显示删除图标 v-if="index>0" type="minus-circle" style="margin-left: 11px; font-size: 25px" @click="delContract(index)" /> </a-form-item> </a-row> </div>
:disabled(单向绑定),来控制是否可以输入;@input(event事件监听),来处理输入的值
v-decorator(双向绑定)来进行对元素进行校验处理; - 在rules中添加contractNameCheck的rule。 rules是放在data()中,
data(){ return { rules: { // 引入的公共rules ...rules, contractNameCheck: { rules: [ { required: true, message: '请输入合同名称' }, ], // 公共的rule(引入使用),类似trigger:blur,内容如下: // export const commonInputRule = { // validateTrigger: 'blur', // validateFirst: true,} ...commonInputRule, }, } } }
- 在methods方法中,添加disabledByAppKey(),handleInputChange(index, ‘contractName’, $event),addContract(),delContract()等方法
methods: { ... // 通过appKey控制disable disabledByAppKey() { return this.appKey ? !(this.appKey === '***') : false }, // 增加合同名称 addContract() { if (this.contractList.length > 2) { this.$message.error('最多只能添加3个合同名称') return } // push 添加对象 this.contractList.push({ contractName: undefined }) // 通过setFieldsValue把list赋值给template要遍历的contractList this.form.setFieldsValue({ contractList: this.contractList }) }, // 删除合同名称 delContract(index) { if (this.contractList.length > 1) { // splice通过index删除list中的对象 this.contractList.splice(index, 1) // 通过setFieldsValue把list赋值给template要遍历的contractList this.form.setFieldsValue({ contractList: this.contractList }) } }, // 合同名称输入框值改变 handleInputChange(index, field, event) { // field表示传入的属性值,通过event事件,event.target.value来获取输入的值 this.contractList[index][field] = event.target.value }, }
- 保存之后,点击编辑进来,要回显数据,要遍历并通过const obj,逐个设置【重点】
- watch监听数据变化
watch:{ info:{ handler(val){ // $nextTick表示立即钓调用,this.setInfo为方法 if(val) this.$nextTick(()=>this.setInfo(val)) } // 立即渲染 immediate: true, // 进深渲染 deep: true, } }
- 在methods的setInfo方法中
setInfo(detail){ // 设置合同名称 if (detail.contractNameList) { // detail.contractNameList为List<String>的list,把list转化为是对象类型的JS数组,使用map this.contractList = detail.contractNameList.map((item) => ({ contractName: item })) // 要使用this.$nextTick,立即执行。 this.$nextTick(() => { // 遍历js的list, 不能直接设置,如: // this.form.setFieldsValue({contractList, this.contractList}),这样的话,只会显示第一条数据 this.contractList.forEach((item, index) => { const obj = {} // 采用如下方式,根据下标设置每个值,才能获取所有的list的数据 obj[`contractList[${index}]`] = this.contractList[index] this.form.setFieldsValue(obj) }) }) } }
五、元素添加红色*
号
报错信息
column前面添加必填的红色*号,但子元素不是input输入框,无法添加
报错原因
因为子元素input无法通过validator来控制父元素column前面的红色*
号。
解决方案
通过添加新样式的形式来解决
- template中的代码如下
<a-row> <a-col :span="12"> <!-- label-required 是用来显示红色 * 号 --> <a-form-item label="名称1:" class="form-item left-col label-required"> <p class="content">{{ name2 }}</p> </a-form-item> </a-col> <a-col :span="12"> <a-form-item label="名称2:" class="form-item label-required"> <p class="content">{{ name2 }}</p> </a-form-item> </a-col> </a-row>
- 在页面用element找到element找到对应的元素和对应的style信息
- 在style中添加红色的
*
号样式// /deep/ 表示二级元素,要用这个 /deep/ .label-required { // ::before表示在之前,添加样式 .ant-form-item-label label::before { display: inline-block; margin-right: 4px; color: #f5222d; font-size: 14px; font-family: SimSun, sans-serif; line-height: 1; content: '*'; } }
- 调整之后,效果如上图的截图的名称2一样
- 如果想在元素之前添加红色*号,因为不是二级元素,不用/deep/
.span-required::before { display: inline-block; margin-right: 4px; color: #f5222d; font-size: 14px; font-family: SimSun, sans-serif; line-height: 1; content: '*'; }