【Vue】怎样让你的组件变得更灵活?

这篇具有很好参考价值的文章主要介绍了【Vue】怎样让你的组件变得更灵活?。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

引言

在我们的日常开发中,我们一般会引入做的比较成熟的第三方UI框架,比如ElementUI。

当我们在调用UI框架中的组件时,会发现常用的调用方式有两种,一种是直接在页面中嵌入组件:

<el-dialog
    v-model="dialogVisible"
  >
  ...
</el-dialog>

另一种则是在js中通过方法调用:

ElMessageBox.confirm(...)

可以看到ElementUI中的组件使用方式更加灵活,可以满足不同场景的需求,那么这两种不同的调用方式都是如何实现的呢?下面我们就在弹框组件的基础来实现一下。

全局组件注册

我们在home中引入了Modal弹框,才能在home中使用:

...
<script setup>
    import Modal from '../components/Modal';
</script>

像弹框这种在项目中会被频繁使用到的公共组件,每次都在使用的地方引入无疑是很不方便的,所以我们可以将弹框组件注册为全局组件,在main.js中,我们添加如下代码。

...
+ import Modal from './components/Modal/Modal.vue';

  const app = createApp(App);
+ app.component('Modal', Modal);
  app.use(router).mount('#app');

相对于Vue2来说,Vue3中注册全局组件,不再将组件挂载到Vue对象上,而是应该挂载到createApp生成的实例上,所以,如果我们有多个app实例的情况:

import Modal from './components/Modal/Modal.vue';

const app1 = createApp(App1);
const app2 = createApp(App2);

// 只有app1注册了组件
app1.component('Modal', Modal);

app1.mount('#app1');
app2.mount('#app2');

如上的代码中,只有app1实例下才挂载了弹框组件,app2不会受到影响。

这样我们在app下的任何组件中,都可以直接使用我们的弹框组件而不需要再额外引入了。

函数式组件

除了嵌入的方法外,函数式调用的方法也是比较常见的,而且相对于嵌入式来说,函数调用的时候可以将组件绑定到body元素下,避免了组件的样式被其他地方所覆盖,从而可能导致组件展示错乱,我们的弹框组件与app组件在同一级渲染。

在Modal文件夹下新建index.js文件,接下来我们就在index.js文件中来实现下弹框组件的函数式调用。

// 弹框的函数式调用方法
function openModal () {
    // 1. 创建弹框组件实例
    // 2. 创建渲染节点
    // 3. 将实例挂载到页面节点上
}

export default openModal

我们定义了一个openModal的方法,并且梳理下这个方法中要实现的逻辑,最后导出了这个方法供其他地方调用。

我们都知道在Vue3中是通过createApp来创建一个组件实例的,所以我们引入createApp和Modal.vue,创建一个弹框组件实例。

import { createApp, provide } from 'vue';
import Modal from './Modal.vue';

function openModal () {
    // 1. 创建弹框组件实例
    const modalApp = createApp(Modal);
    // 2. 创建渲染节点
    // 3. 将实例挂载到页面节点上
}

我们在实现Modal组件的时候是有一些属性需要传递的。

<Modal
    title="信息提示"          // 弹框标题
    content="打开了一个弹框"   // 弹框内容
    ...
>
</Modal>

createApp的第二个参数就可以让我们传递参数给弹框组件的props属性。

function openModal (options = {}) {
    const modalApp = createApp(Modal, {
        // 控制弹框是否显示
        modelValue: true,
        // 传入弹框标题
        title: options.title || 'title',
        // 传入弹框内容
        content: options.content || 'content',
        // 传入关闭弹框的方法
        close: () => {
            
        }
    })
}

调用openModal方法时,我们会传入options参数,携带弹框的标题,内容等信息,来赋值给组件的props属性。

接下来,我们继续实现创建渲染节点并将弹框实例挂载上去。

function openModal () {
    // 1. 创建弹框组件实例
    ...
    // 2. 创建渲染节点
    const dom = document.createElement('div');
    document.body.appendChild(dom);
    
    // 3. 将实例挂载到页面节点上
    modalApp.mount(dom);
}

这样我们就完成了弹框实例的挂载渲染,并且可以通过openModal方法进行函数式调用。

<template>
    <button @click="open">打开弹框</button>
</template>
<script setup>
    import openDialog from '../components/Modal';
    
    const openDialog = () => {
        openDialog({
            title: '标题',
            content: '内容'
        });
    }
</script>

我们在传递props参数的时候,还传入了close方法用来关闭弹框,那要怎么实现关闭弹框的方法呢?

其实简单来说,关闭弹框就是将弹框实例卸载下来,所以在close方法中,我们添加如下代码:

close: () => {
    // 将弹框实例卸载
    modalApp.unmount(dom);
    // 删除页面节点
    document.body.removeChild(dom);
}

修改下Modal.vue中的按钮点击事件:

const onOk = () => {
    props.close();
}

通过DOM结构,我们可以看到,点击确定按钮时,弹框组件已经从DOM树中删除了。

