踩坑记19 element-plus 根据视口尺寸隐藏元素 | vue3 v-model props emit 二次封装el组件 | vite import 路径 Vetur报错

2021.9.3

坑61(element-plus、根据视口尺寸隐藏元素):文档要求引入文件 import 'element-plus/lib/theme-chalk/display.css',其中地址错误,查看包文件结构后,确认地址应该为:

import 'element-plus/theme-chalk/display.css';

地址改变的原因是element-plus更新到1.1.0-beta.1版本的时候的变化。详细见: Breaking changes made in 1.1.0-beta.1 · Discussion #3020 · element-plus/element-plus · GitHub ,可以看到element-plus的文件组织形式/项目结构发生了较大变化。

坑62(vue3、v-model、props、emit、二次封装、父组件和子组件双向传递数据、el-form-item、el-input、el-checkbox-group、el-radio-group):目标是封装el-form-item,而el-form-item中又包含了el-input、el-checkbox-group、el-radio-group(当然更深入还有el-checkbox、el-radio)。

首先看一下封装前父组件中el-form-item的使用,代码量较多,数据存放在dataForm中,如下:

<el-form-item prop='inputData'>

    <el-input class='isInput'

    v-model="dataForm.inputData"

    placeholder="输入"

    type="text"

    clearable autocomplete>

    </el-input>

</el-form-item>



<el-form-item prop='checkboxData'>

    <el-checkbox-group class='isSelectbox' 

    v-model='dataForm.checkboxData' >

        <el-checkbox label='复选1'></el-checkbox>

        <el-checkbox label='复选2' ></el-checkbox>

        <el-checkbox label='复选3'></el-checkbox>

    </el-checkbox-group>

</el-form-item>



<el-form-item prop='radioData'>

    <el-radio-group class='isSelectbox' 

    v-model='dataForm.radioData'>

        <el-radio label='单选1'></el-radio>

        <el-radio label='单选2'></el-radio>

    </el-radio-group>

</el-form-item>

之后开始封装,期间踩坑无数,记录一些要点:

1、el-input、el-checkbox-group、el-radio-group这些组件都使用了v-model进行数值的双向绑定,而不是使用html中原生inputvalue

2、父组件传值到子组件props子组件传值到父组件emit

3、父组件props传值的时候,使用v-model

循序渐进:在多次尝试el-input的封装失败后,先尝试了原生input的封装

子组件中,input输入框的value绑定通过props(父组件中使用了v-model)传入数据值dataModel。在input输入框值改变触发input事件时,通过emit发送dataModel更新事件给父组件,更新dataModel的值为$event.target.value。代码如下:

<template>

<input type='text' :value='dataModel'

    @input="$emit('update:dataModel',$event.target.value)" />

</template>



<script>

export default {

    name: 'TestInput',

    props: {

        dataModel: String,

    },

    setup() {



    }

}

父组件中调用,通过v-model绑定数据即可,代码如下:

<TestInput v-model:dataModel='inputData' />

// 等同于以下

<TestInput :dataModel='inputData' @updata:dataModel='dataModel=$event' />

另外,如果直接用v-model='inputData',不指定具体属性名称时,默认名称是modelValue

正式封装:接下来正式进行包含el-input、el-checkbox-group、el-radio-group的el-form-item的封装。首先确认传递的props参数如下。

type:指定el-form-item中具体的组件类型,String,值为 input / checkbox / radio ;

prop:指定el-form-item的prop属性值,String;

dataModel(需要在父组件和子组件之间双向传递):指定el-form-item中具体的组件的v-model绑定的数据值,输入框String,选择组Array;

text:指定el-form-item中具体的组件的提示文本,输入框String,值绑定到placeholder,选择组Array,值循环绑定到选项的label(此处暂时以提示文本作为选项的label值;有具体需要的话,应另设一个label参数,确定每个选项的label)。

其中,数据值dataModel在父组件中会用v-model传递。

接下来是具体解决方案。

子组件中,数据值dataModel直接绑定到el组件的v-modelemit事件的触发参考element-plus各组件的文档:el-input使用input事件;el-checkbox-group和el-radio-group使用change事件。emit事件所传的值也与原生input不同,根据文档,input和change事件的参数值就是组件的数据值,即$event。代码如下:

