這是我參與8月更文挑戰的第8天,活動詳情查看:8月更文挑戰javascript
本文將深刻分析組件 Link
源碼,剖析其實現原理,耐心讀完,相信會對您有所幫助。 組件文檔 Linkcss
packages/link/src/main.vue
文件是組件源碼實現。 github源碼 main.vuehtml
從模板內容看出,組件封裝一個 <a>
元素,包含3個子節點:vue
icon
,渲染此節點 ;slot
的 <span>
元素,class
名爲el-link--inner
(此樣式規則未定義,無效樣式),沒有設置後備內容(默認值);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 動態添加 class
。git
'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-if
、v-show
、v-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>
複製代碼
兩種使用方式渲染內容相同。
組件提供了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 | — | - |
組件提供了 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>
複製代碼
組件樣式源碼 packages\theme-chalk\src\link.scss
使用 scss
的混合指令 b
、 when
嵌套生成組件樣式。
// 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 {
// ...
}
}
}
}
}
複製代碼
前文可知使用 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 -------------------------- */
// ...
複製代碼
"vm-attrs",vuejs.org
「JavaScript 邏輯運算規則 」, cnblogs
此文章已收錄到專欄中 👇,能夠直接關注。