到目前为止,我们使用组件的时候还是需要引入方法,为了方便全局使用,我们可以进一步优化,将openDialog方法注册到全局属性中去。

那么我们在什么时候完成注册的操作呢?当我们使用第三方插件的时候,经常会使用到app.use方法。

app.use(router).mount('#app');

其实use方法就是Vue提供给我们来注册插件的,use方法会先判断插件有没有被注册,如果没有注册,会调用插件的install方法,如果插件不是对象,本身就是个方法,那么就执行这个方法。

所以我们可以添加一个dialogInstall方法,在use执行的时候,将openDialog方法注册到全局。

function openModal () {
    // 1. 创建弹框组件实例
    ...
    // 2. 创建渲染节点
    ...
    // 3. 将实例挂载到页面节点上
    ...
}

function dialogInstall (app) {
    console.log('dialogInstall was invoked');
    app.provide('OPENDIALOG', openModal)
}

export {
   openModal,
   dialogInstall
}

在main.js中引入dialogInstall方法并注册。

import {dialogInstall} from './components/Modal';
...
app.use(dialogInstall).use(router).mount('#app');

当我们刷新页面的时候,可以看到“dialogInstall was invoked”这句话在控制台中打印出来了,说明dialogInstall方法在注册的时候确实被执行了。

那么在其他组件中,我们使用inject获取到openModal方法进行调用。

const openDialog = inject('OPENDIALOG');

const open = () => {
    openDialog({
        title: '标题',
        content: '内容'
    });
}

我们这里是利用provide和inject来实现全局属性的传递,大家也可以使用app.config.globalProperties来挂载openDialog方法,不妨自己去尝试实现一下。

自定义指令

除了不同的调用方式外,有的时候我们还希望给组件添加一些自定义的指令来完成一些特殊需求,丰富组件的功能。

在上一节的插槽模块中,我们介绍了怎么在弹框组件中传入表单内容,如果要求弹框组件显示的时候,表单内的输入框自动获得焦点,要怎么实现呢?

我们定义一个自定义指令v-focus来实现自动获得焦点的功能,在表单子元素中,给input输入框绑定v-focus指令。

<Modal
    title="信息提示"
    content="打开了一个弹框"
    v-model="modalVisible"
>
    <form>
        <label>姓名: </label>
        // 给姓名输入框增加v-focus指令
        <input v-focus v-model="name" placeholder="请输入姓名" />
        
        <label>年龄: </label>
        <input v-model="age" placeholder="请输入姓名" />
    </form>
</Modal>

指令已经添加了,接下来就是实现指令功能了,Vue3注册自定义指令也需要在app实例上进行,我们在main.js中添加v-focus的代码。

app.directive('focus', {
    mounted(el) {
      // el为指令绑定的页面元素
      el.focus()
    }
})

通过directive方法我们定义了一个指令,自定义指令时也支持钩子函数的调用,我们希望在表单元素加载完成后自动获得焦点,所以在mounted钩子中增加元素获得焦点的方法。

钩子函数支持多个参数mounted(el, binding),el表示指令绑定的DOM元素,binding则是指令的一些参数信息,目前弹框组件在页面位置是居中展示,如果我们希望可以自定义弹框组件的位置,就可以通过binding来传递参数。

我们定义一个新的指令v-position用来控制弹框的位置。

app.directive('position', {
    mounted(el, binding) {
      // 设置弹框的top位置
      el.style.position = 'absolute';
      el.style.top = binding.value + 'px';
    }
})

在Modal.vue中给弹框内容添加v-position指令,并携带位置参数。

<div class="modal-content" v-position="200">
...
<div>

可以看到,v-position指令传入了一个参数200,在mounted中,我们通过binding.value来获取传入的参数并赋值给元素的top属性。

参数也支持以对象的方式传入。

<div class="modal-content" v-position="{top: 200, left: 400}">
...
<div>
app.directive('position', {
    mounted(el, binding) {
      // 设置弹框的top位置
      el.style.position = 'absolute';
      el.style.top = binding.value.top + 'px';
      el.style.left = binding.value.left + 'px';
    }
})

binding除了参数,还可以获取到指令的属性,比如我们让弹框的top属性单独设置。

<div class="modal-content" v-position:["top"]="200">
...
<div>
app.directive('position', {
    mounted(el, binding) {
      // 设置弹框的top位置
      el.style.position = 'absolute';
      el.style[binding.arg] = binding.value + 'px';
    }
})

不管是arg还是value,都支持传入动态参数,这也让自定义指令的使用变得更加灵活。

总结

本小节中我们介绍了组件的全局注册,以及组件函数式调用的实现,在Vue2中,因为常规组件优化的不够完善,使用函数式组件初始化和渲染都很快,可以大幅度的提高页面的响应程度,提升性能,这也是函数式组件的主要应用场景。

在Vue3中,常规组件得到优化,函数式组件的性能提升已经很微小了,常规组件就足以满足日常的开发需求了。

