Vue.js组件开发从1到100

vue 3.0实现数字(0-100) 滚动显示动画 阅读详情

100

如果说从0到1是解决温饱的过程,那么从1到100就是实现共同富裕的漫漫长路。

认真看过Vue.js官方文档和《Vue.js组件开发从0到1》的同学相信已经能胜任正常的业务开发了,但就像前文中提到的“实现同样一个小功能,可以有千万种写法”,作为一个积极向上的程序猿,我们始终在思考怎样才能写出优雅的代码,也就是更适合当前业务场景的代码。本文希望和大家共同探索学习如何从1到100优雅地开发Vue.js组件。

组件的基本逻辑复用 - mixins

说到基于Vue.js的前端项目中的代码复用,个人总结下来有三种:

复用类型复用形式例子
UI复用组件通用对话框
框架无关的纯js逻辑复用工具类日期时间转换工具类
与框架相关的逻辑复用(使用了框架的相关接口)mixin页面渲染测速上报

UI复用我们已通过组件来实现。纯js逻辑的复用我们一般会把可复用代码抽离到一个工具类里,通过模块化的方式引入到各处使用。而与框架相关的逻辑代码怎么复用呢?例如这部分逻辑代码作为组件生命周期钩子函数的回调。Vue给我们提供了一种解决方案-混合 (mixins)。

mixins在官方文档中被定义为“一种分发 Vue 组件中可复用功能的非常灵活的方式”,其行为与继承特别像。 在mixin里定义的属性、方法会被自动挂载到使用该mixin的组件上。与继承不同的是,当mixin中定义的方法与组件中方法同名时,这两个同名方法都会被保留下来,并且默认优先执行mixin中的方法,而同名的是对象时,组件的键值对会覆盖mixin中对应的键值对。但选项合并的策略也是能自定义的,具体的例子请参考官方文档-选项合并和官方文档-自定义渲染合并策略,这里将举个页面渲染测速上报的例子来说明mixins的用法。

在页面(页面也就是一个组件)加载前(beforeCreate)记录时间点,在页面挂载到DOM后(mounted)再记录一个时间点,就能算出当前页面渲染耗时。这里可以看到,我们主要使用了Vue.js提供的生命周期钩子beforeCreate和mounted,代码如下:

<template>
<div>页面测速demo</div>
</template>
<script>
export default {
    startTime: 0,
    beforeCreate() {
        console.log('beforeCreate');
        this.startTime = Date.now();
    },
    mounted() {
        console.log('mounted');
        console.log((Date.now() - this.startTime) + ' ms');
        // 数据上报
    }
};
</script>

页面渲染过程(部分)如下timeline(时间线)所示:

页面渲染过程

页面测速逻辑是js逻辑,与UI代码复用无关,那这部分代码复用就只能归为上面提及的两种情形:

  1. 框架无关的纯js逻辑复用
  2. 与框架相关的逻辑复用(使用了框架的相关接口)

在页面测速时,我们必须依赖Vue.js提供的生命周期回调接口,所以属于与框架相关的逻辑复用。我们最多只能把计算逻辑和数据上报逻辑封装成工具类,在需要测速的页面中手动调用这些工具类完成测速需求。而mixins则能帮我们更进一步地封装和复用代码:

<template>
<div>页面测速demo</div>
</template>
<script>

// 页面测速逻辑
// PS:应该抽离到mixins文件夹里统一管理,这里仅为演示方便
const renderSpeedTest = {
    startTime: 0,
    beforeCreate() {
        console.log('beforeCreate');
        this.startTime = Date.now();
    },
    mounted() {
        console.log('mounted');
        console.log((Date.now() - this.startTime) + ' ms');
    }
}
// 页面逻辑
export default {
    mixins: [renderSpeedTest]
};
</script>

在需要测速的页面逻辑代码里添加mixins: [renderSpeedTest]就能复用测速逻辑,这要比手动调用工具类更加优雅(简洁、不易出错、后期统一维护)。

