<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
在專案開發中,我們經常使用可能都是UI元件庫裡的圖示,當然由於業務需要,可能當前圖示庫沒有我們需要的圖示這時候就需要引入其它圖示庫的圖示,比如iconfont、FontAweSome、本地圖示庫。在瞭解引入這些圖示庫之前,我們先學習一下各種圖示庫的引入使用:
Element-Plus:由於elemen官方已經把圖示封裝成了元件,所以當我們引入圖示的時候,需要全域性宣告元件。
import * as Icons from '@element-plus/icons'; const app = createApp(App); // 全域性註冊圖示,犧牲一點效能 for (let i in Icons) { // 官方圖示名稱首字母都是大寫,所以轉為小寫,並命名元件未el-icon-圖示名 app.component(`el-icon-${toLine(i)}`, (Icons as any)[i]); } // 元件中使用圖示 <el-icon-user />
Iconfont:阿里巴巴圖示庫,通過建立一個專案目錄,然後把我們需要的圖示新增進去,然後在專案中引入圖示目錄的cdn(三種方式之一:css程式碼、css連結、js連結)就可以使用了,如果沒有特殊處理一般是在專案的index.html中引入相關連結,css程式碼可以在根目錄的樣式檔案中引入。然後就可以在專案中使用:
<i class="iconfont icon-user"></i>
FontAwesome:一個比較好用的字型圖示庫,可以直接通過cdn引入,也可以通過安裝package包引入,然後就可以使用了:
<i class="fa fa-user"></i>
參照本地圖示:一般使用svg格式圖示,因為svg效能好,相對於其它格式,它體積更小,可以任意放大圖形顯示,不以犧牲圖示質量為代價,專案中是不能直接載入svg格式,需要額外外掛實現(後面會詳細介紹)。
<svg class="svg-icon icon" style="width: 1em;height: 1em;color: black;"> <use href="#local-vue" rel="external nofollow" rel="external nofollow" /> </svg>
為了方便維護以及擴充套件,我們可以把四種圖示封裝為統一元件使用,在封裝前我們需要明確三點:
在學習各類的圖示庫之前我們先了解一下如何封裝一下圖示共用元件,它向外暴露的名稱是Icon:
實現元件健壯性、易維護:支援圖示名稱(name)、圖示顏色(color)、圖示大小(size)三要素的自定義。四種圖示格式引入為element-plus(el-icon-iconName
)、iconfont(iconfont iconName
)、fontawesome(fa fa-iconName
)、本地圖示(local-iconName
),iconName是圖示名稱。
props: { name: { type: String, required: true, }, size: { type: String, default: '30px', }, color: { type: String, default: '#00000', }, }, // 處理樣式,去掉多餘px命名 const iconStyle = computed((): CSSProperties => { const { size, color } = props; let s = `${size.replace('px', '')}px`; return { fontSize: s, color: color, }; });
相容上面四種圖示實現:通過Vue3的setup的返回值中使用渲染函數實現,不需要在template中定義標籤使用,分三種情況。
createVNode函數:建立虛擬節點,從左到右有三個引數:html標籤名稱或元件(String)、標籤屬性(Object)、巢狀標籤定義(Array)。
對於element-plus圖示的渲染:官方是通過el-icon標籤內直接使用圖示元件,所以建立虛擬節點標籤就是el-icon,由於圖示元件是巢狀的,所以需要用到第三引數。
setup(props) { // 當前引入的是element-plus圖示 if (props.name.indexOf('el-icon-') === 0) { return () => createVNode( 'el-icon', { class: 'icon el-icon', style: iconStyle.value }, [createVNode(resolveComponent(props.name))] ); } }
對於iconfont、fontawesome圖示的渲染:由於使用這兩種的圖示的標籤都是i,它們唯一不同就是圖示名稱的命名所以可以共用同一個渲染函數。
setup(props){ // 當前引入的是iconfont或fontawesome圖示 if (props.name.indexOf('local-') === 0 || isExternal(props.name)) { return () => createVNode('i', { class: [props.name, 'icon'], style: iconStyle.value, }); } }
對於本地svg圖示的渲染:直接引入本地封裝的svg元件,把這個元件當作渲染標籤,這裡圖示命名以local-iconName格式引入的。
setup(props){ // 當前引入的是本地svg圖示 if (props.name.indexOf('local-') === 0 || isExternal(props.name)) { return () => createVNode(svg, { name: props.name, size: props.size, color: props.color, }); } }
最終就可以通過這樣使用圖示:
<Icon name="" color="" size=""/>
其實上面就已經實現了四種圖示的型別統一封裝,一致使用。接下來為了更方便獲取圖示,我們把所有圖示封裝起來就可以直接cv使用了。
點選實現cv方式:通過點選圖示傳入我們想要複製的內容,一般都是整個元件的字串。
export const useCopy = (text: string) => { let input = document.createElement('input'); // 建立輸入框 input.value = text; // 給輸入框value賦值 document.body.appendChild(input); // 追加到body裡面去 input.select(); // 選擇輸入框的操作 document.execCommand('Copy'); // 執行復制操作 document.body.removeChild(input); // 刪除加入的輸入框 ElMessage.success('複製成功!'); };
import * as elIcons from '@element-plus/icons-vue'; // 獲取所有Element-Plus圖示元件名稱,如搜尋圖示Search export function getElementPlusIconfontNames() { return new Promise<string[]>((resolve, reject) => { nextTick(() => { const iconfonts = []; const icons = elIcons as any; // 遍歷新增icons元件名稱 for (const i in icons) { iconfonts.push(icons[i].name); } if (iconfonts.length > 0) { resolve(iconfonts); } else { reject('No ElementPlus Icons'); } }); }); }
先載入圖示樣式表:
const cssUrls: Array<string> = [ '//at.alicdn.com/t/c/font_3846007_vf3shrhbpya.css', // 阿里圖示庫cs,每新增一次圖示都需要更換 '//cdn.bootcdn.net/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css', // font-awesome的css ]; export default function init() { // 遍歷載入圖示連結樣式 if (cssUrls.length > 0) { cssUrls.map((v) => { loadCss(v); }); } } // 通過建立link標籤引入樣式連結 export function loadCss(url: string): void { const link = document.createElement('link'); // 建立link標籤 link.rel = 'stylesheet'; link.href = url; // 是否採用跨域的方式載入。它可以取兩個值 // anonymous(跨域請求時,不傳送使用者憑證,主要是 Cookie) // use-credentials(跨域時傳送使用者憑證)。 link.crossOrigin = 'anonmous'; document.getElementsByTagName('head')[0].appendChild(link); }
獲取當前頁面中從指定域名載入到的樣式表內容:在呼叫這個函數之前必須要先引入樣式。
// 獲取樣式表內容 function getStylesFromDomain(domain: string) { const sheets = []; const styles: StyleSheetList = document.styleSheets; for (const key in styles) { if (styles[key].href && (styles[key].href as string).indexOf(domain) > -1) { sheets.push(styles[key]); } } return sheets; }
呼叫這個函數之後就可以獲取到當前圖示庫相關樣式表內容,我們的目的就是拿到圖示名稱,可以提取rules陣列內的樣式名稱就可以拿到所有圖示名稱了。
// 獲取所有iconfont圖示庫圖示名稱 export function getIconfontNames() { init(); return new Promise<string[]>((resolve, reject) => { nextTick(() => { const iconfonts = []; const sheets = getStylesFromDomain('at.alicdn.com'); for (const key in sheets) { const rules: any = sheets[key].cssRules; for (const k in rules) { // .表示匹配除換行符 n 之外的任何單字元 // *表示單個字元匹配任意次 if ( rules[k].selectorText && /^.icon-(.*)::before$/g.test(rules[k].selectorText) ) { // 去掉樣式的.符號以及::before iconfonts.push( `${rules[k].selectorText .substring(1, rules[k].selectorText.length) .replace(/::before/gi, '')}` ); } } } if (iconfonts.length > 0) { resolve(iconfonts); } else { reject('No Iconfont style sheet'); } }); }); }
先載入圖示樣式表:也就是直接呼叫init函數,載入相應的樣式連結。
獲取當前頁面中從指定域名載入到的樣式表內容:如下圖所示。
export function getAwesomeIconfontName() { init(); return new Promise<string[]>((resolve, reject) => { nextTick(() => { const iconfonts = []; // 獲取所有圖示名稱 const sheets = getStylesFromDomain( 'cdn.bootcdn.net/ajax/libs/font-awesome/' ); for (const key in sheets) { const rules: any = sheets[key].cssRules; // 處理方法與iconfont一致,只不過名稱不一樣 for (const k in rules) { if ( rules[k].selectorText && /^.fa-(.*)::before$/g.test(rules[k].selectorText) ) { if (rules[k].selectorText.indexOf(', ') > -1) { // selectorText裡有多個圖示,只提取第一個 const iconNames = rules[k].selectorText.split(', '); iconfonts.push( `${iconNames[0] .substring(1, iconNames[0].length) .replace(/::before/gi, '')}` ); } else { iconfonts.push( `${rules[k].selectorText .substring(1, rules[k].selectorText.length) .replace(/::before/gi, '')}` ); } } } } if (iconfonts.length > 0) { resolve(iconfonts); } else { reject('No AwesomeIcon style sheet'); } }); }); }
在引入本地svg圖示之前,我們先了解一下svg標籤的相關知識:
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45