然后我们进一步介绍了Vue3中如何去自定义指令,以及自定义指令相关的传参数方法,使用自定义指令可以辅助我们的组件实现更多更加复杂的功能。通过本节的学习,希望大家对组件的概念有个更清晰的理解,对组件的使用也可以变得更加灵活。文章来源地址https://www.toymoban.com/news/detail-455874.html

到了这里,关于【Vue】怎样让你的组件变得更灵活?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 5款冷门小工具,让你的电脑变得与众不同

    每个人的电脑中都会安装很多软件,可能还保留着很多不为人知的冷门软件。不过虽然冷门,但绝不意味着低能,相反很多冷门软件的功能十分出色。闲话少说,接下来我就给大家推荐5款冷门小工具,看一看有没有你喜欢的。 TileIconifier是一款用于自定义Windows 10的磁贴图标的

    2024年02月07日
    浏览(41)
  • Linux常见指令大全及周边知识:让你的命令行变得更加强大

    目录 文章目录 前言 一,Linux操作系统是啥? 二,Linux操作系统具有以下特点 三,指令的学习 1,指令是什么? 2,ls 指令及其常用的衍生指令: 周边知识: ls:指令的作用是显示当前路径下的文件名 ls -l :显示当前路径下更详细的文件属性包括文件名 ls -a :显示当前路径下的

    2024年02月05日
    浏览(44)
  • C语言柔性数组详解:让你的程序更灵活

    仔细观察下面的代码,有没有看出哪里不对劲? 还有另外一种写法: 你应该一眼就看到了,结构体的最后一个成员数组的写法是 int arr[]; 或者是 int arr[0] ,这两种写法是等价的,意思是这个数组的大小是 不确定的、未知的、可以变化的 。 C99允许这种特殊的结构体存在。这

    2024年02月09日
    浏览(44)
  • 设计模式之策略模式:让你的代码灵活应对不同的算法

    作为一个程序员,我们经常会面临着在不同的情况下选择不同的算法来解决问题的需求。这种情况下,策略模式是一个非常有用的设计模式。在本文中,我将向你介绍策略模式的概念、结构以及如何应用这个模式来使你的代码更灵活。 策略模式是一种行为型设计模式,它允许

    2024年02月08日
    浏览(43)
  • Animation Rigging 如何让你的Avatar人物更具灵活性

    Animation Rigging 是 Unity 官方发布的可以对 Avatar 人物骨骼进行约束的工具,已经有稳定的经过验证的 Vertified 包体,可以将其理解为一个 IK 工具,使用它可以让我们的人物动作表现更具灵活性。 Rig Builder 依赖 Animator 组件,所以将其与 Avatar 的 Animator 组件挂载于同一个物体上,

    2023年04月21日
    浏览(68)
  • 让你的网站变得更智能 - B2 Pro主题问答模块新增OpenAI ChatGPT机器人自动回答功能

    作为一个网站管理员,你一定会希望能够给你的用户提供更多、更好的服务。那么,你是否曾经想过为你的B2 Pro主题问答模块新增一个智能机器人自动回答功能呢?相信你一定想要这个功能,因为它能够大大提升你网站的用户体验。 现在,我们为你提供了一个好消息。我们已

    2024年02月09日
    浏览(54)
  • 【设计模式】模板方法模式--让你的代码更具灵活性与可扩展性

    在软件开发中,设计模式是一种经过实践检验的、可复用的解决方案,它们可以帮助我们解决某一特定领域的典型问题。设计模式不仅能提高代码的可读性、可维护性,还能让我们的代码更加灵活和易于扩展。在这个不断发展的技术世界中,了解并掌握设计模式对于软件开发

    2024年02月04日
    浏览(39)
  • 开源Blazor UI组件库精选:让你的Blazor项目焕然一新!

    今天给大家推荐一些开源、美观的Blazor UI组件库,这些优秀的开源框架和项目不仅能够帮助开发者们提高开发效率,还能够为他们的项目带来更加丰富的用户体验。 注:排名不分先后,都是十分优秀的开源框架和项目 Ant Design Blazor 是一个基于 Blazor 的前端 UI 组件库,它是

    2024年02月15日
    浏览(35)
  • 「为什么代码要整洁?」——代码整洁度对于项目质量的影响,让我们通过这边文章来教你js和ts的代码整洁技巧,让你的项目更出众

    为什么代码要整洁? 代码质量与整洁度成正比。有的团队在赶工期的时候,不注重代码的整洁,代码写的越来越糟糕,项目越来越混乱,生产力也跟着下降,那就必须找更多人来提高生产力,开发成本越来越高。 整洁的代码是怎样的? 清晰表达意图、消除重复、简单抽象、

    2024年02月07日
    浏览(69)
  • vue设置全局变量:让你的数据无处不在!

    在 vue 开发中,如何设置全局变量是一个关键问题。本文将介绍多种方法,帮助大家轻松实现全局变量的共享,提升 vue 项目的开发效率。让我们一起来探索这些方法,为你的 vue 项目带来更好的开发体验。 通过在 vue 的原型上定义属性,可以在所有组件中访问该属性。例如,

    2024年02月08日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包