但是前面已经提到,默认的选项合并策略是先执行mixin里的方法,再执行组件里的同名方法。而我们的页面测速需求是需要先执行mixin的beforeCreate方法作为开始点记录,后继续组件的生命周期(beforeCreate…mounted),最后执行mixin的mounted方法计算页面渲染时间。因此需要用到[自定义选项合并策略]来自定义同名选项的执行顺序,这里由于时间关系就不展开了。

你并不总需要组件 - 指令

“在 Vue2.0 中,代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。” ——Vue官方文档 - 自定义指令

理解一样东西有两种方法:

  1. 作者的设计初衷是什么?为了解决什么问题? —— 了解背景
  2. 如何使用? —— 阅读文档,学习API,写demo

个人觉得第一种方法将理解得更加深刻。归纳文档的话,指令的设计是为了覆盖DOM元素操作逻辑复用的情况。理解了设计初衷后,我们快速阅览Vue指令提供的钩子函数- bind、inserted、update、componentUpdated、unbind,就相当于学会了加减乘除,至于用加减乘除来做什么,更多的是看业务场景,看你对指令本身的理解。下面举个性能优化的例子来一起学习指令的用法。

性能优化场景:假设一个长页面的顶部有一个旋转的物体,在滚到页面底部时,虽然旋转物体不可见,但任在旋转,这是一个不必要的消耗。但类似的动画物体越来越多,滚动及后面的操作也会越来越卡顿。

性能优化方法:但旋转物体离开视图时,暂停旋转。重新进入视图前,恢复旋转。

借助指令,我们怎样优雅地解决这个问题:

<template>
<div>
    <div>指令demo</div>
    <div class="rotate-obj" v-scrollInOut="startOrStop">旋转物体</div>
    <ul>
        <li v-for="i in testData">{{ i }}</li>
    </ul>
</div>
</template>
<style scoped>
    .rotate-obj { width: 100px; height: 100px; background: green; }
    li { height: 100px; }
</style>
<script>
import Vue from 'vue';

// 滚动检测逻辑
// PS:应该抽离到directives文件夹里统一管理,这里仅为演示方便

let io = null;
const scrollInOut = {
    // 指令绑定
    bind: function(el, binding) {
        console.log('bind');
        io = new IntersectionObserver(
            entries => {
                const entry = entries[0];
                // 获取绑定的值
                const callback = typeof binding.value === 'function' ? binding.value : null;
                if (entry.intersectionRatio === 0 ) {
                    callback && callback('out of viewport');
                } else {
                    callback && callback('in viewport');
                }
            }
        );
        io.observe(el);
    },
    // 指令解除绑定
    unbind: function(el) {
        io.unobserve(el);
        io = null;
    }
}

// 页面逻辑
export default {
    data() {
        return {
            testData: [1,2,3,4,5,6,7,8,9];
        }
    },
    methods: {
        startOrStop(inOrOut) {
            console.log('startOrStop: ', inOrOut);
        }
    },
    directives: {
        scrollInOut
    }
};
</script>

上面使用了浏览器一个新的接口IntersectionObserver API来监听具体元素是否在视窗内,可用于做图片懒加载等资源加载优化,具体内容请参考IntersectionObserver API 使用教程 - 阮一峰,简单易懂。总的来说,我们设计了一个指令,绑定该指令的DOM元素将拥有一个监听自身是否在视窗内的回调方法。类似地,我们可以用指令来封装一系列事件的绑定和组合,例如实现长按事件,滑动事件等。

结合作者设计的初衷、Vue指令提供的钩子函数以及上面的例子,相信大家在考虑怎么复用代码时能想起有指令这一种选择。

组件库的技术架构

学习了组件、mixins和指令,大家几乎能针对每一种场景写出合适的、优雅的代码了。随着项目的发展,组件的逐步积累,天然会按照项目交互和视觉规范形成一套组件,这一套组件的沉淀,将是后续启动新项目的基石,怎么将已有项目的组件用到新项目或其他已有项目中,将是我们要讨论的问题。

