Element 2 組件源碼剖析之Link文字連接

這是我參與8月更文挑戰的第8天,活動詳情查看:8月更文挑戰javascript

0x00 簡介

本文將深刻分析組件 Link 源碼,剖析其實現原理,耐心讀完,相信會對您有所幫助。 組件文檔 Linkcss

packages/link/src/main.vue 文件是組件源碼實現。 github源碼 main.vuehtml

0x01 組件源碼

template 模板內容

從模板內容看出,組件封裝一個 <a> 元素,包含3個子節點:vue

  1. 圖標節點,定義 icon,渲染此節點 ;
  2. 提供了 slot<span> 元素,class 名爲el-link--inner此樣式規則未定義,無效樣式),沒有設置後備內容(默認值);
  3. 具名插槽 icon

3個子節點都設置 v-if判斷是否渲染節點元素。java

<template>
  <a :class="[ 'el-link', type ? `el-link--${type}` : '', disabled && 'is-disabled', underline && !disabled && 'is-underline' ]" :href="disabled ? null : href" v-bind="$attrs" @click="handleClick" > <!-- 圖標 --> <i :class="icon" v-if="icon"></i> <!-- 不帶 name 的 <slot> 出口會帶有隱含的名字「default」。 --> <span v-if="$slots.default" class="el-link--inner"> <slot></slot> </span> <!-- 具名插槽 icon --> <template v-if="$slots.icon"><slot v-if="$slots.icon" name="icon"></slot></template> </a> </template>
複製代碼

根據組件prop 動態添加 classgit

  • 'el-link' 組件默認樣式。
  • type ? 'el-link--${type}' : '' 設置組件文字不一樣類型顏色。若 type 值不是如下default/primary / success / warning / danger / info 其中一個,設置無效(生成無效的class)。
  • disabled && 'is-disabled' 禁用狀態下樣式。
  • underline && !disabled && 'is-underline' 文字連接下劃線樣式,禁用狀態下無效

邏輯與(&&) 看左邊的值是真仍是假。若是值是真,返回的是右邊的值,若是值是假;返回的是左邊的值(只有false 、0、NaN、null、undefined、空字符串爲假, 其他都是真)github

:href="disabled ? null : href" 禁用狀態下值爲 null,設置無效。web

@click="handleClick" 監聽click事件提供處理方法。gulp

接收額外屬性

$attrs 包含了父做用域中不做爲 prop 被識別 (且獲取) 的 attribute 綁定 (class 和 style 除外)。當一個組件沒有聲明任何 prop 時,這裏會包含全部父做用域的綁定 (class 和 style 除外),而且能夠經過 v-bind="$attrs" 傳入內部組件。api

具名插槽

組件提供了兩個插槽,一個在默認插槽,一個具名插槽 icon

<template>
    ...
    <!-- 具名插槽 icon --> 
    <template v-if="$slots.icon">
        <slot v-if="$slots.icon" name="icon"></slot>
    </template>
    ...
</template>
複製代碼

具名插槽 icon 使用了多層 <template> 標籤嵌套,<template> 不會渲染成元素,用 div的話會被渲染成元素。把 v-ifv-showv-for 等抽取出來放在<template>上面,把綁定的事件放在<template>裏面的元素上,能夠使結構更加清晰,還能夠改善元素嵌套過深。

具名插槽的使用示例,使用 <template slot="name">指定名稱。

<template>
  <div style="display: flex;flex-direction: column;">
    <!-- prop underline 沒有值,意味着 `true`。-->
    <el-link underline>
      查看 <i class="el-icon-view el-icon--right"></i>
      <template slot="icon">
        <h3>Link</h3>
      </template>
    </el-link>
    <el-link underline>
      <template slot="default">
        查看 <i class="el-icon-view el-icon--right"></i>
      </template>
      <template slot="icon">
        <h3>Link</h3>
      </template>
    </el-link>
  </div>
</template>
複製代碼

兩種使用方式渲染內容相同。

image.png

attributes 屬性

組件提供了5個 prop

props: {
    type: {
      type: String,
      default: 'default'
    },
    underline: {
      type: Boolean,
      default: true
    },
    disabled: Boolean,
    href: String,
    icon: String
},

複製代碼

prop詳細描述以下:

參數 說明 類型 可選值 默認值
type 類型 string primary / success / warning / danger / info default
underline 是否下劃線 boolean true
disabled 是否禁用狀態 boolean false
href 原生 href 屬性 string -
icon 圖標類名 string -

events 事件

組件提供了 click 事件 。

handleClick(event) {
  // 非禁用狀態
  if (!this.disabled) {
    // href未定義值
    if (!this.href) {
      // 觸發當前實例上的事件
      this.$emit('click', event);
    }
  }
}
複製代碼

click事件只有非禁用狀態且href未定義值的狀態下生效,用於須要代碼處理頁面跳轉的場景。

<template>
  <div>
    <el-link @click="goToPage">默認連接</el-link>
  </div>
</template>
<script> export default { methods: { goToPage(e) { // url redirect }, }, }; </script> 
複製代碼

0x02 組件樣式

src/link.scss

組件樣式源碼 packages\theme-chalk\src\link.scss 使用 scss 的混合指令 bwhen 嵌套生成組件樣式。

// Maps 可視爲鍵值對的集合
$typeMap: (
  primary: $--link-primary-font-color,
  danger: $--link-danger-font-color,
  success: $--link-success-font-color,
  warning: $--link-warning-font-color,
  info: $--link-info-font-color,
);

// 生成 .el-link
@include b(link) {
  // ...

  // 生成.el-link.is-underline:hover:after
  @include when(underline) {
    &:hover:after {
      // ...
    }
  }
  // 生成 .el-link.is-disabled
  @include when(disabled) {
    // ...
  }

  // 生成 .el-link [class*=el-icon-] + span
  & [class*="el-icon-"] {
    & + span {
      // ...
    }
  }
  // 生成 .el-link.el-link--default
  &.el-link--default {
    // ...

    // .el-link.el-link--default:hover
    &:hover {
      // ...
    }

    // 生成  .el-link.el-link--default:after
    &:after {
      // ...
    }
    // 生成 .el-link.el-link--default.is-disabled
    @include when(disabled) {
      // ...
    }
  }

  @each $type, $primaryColor in $typeMap {
    // 生成 .el-link.el-link--[type]
    &.el-link--#{$type} {
      // ...
      
      // 生成 .el-link.el-link--[type]:hover
      &:hover {
        // ...
      }
      // 生成 .el-link.el-link--[type]:after
      &:after {
        // ...
      }
      // 生成 .el-link.el-link--[type].is-disabled
      @include when(disabled) {
        // ...
      }
      // 生成 .el-link.el-link--[type].is-disabled:hover:after
      @include when(underline) {
        &:hover:after {
          // ...
        }
      }
    }
  }
}

複製代碼

lib/link.scss

前文可知使用 gulpfile.js編譯 scss 文件轉換爲CSS,通過瀏覽器兼容、格式壓縮,最後生成 packages\theme-chalk\lib\link.scss,內容格式以下。

.el-link {
  //...
}
.el-link.is-underline:hover:after {
   //...
}
.el-link.is-disabled {
   //...
}
.el-link [class*="el-icon-"] + span {
   //...
} 

.el-link.el-link--default:after,
.el-link.el-link--primary.is-underline:hover:after,
.el-link.el-link--primary:after {
   //...
} 
/* ------------default------------- */
.el-link.el-link--default {
   //...
}
.el-link.el-link--default:hover {
   //...
}
.el-link.el-link--default.is-disabled {
   //...
}
/* ------------primary------------- */
.el-link.el-link--primary {
  //...
}
.el-link.el-link--primary:hover {
  //...
}
.el-link.el-link--primary.is-disabled {
  //...
}  

/* type danger -------------------------- */
.el-link.el-link--danger.is-underline:hover:after,
.el-link.el-link--danger:after {
  border-color: #f56c6c;
}
.el-link.el-link--danger {
  color: #f56c6c;
}
.el-link.el-link--danger:hover {
  color: #f78989;
}
.el-link.el-link--danger.is-disabled {
  color: #fab6b6;
}
/* type success -------------------------- */
// ...

/* type warning -------------------------- */
// ... 

/* type info -------------------------- */
// ... 
 

複製代碼

0x03 📚參考

"vm-attrs",vuejs.org
「JavaScript 邏輯運算規則 」, cnblogs

0x04 關注專欄

此文章已收錄到專欄中 👇,能夠直接關注。

相關文章
相關標籤/搜索