7. Vue 3组件开发实战与Element-Plus使用指南

1 前言

关于vue的知识通过前面的章节我们已经学的差不多了,所以本章将带大家实践一下、深刻体会vue提供的便利所在。

注意,由于我个人喜欢使用TypeScriptscss语法,所以我在vue项目中会直接使用这两者,不会安装、使用这两者的可以参考前面的文章。

包括项目建立等基础性内容,这里也不再重复赘述了。

1.1 按钮组件

对于“按钮”这种非常通用的组件来说,一般我们都会将其放在components文件夹下:

image-20240124214943936

由于实现一个基本的按钮过于简单,所以我这里直接将代码完成如上图。

注意2号位置,使用的是vue的插槽知识,忘了的可以到 Vue组件全面指南回顾。

至于3号样式中的内容就属于css的知识了,用于设置该按钮组件的各种基本样式,不会的自己多敲一敲就好了。

注意scss中这里使用的&符号,代表的是父标签,比如这里&:hover等价于.Mbutton:hover

完成代码如下:

<script setup lang="ts">
</script>

<template>
    <button class="MButton">
        <slot></slot>
    </button>
</template>

<style scoped lang="scss">
.MButton {
    height: 25px;
    background-color: #ecf5ff;
    color: #48a2ff;
    border-radius: 5px;
    cursor: pointer;
    user-select: none;
    border: solid 1px #a0cfff;

    &:hover {
        background-color: #409eff;
        color: #e5f2ff;
    }
}
</style>

使用方法如下:

image-20240124215534571

使用vue组件,其实和使用普通的标签没有太大的区别,正如上图所示:

  1. 首先你需要将组件导入到要使用的页面中
  2. 然后将导入的该组件直接写在template标签中即可
  3. 如果想要绑定基本事件,那就直接绑定即可,这里涉及到前面提到过的“透传”概念。

至于写在标签中的字符串“测试按钮”,也会通过插槽传入其内部slot标签位置。

注意,这里标签的外围之所以会出现一个空隙,是因为其默认行为导致的,你可以在assets/main.css这个全局样式文件中添加以下代码将其取消掉:

*{
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

本节的代码实例中实际使用的是less,但其和scss语法几乎一致,至少本文是一致的,所以你可以直接将less更改为scss、其它的保持不变即可。

1.2 input组件

按钮控件比较简单,没用到太多的vue技术,所以这里再来一个稍微复杂一点的input标签:

image-20240124221308106

样式就不再多说了,可以参考后文源码自己参照一下即可,比较简单,这里主要讲解vue的语法运用。

首先注意,此时我并没有将input标签作为该组件的根标签,所以外面想要绑定input标签内的值就不能直接使用v-model

但为了能够让外面依旧可以这样用,这里我就做了一个中间层,也就是第1步,先在组件内部定义一个响应式变量input_value绑定到input标签上同步数据。

然后就是第2步,通过定义propsemits,就可以实现一个自定义的v-model双向绑定值,比如我这里就是value这个变量名。

紧接着来到第三步,使用watch函数进行监视,一旦input标签内的值发送变化,那么会自动同步到input_value变量上,一旦input_value值发送变化,就会立马触发相应的watch函数,比如我这里就是通过emits来更新外部的值。

同样的,如果外面传入了value值、并且发生了变化,也会立马同步给input_value,然后input_value继续将数据同步给真正的input标签。

简单来说就是,通过前面这一系列的步骤,就实现了v-model中的标签数据与响应式变量双向同步的功能。

这里响应式变量指的是外部使用该组件传入的响应式变量,也就是这里触发的update:value方法与value值。

最后第4步,还添加了一个placeholder属性,让外部填充input标签的占位符,此时使用方式如下:

image-20240124222531296

可能还存在很多细节之处没有处理到,可以自己在继续完善,完整代码如下:

<script setup lang="ts">
import { ref, watch } from 'vue';

const props = defineProps(['value', 'placeholder'])
const emits = defineEmits(['update:value'])

const input_value = ref('');

watch(input_value, () => {
    emits('update:value', input_value.value)
})

if (props.value) {
    watch(props.value, () => {
        input_value.value = props.value;
    })
}
</script>

<template>
    <div class="MInput">
        <input v-model="input_value" :placeholder="props.placeholder">
    </div>
</template>

<style scoped lang="scss">
.MInput {
    display: inline-block;

    input {
        width: 200px;
        height: 25px;
        border: 1px solid #dcdfe6;
        border-radius: 5px;
        outline: none;
        padding: 0 10px;
        font-size: 13px;
        color: #8e9092;

        &::placeholder {
            color: #ddd;
        }
    }
}
</style>

1.3 简单总结

总的来说,vue中组件是一个和html中标签很像的东西,所以我相信你是可以很快上手的,当然如果你觉得还是不够熟悉,可以自己再试着复现几个常用组件练练手。

大多数时候我们是不需要自己去实现这些控件的,因为前端有很多开源库,就和上面两个组件一样,已经被别人封装好了,我们可以直接拿来用。

但想要熟练使用这些开源组件的前提是你得对这里基本的技术细节有一定的了解才行,我这里简单总结几个常用的组件功能:

  1. props:用于外部向组件内部传值的,一般被用于v-model以及使用:直接绑定的响应式变量,但同样也包括非响应式变量,比如前面input标签中的placeholder参数。
  2. emits:用于内部触发外部函数的,常用于v-model反向更新父组件响应式变量的值,同样也常用于使用@符号绑定的自定义事件函数。
  3. watch:用于监视响应式变量的变化
  4. slot:常用于外部向组件内部传递html标签代码

不管怎么说,即使是复制粘贴使用开源库,我觉得你也应该至少学会使用这4个基本的vue功能,

2 目录树

开源UI库对于常用的前端控件已经实现的非常好了,比如后文将要介绍的Element-Plus开源库的使用。

但对于一些特殊的、不那么通用的组件,一般开源库都不会提供相应的实现,此时就需要我们自己封装了。

比如文本要介绍的“目录树组件”,在开源库中就很少有实现的,而其在一些需要显示文件目录的地方又确实很有用。

所以本文就带大家来看看一个目录树的实现逻辑。

2.1 代码思路

写代码前思路很重要,目录树大家应该都很熟悉,比如windows系统上的文件资源管理器中,就有很多目录,只不过它的目录结构并不允许多个层次的文件同时出现。

所以这里我以vscode中目录树为基准:

image-20240125192536167

它就可以很好的将不同目录下的文件全部展示到一个控件中去。

而我们的目的就是用vue实现出这样一个目录结构,经过前面的我的摸索,大概可以将目录树分为两个结构:

  • DirNode:目录节点。

目录树最外层肯定是一个目录,也就是这里的DirNode,每个目录里面只有两个东西:目录、文件,其中文件可以直接展示,而子目录则继续使用DirNode表示,这样就完成了无限递归嵌套的任务,无论你有多少层,都可以用DirNode表示出来。

  • FileTree:目录树

这个结构主要是用来整理上面的DirNode样式的,比如我们一般需要设置目录的最大高度,如果超出了这个高度就需要显示滑动条。

有了思路,我们就可以开始来写代码了,根据前面的思路,这里就将其分开作为两个组件进行实现。

作者:余识
全部文章:0
会员文章:0
总阅读量:0
c/c++pythonrustJavaScriptwindowslinux