复制粘贴是一个有效的方法,但显然算不上优雅。将组件以npm包的规范整理成一个组件库,同时利用npm包的更新机制解决组件更新同步的问题,是业界的常规做法,这里以饿了么Vue组件库 - mint-ui为例,和大家一起学习怎么去搭建一个组件库?

我们先来看看Mint UI官网里的介绍:

mint-ui使用介绍

mint-ui特性介绍

从使用方式来看,是标准的npm模块引入,再通过Vue插件规范来进行全局注册或者按需引入部分组件。从特性来看,上面列举的丰富齐全、关注移动端性能、复用代码减小体积都是具体实现的事情,和架构无关。因此我们的重点在于:

  1. 代码怎么组织?
  2. 如何实现全部加载和按需加载?

纵使设计得再高深,答案也在代码里。

通过简单观察代码库里的代码文件结构以及阅读组件库入口文件index.js,我已找到答案。mint-ui将组件统一放在packages文件夹里,在index.js文件中全部引入,再对外export所有组件的引入,以及最重要的install方法。了解Vue插件的同学都知道,install是Vue插件的入口函数,在调用Vue.use(MyPlugin)来注册插件时,实际上会调用MyPlugin.install(Vue),所以入口文件index.js在入口函数install里面利用Vue.component来全局注册组件或者利用Vue.use来引入组件库里的插件。抽象来说,全部加载组件库这种做法,是通过Vue插件规范来实现的。

那按需加载是怎么实现的呢?下面介绍一个babel插件babel-plugin-component,babel主要用来将我们编写的es6、es7代码编译成浏览器兼容的es5代码,而babel-plugin-component则在编译过程中又做了一些小事:

// 编译前
import { Button } from 'components'

// 编译后
var button = require('components/lib/button')
require('components/lib/button/style.css')

至于这个css文件时怎么编译来的,通过阅读代码可知,.vue文件里采用css模块化解决方案——postcss来组织样式,可编译成单个css文件。

这么一说大家应该都明白了,babel-plugin-component具体配置请参考文档。mint-ui按照Vue插件的规范来组织代码,然后通过babel-plugin-component来实现按需加载。

而单个Vue组件怎么实现,在《Vue.js组件开发从0到1》中已详细介绍过。这里mint-ui将每一个组件都作为npm包,通过package.json文件指定入口文件为index.js,再在index.js里引入并对外暴露单vue文件(如果需要对插件进行逻辑操作,可以在这进行封装,前文也已经介绍过),如下:

export { default } from './src/button.vue';

看得比较浅显,简单回顾一下前面两个问题:

  1. 代码怎么组织?
    1. index里面引用组件,注册组件
    2. 单个组件采取.Vue文件 + js封装的模式
    3. css组织采用PostCSS
  2. 如何实现全部加载和按需加载?
    1. 作为一个Vue插件来使用,实现全部加载
    2. 利用babel-plugin-component来打包和引用,实现按需加载。

最后和大家分享一下之前阅读index.js的一个小困惑:

// auto install
if (typeof window !== 'undefined' && window.Vue) {
  install(window.Vue);
}

这里的自动安装是为了使得通过<script>直接引入mint-ui.js时能作为插件自动安装,之前一直想不明白,是局限于自己仅关注通过npm包这种使用场景,觉得这是一段冗余代码。

别钻牛角尖,学会多角度全面看待问题和自己遇到的困惑。

高阶组件 - 内置的transition组件分析 - 敬请期待

简单说一下:提供了一个render函数,使用底层方法构造任意想要的组件,返回。

复杂项目中的状态管理 - 敬请期待

组件与SSR - 敬请期待

