Element UI 组件源码分析之Divider分割线 您所在的位置:网站首页 vue分割线怎么实现 Element UI 组件源码分析之Divider分割线

Element UI 组件源码分析之Divider分割线

2023-10-15 19:11| 来源: 网络整理| 查看: 265

0x00 简介

组件 Divider 多用于区隔内容。 本文将深入分析组件源码,剖析其实现原理,耐心读完,相信会对您有所帮助。packages/divider/src/main.vue 文件是组件源码实现。 🔗 组件文档 Divider 🔗 github源码 main.vue

更多组件分析详见 👉 📚 Element UI 源码剖析组件总览 。

本专栏的 gitbook 版本地址已经发布 anduril.gitbook.io/learning-el… ,内容同步更新中!

0x01 组件源码

组件divider/src/main.vue SFC(单文件组件 single-file components ),声明了基于模板的函数式组件。

// ... export default { name: 'ElDivider', props: { // ... } }; attributes 属性

组件定义了2个prop : direction 、contentPosition

direction

设置分割线方向,默认值horizontal,可选值为 horizontal / vertical,定义了 validator 进行验证。如果传入其他值生成无效样式 el-divider--${direction}。

direction: { type: String, default: 'horizontal', validator(val) { return ['horizontal', 'vertical'].indexOf(val) !== -1; } }, contentPosition

设置分割线文案的位置,默认值center,可选值为 left / right / center,定义了 validator 进行验证。如果传入其他值生成无效样式 is-${props.contentPosition}。

contentPosition: { type: String, default: 'center', validator(val) { return ['left', 'center', 'right'].indexOf(val) !== -1; } } template 模板内容

组件将创建一个  元素节点,用来绘制分割线。 该节点包含1个子节点 ,内置了 slot 用于自定义分割线文案。 子节点只有组件是分割线水平方向,且提供插槽内容用于自定义分割线文案时才会渲染。

再进一步分析组件之前,先了深入了解下函数式组件。

函数式组件 context

函数式组件需要的一切都是通过 context 参数传递,组件中使用了该参数的部分属性:

props:提供所有 prop 的对象 slots:一个函数,返回了包含所有插槽的对象 data:传递给组件的整个数据对象 listeners: 一个包含了所有父组件为当前组件注册的事件监听器的对象。这是 data.on 的一个别名。

其他属性 parent、children、scopedSlots、injections 详见官方文档 。

context 接口定义 @2.6源码 types/options.d.ts#L136

export interface RenderContext { props: Props; children: VNode[]; slots(): any; data: VNodeData; parent: Vue; listeners: { [key: string]: Function | Function[] }; scopedSlots: { [key: string]: ScopedSlot }; injections: any }

其中数据对象 data 类型为 VNodeData 官方文档 。

VNodeData 接口定义 @2.6源码 flow/vnode.js#L35 。

class Vs staticClass

从接口声明上看两者区别在于staticClass只能是字符串。 class支持所有其他格式,例如对象或数组。

declare interface VNodeData { // ... staticClass?: string; class?: any; // ... };

下面使用 Vue.compile 实时编译模板字符串,对比区别,代码详见 模板编译。

指令 v-bind 用于 class  时,Vue.js 做了专门的增强。表达式结果的类型除了字符串之外,还可以是对象或数组。

编译(render)内容 输出 class

function anonymous( ) { with(this){return _c('div',{class:['element','active']})} }

不使用指令 v-bind 定义 class字符串内容时。

编译(render)内容 输出 staticClass

function anonymous( ) { with(this){return _c('div',{staticClass:"active"})} } 组件功能

组件将创建一个  元素父节点,通过背景色绘制分割线。  el-divider 定义元素背景色, 通过el-divider--horizontal 或 el-divider--vertical 定义元素宽高实现水平、垂直分割效果

基于模板的函数式组件,可以通过 context访问到其独立的上下文内容。 v-bind="data.attrs" 使用 data.attrs 传递任何 HTML attribute;v-on="listeners" 使用 listeners  (即 data.on 的别名) 传递任何事件监听器。

:class="[data.staticClass, 'el-divider', 'el-divider--${props.direction}']" 根据传入prop 值设置分割线方向样式,然后将静态class 和动态生成的class 合并 merge 。

组件包含1个子节点 ,只有组件是分割线水平方向(props.direction !== 'vertical'),且提供插槽内容(slots().default)时才会渲染。根据contentPosition 生成文案位置样式, is-left、 is-right 或is-center。

0x02 组件样式 src/divider.scss

组件样式源码 packages\theme-chalk\src\divider.scss 使用混合指令 b、 m、e、 when 嵌套生成组件样式。

// 生成 .el-divider @include b(divider) { // ... // 生成 .el-divider--horizontal @include m(horizontal) { // ... } // 生成 .el-divider--vertical @include m(vertical) { // ... } // 生成 .el-divider__text @include e(text) { // ... // 生成 .el-divider__text.is-left @include when(left) { // ... } // 生成 .el-divider__text.is-center @include when(center) { // ... } // 生成 .el-divider__text.is-right @include when(right) { // ... } } } lib/divider.scss

前文可知使用 gulpfile.js编译 scss 文件转换为CSS,经过浏览器兼容、格式压缩,最后生成 packages\theme-chalk\lib\divider.scss,内容格式如下。

.el-divider { // ... } .el-divider--horizontal { // ... } .el-divider--vertical { // ... } .el-divider__text { // ... } .el-divider__text.is-left { // ... } .el-divider__text.is-center { // ... } .el-divider__text.is-right { // ... } 📚参考&关联阅读

"vm-attrs",vuejs.org "vm-listeners",vuejs.org "函数式组件",vuejs.org “class vs staticclass”,stackoverflow

关注专栏

如果本文对您有所帮助请关注➕、 点赞👍、 收藏⭐!您的认可就是对我的最大支持!

此文章已收录到专栏中 👇,可以直接关注。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有