<template>

    <el-form-item :prop='prop'>

        <el-input v-if='type==="input"' class='isInput'

            v-model='dataModel'

            @input="$emit('update:dataModel',$event)"

            :placeholder="text"

            type="text"

            clearable autocomplete>

        </el-input>

        <el-checkbox-group v-else-if='type==="checkbox"' class='isSelectbox'

            v-model='dataModel'

            @change="$emit('update:dataModel',$event)">

            <el-checkbox v-for='item in text' :key="item"

            :label='item'></el-checkbox>

        </el-checkbox-group>

        <el-radio-group v-else-if='type==="radio"' class='isSelectbox'

            v-model='dataModel'

            @change="$emit('update:dataModel',$event)">

            <el-radio v-for='item in text' :key="item"

            :label='item'></el-radio>

        </el-radio-group>

    </el-form-item>

</template>





<script>

export default {

    name: 'SearchItem',

    props: {

        type: String,

        prop: String,

        dataModel: [String, Array],

        text: [String, Array],

    },

    setup(){



    },

}

</script>

需要注意的一点是props的类型判断,根据前文定下的来。

另外,el-checkbox和el-radio,现在因为没有配置显示值,默认显示值是和label相同的。如有需要,label及显示提示文本也可以分开配置。

父组件中调用,通过v-model绑定dataModel数据值,并配置其他各项props参数,代码如下:

<SearchItem type='input' prop='inputData'

v-model:dataModel='dataForm.inputData' 

text='输入' />



<SearchItem type='checkbox' prop='checkboxData'

v-model:dataModel='dataForm.checkboxData'

:text='["复选1","复选2","复选3"]' />



<SearchItem type='radio' prop='radioData'

v-model:dataModel='dataForm.radioData'

:text='["单选1","单选2"]' />

现在一些样式也可以移动到子组件中了,关于表单样式,见坑60(el-form、inline模式、元素高度不统一、元素垂直间距不统一),链接: 踩坑记18 vue 组件折叠 v-show | 深度合并对象 deepmerge | el-checkbox-group size设置无效 | el-form中元素高度、垂直间距不统一_Alloom的博客-CSDN博客

参考一览:

Props | Vue.js (vuejs.org)  vue3文档:props类型

Props | Vue.js (vuejs.org)  vue3文档:props验证

组件基础 | Vue3中文文档 - vuejs (vue3js.cn)  vue3文档:在自定义组件中使用v-model

v-model | Vue.js (vuejs.org)  vue3文档:3.x语法下的v-model

组件 | Element (element-plus.org)  element-plus文档:Input 输入框

组件 | Element (element-plus.org)  element-plus文档:Checkbox 多选框

组件 | Element (element-plus.org)  element-plus文档:Radio 单选框

Vue3组件(三)把别人的组件拿过来再封装一下 - 简书 (jianshu.com)

Vue3.x + Vite2.x 入门实战 03:二次封装el-input组件 - 掘金 (juejin.cn)

el-input 输入框不能输入值_sinat_23536373的博客-CSDN博客_el-input无法输入  vue2的

element-ui组件的二次封装 - 简书 (jianshu.com)  vue2的

坑63(vue、vite、import、路径、Vetur):引入vue组件文件时Vetur报错(但可以正常运行),引入代码如下:

import AItem from '../../../components/widgets/util/AItem.vue'

错误信息如下:

File name 'g:/Users/Administrator/VueProjects/xxx-web/src/components/widgets/util/AItem.vue' differs from already included file name 'g:/Users/Administrator/VueProjects/xxx-web/src/components/widgets/util/aItem.vue' only in casing.

The file is in the program because:

Root file specified for compilation

Imported via '../../../components/widgets/util/AItem.vue' from file 'g:/Users/Administrator/VueProjects/xxx-web/src/views/system/user/index.vue'Vetur(1149)

可以知道Vetur报错是因为两个文件名仅大小写不同,但都用于编译。这是因为修改文件名导致的:从aItem.vue变为AItem.vue。

解决方法一(推荐):关闭vs code,重新打开就好了。

解决方案二:警用Vetur。可以尝试改用Volar,实验了一下修改文件名时,Volar不会报此错误。

解决方法三:使用别名@。关于别名配置方法见坑49( vite2、alias、路径别名 ),链接: 踩坑记14 vs code 快捷键 | vue3 vite2 alias 别名设置_Alloom的博客-CSDN博客。代码如下:

import AItem from '@/components/widgets/util/AItem.vue'

一个不成功的方法:

另外参考了此篇 Vue 引入路径正确的,但一直报错: Already included file name ‘××ב differs from file name ‘××ב only in casing._estrusKing的博客-CSDN博客 中,去掉.vue后缀的方法,但运行会报错,如下:

[plugin:vite:import-analysis] Failed to resolve import "../../../components/widgets/util/AItem" from "src\views\system\user\index.vue". Does the file exist?

推测可能是使用vite的原因,import模式有些不同。

by 莫得感情踩坑机(限定)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值