Vue组件化开发 文章目录Vue组件化开发组件化开发:Vue实例方法与属性Vue.extend与Vue.Component全局指定、组件、方法实例:Popup插件的封装 Vue组件化开发 组件化开发: 1、组件化开发指的是将复杂的业务拆分为一个有一个的组件 2、组件化开发的组件一般来说要灵活 3、组件化开发涉及到了Vue的js组件封装,需要掌握Vue基础、Vue实例方法与属性、Vue.extend、Vue插件等知识... 阅读详情

相关推荐

构建Vue.js进度条组件:从设计到实现

props: {

weixin_42613018的博客 969

el-input只能输入1-100之间的数字

【代码】el-input只能输入1-100之间的数字。

weixin_54129994的博客 4667

Win10下ISE14.7安装避坑全记录:从License加载失败到ChipScope连不上,我踩过的雷都在这了

本文详细记录了在Win10系统下安装ISE14.7时遇到的常见问题及解决方案,包括License加载失败、IMPACT闪退、ChipScope连接故障等。通过实际案例和步骤解析,帮助用户避开安装陷阱,确保FPGA开发工具顺利运行。特别针对license问题提供了兼容性设置和文件修改的实用技巧。

weixin_42683394的博客 225

vue 加减数字输入框

index主页面 <template> <div> <numInput :frontTit="'限制年龄'" :afterTit="'周岁'" @num="getNum" /> <el-button @click="getData">获取</el-button> </div> </template> <script> import numInput from './numInput'.

qq_42619759的博客 2250

TensorFlow_PyTorch实战:构建AI人工智能回归模型

回归分析是机器学习的核心任务之一,用于预测连续型目标变量(如房价、股票价格、用户留存时间等)。基础线性回归模型的数学原理与代码实现多项式回归模型的过拟合处理与正则化技巧自定义数据集加载与数据预处理流程动态图(PyTorch)与静态图(TensorFlow)的编程范式对比模型评估指标与可视化分析方法核心概念:对比两大框架的架构设计,解析回归模型核心组件数学原理:推导线性回归的假设函数、损失函数及优化算法算法实现:提供TensorFlow和PyTorch的完整代码示例项目实战。

AI天才研究院 1429

QCustomPlot实现毫秒级时间轴数据的动态可视化与实时刷新优化

本文深入探讨了如何利用QCustomPlot库高效实现毫秒级时间轴数据的动态可视化与实时刷新。文章从基础配置讲起,详细介绍了时间轴初始化、数据平滑滚动、增量更新与内存管理等核心优化技巧,并分享了应对高频数据的缓冲策略及OpenGL硬件加速等高级优化手段,旨在解决实时图表卡顿问题,提升流畅度。

weixin_29012677的博客 424

vue中如何展现快速增长数字的动画

vue-countupjs的使用 vue-countupjs的前身就是countup.js专门用于做数字增长的动画,满足一些展示型数字的使用. 使用流程 1. 安装vue-countupjs npm install vue-countupjs --save 2. 项目中如何使用 <template> <div> <VueCountUp :start-value="0" :end-value="middleValue2.value1" :duration="1

Xyp9x的博客 2386

TouchGFX在STM32上的移植全过程:超详细版指南

深入讲解将TouchGFX集成到STM32开发环境的每一步,涵盖配置、驱动适配与UI调试。无论是初学者还是进阶开发者,都能快速掌握TouchGFX在嵌入式平台的应用技巧。

weixin_42443533的博客 600

vue的v-for循环指令

&lt;!DOCTYPE html&gt; &lt;html&gt; &lt;head lang="en"&gt; &lt;meta charset="UTF-8"&gt; &lt;script src="js/vue.js"&gt;&lt;/script&gt; &lt;title&gt;&lt;/title&a

幸福有多远 3200

四旋翼滑模控制:从理论到Simulink实现

本文深入探讨了四旋翼滑模控制的理论与Simulink实现,对比了其相较于PID控制在抗干扰和鲁棒性方面的显著优势。文章详细介绍了从精确动力学建模、内外环滑模控制器设计到指令解算的完整流程,并分享了Simulink仿真搭建、参数调试及抗扰性能验证的实战经验,帮助工程师掌握在复杂环境下提升四旋翼稳定性的进阶技能。

weixin_29163581的博客 375

MacOS下Mixly 2.0安装避坑指南:从Java环境到终端权限全解析

本文详细解析了在MacOS系统上安装Mixly 2.0时可能遇到的核心问题与解决方案。针对Java环境版本不兼容、MacOS Gatekeeper安全机制拦截以及终端权限不足三大常见障碍,提供了从检查并配置正确Java版本、安全设置绕过到彻底解决应用内部工具链权限的完整避坑指南,帮助用户顺利完成安装并正常使用。

weixin_29231725的博客 503

《Vue.js实战》数字输入框组件案例(包含练习1和练习2)

题目来源:《Vue.js实战》第七章 7.7.1实战:开发一个数字输入框组件 展示效果链接:https://loaln.github.io/vue_practice/html/7-7-1.html 数字输入框组件展示效果需求: 数字输入框只能输入数字,而且有两个快捷键按钮,可以直接减1或加1。除此之外,还可以设置初始值、最大值, 在数值改变时,触发一个自定义事件来通知父组件。 操作提...

Corlly的博客 1900

扣子Coze工作流教程:采集公众号爆文,一键仿写自动发布

通过本教程,你学会了如何利用扣子(Coze)平台构建一个完整的公众号文章自动处理工作流。这个系统不仅能够大幅提升内容产出效率,还能通过AI二创保持内容新鲜度和原创性。最佳实践建议:初次使用时,建议先保存为草稿而不是直接发布,以便人工审核;从简单的工作流开始,逐步增加复杂度;定期检查工作流运行日志,优化节点配置。自动化内容创作是新媒体运营的未来趋势,掌握这项技能将使你在数字内容领域占据显著优势。

互联网架构师笔记 1238

3分钟掌握Vue时间轴组件:timeline-vuejs终极使用指南

timeline-vuejs是一款专为Vue.js设计的极简时间轴组件,能够帮助开发者快速构建美观的时间线展示界面。作为一款轻量级组件,它不依赖任何大型第三方库,确保在各种Vue项目中都能高效运行。无论你是要展示个人经历、项目里程碑还是历史事件,这个Vue时间轴组件都能提供简洁优雅的解决方案。 ## 🚀 快速上手:零基础搭建时间轴 ### 环境准备 确保你的开发环境满足以下要求: - Nod

gitblog_00632的博客 1175

OpenClaw用户必看:每天0成本使用OpenClaw!NVIDIA NIM免费大模型接入教程

🚀 OpenClaw接入NVIDIA NIM免费API!glm5、minimax-m2.5等大量模型任选,0成本升级AI助手!💰

XiaoqiangClub的博客 5575

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Vue组件化开发(1)

相比于小项目全部写在一起,这样组件化开发就容易维护,一旦几百行的代码异常,只需要找某个独立的组件代码去调整即可,所以项目越大,若是不做拆分维护起来难度就越大。若需要让组件支持less,先去style标签,lang=less" 开启less功能,装依赖包:yarn add less-loader。页面可拆分成一个个组件,每个组件有着独立的结构、样式、行为① 好处:便于维护,利于复用,提升开发效率。封装好的组件可以拆分出来,别的页面直接拿去用就可以,页面的风格保持一致,维护时会同步更新。

SSHLY3的博客 2203

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Vue.js 组件设计详解

通过本文,我们详细探讨了 Vue 组件设计的方方面面,从基础概念到高级技术,包括组件的创建、通信、复用、优化以及最佳实践。我们还结合生活中的实际场景,使每个概念更加生动易懂。掌握这些知识和技巧,将有助于我们更好地构建高质量的 Vue 应用。在实际开发中,我们应不断实践和总结,逐步提升自己的开发能力。希望本文能对你有所帮助!如果你有任何问题或建议,欢迎随时交流。

繁依Fanyi的博客 1501

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

10+个很酷的Vue.js组件,模板和demo示例

众所周知,Vue.js 组件是Vue创建自定义元素的重要功能之一,同时,模板可帮助你避免从头开始创建网页设计。总之,这些工具对于希望其开发过程更快,更高效的任何Web开发人员都是必不可少的。 此外,在过去的几年中,Vue.js 变得非常流行,许多企业将其添加到他们的技术栈中。该框架的优点是它具有内置的数据绑定和MVC模型(模型、视图、控制器),与Angular.js和React.js相比,它使配置更加容易。另外,Vue.js的学习曲线很小,与 Angular.js 相比,Vue更易于学习,理解和使用。 知.

前端全栈开发者 3758

组件用.vue还是.js_vue.js的温度计组件

组件用.vue还是.js Vuejs温度计 (vuejs-thermometer) Thermometer component for vue.js . vue.js的温度计组件。 View demo 查看演示 Download Source 下载源 Do you have questions or want a new feature? Use the "Issues" section :...

cuk5340的博客 1378

html文件通过script标签引入vue.js,进行公共组件开发

由于各种原因,需要在原有的html页面中通过script标签引入的方式进行部分页面开发 但是由于开发过程中存在许多公共部分需要进行组件封装。所以遇到了一些问题。最后通过讲组件提取为单独js文件进行解决。 具体解决思路如下 首先将要封装的公用组件进行单独js文件提取 header.js var headerTemplate = `<div v-show="aa" style="positio...

weixin_44416446的博客 5809

vue 远程js 组件加载_一个Vue.js加载组件

vue 远程js 组件加载 提示加载 (vue-loading) A vuejs loading component. 一个vuejs加载组件。 View demo 查看演示 Download Source 下载源 安装 (Install) npm i @nulldreams/vue-loading npm i @nulldreams/vue-loading 如何使用 (How ...

cuk5239的博客 1228

Vue.js如何封装组件?

需求:现在需要在多个页面使用到上拉和下拉的滚动效果,手动封装一个BScroll的,如果没有安装better-scroll插件的安装上就可以 1、首先:在src文件目录下创建一个common文件夹,里面在建一个封装组件的文件夹,比如:BScroll文件夹,在该文件夹里面建一个index.vue 文件,里面是需要封装的具体内容: <template> <div class=...

qq_44472790的博客 2907

Vue JS中继器组件

Vue中继器 (Vue-Repeater) The VueJS repeater component allows you to create a set of sub components which can be repeated again and again whilst editing content! VueJS转发器组件允许您创建一组子组件,这些子组件可以在编辑内容时一次又一次地...

cuk5239的博客 468

vue实现js调用式组件

vue实现js调用式组件

vgub158的博客 4244

vue.js组件

组件是Vue.js最强大的功能之一,组件可以扩展HTML元素,也可以封装可重用的代码,组件系统让开发人员可以用独立可复用的小组件来构建大型应用。

pjn20的博客 1234

VueJS 之组件间的数据共享

组件实例的作用域是孤立的。也就是说,子组件的是无法直接获取到父组件中的数据的。VueJS 为组件开发提供了 props,通过 props ,父组件中的数据将能够传递给子组件,而子组件则需要提前对 props 进行声明以便接收父组件传递过来的数据。 在对通用组件进行封装时,合理地使用 props 能够提升组件的复用性。 我们可以在使用组件时,通过使用在子组件中使用 props 定义的属性来向子组件传递数据。 细节 驼峰式命名 排斥现象 HTML 是 不区分大小写的。如果在一个 HTML 元素中存在多个同名属

两个月亮 936
上一篇: Vue.js组件开发从0到1
下一篇: 学会学习
Sheldon_Law
博客等级 码龄11年 44粉丝 32原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值