很長(zhǎng)的一段時(shí)間中,Vue 官方都以簡(jiǎn)單上手作為其推廣的重點(diǎn)。這確實(shí)給 Vue 帶來(lái)了非常大的用戶量,尤其是最追求需求開(kāi)發(fā)效率, 往往不那么在意工程代碼質(zhì)量的國(guó)內(nèi)中小企業(yè)中,Vue 占據(jù)的份額極速增長(zhǎng)。但是作為開(kāi)發(fā)者自身,我們必須要認(rèn)清一個(gè)重點(diǎn),簡(jiǎn)單易用從來(lái)不應(yīng)該在技術(shù)選型中占據(jù)很大的份額,可維護(hù)性才是。
以防萬(wàn)一有的同學(xué)實(shí)在不看官方文檔,我先提一嘴,SFC 就是寫(xiě) Vue 組件的時(shí)候?qū)懙?vue文件,這一個(gè)文件就是一個(gè) SFC,全稱 Single File Component,也即單文件組件。
在開(kāi)始說(shuō)我個(gè)人的觀點(diǎn)之前,我們先來(lái)看幾個(gè)事實(shí):
一是:Vue3 的定義原生支持 JSX,并且 Vue3 源碼中有jsx.d.ts來(lái)便于使用 JSX。 不知道同學(xué)們看到這里會(huì)想到什么, 我的第一反應(yīng)是:社區(qū)對(duì)于 JSX 的需求聲音是不小的,所以會(huì)反向推動(dòng) Vue3 官方對(duì)于 JSX 的支持。
二是:AntDesign 的 vue3 版本,基本全部都是用 JSX 開(kāi)發(fā)的,而且 Vue3 現(xiàn)在官方的 babel-jsx 插件就是阿里的人一開(kāi)始維護(hù)的, 雖然我向來(lái)不喜歡阿里系的 KPI 推動(dòng)技術(shù)方式,而且現(xiàn)在的 JSX 語(yǔ)法支持也不是很符合我的期望,但至少在使用 JSX 開(kāi)發(fā)是更優(yōu)秀的選擇這點(diǎn)上,我還是很認(rèn)可 AntDesign 團(tuán)隊(duì)的。
OK,說(shuō)這些呢,主要是先擺出一些事實(shí)作為依據(jù),讓有些同學(xué)可以不需要拿什么:
這些觀點(diǎn)來(lái)批斗我,首先我都會(huì)從客觀的角度來(lái)分析為什么,至少是我是能講出優(yōu)劣勢(shì)的理由的。
OK,前言差不多到這里,接下來(lái)咱給您分析分析,為什么你應(yīng)該選擇 JSX 來(lái)開(kāi)發(fā) Vue。
其實(shí)第一點(diǎn)就已經(jīng)是殺手了,對(duì)于想要使用 TypeScript 來(lái)開(kāi)發(fā) Vue3 應(yīng)用的同學(xué)來(lái)說(shuō),這簡(jiǎn)直就是 SFC 無(wú)法克服的世界難題。
一句話概括:TypeScript 原生支持 JSX 語(yǔ)法,而基本無(wú)望 TS 官方能支持 SFC 的 template 語(yǔ)法。
TS 毫無(wú)疑問(wèn)在前端社區(qū)的重要性越來(lái)越大,但凡未來(lái)對(duì)于代碼質(zhì)量有一定要求的前端團(tuán)隊(duì),都應(yīng)該會(huì)選擇使用 TS 來(lái)進(jìn)行開(kāi)發(fā)。 而且現(xiàn)在基本上在 NPM 上都能看到包你都能找到對(duì)應(yīng)的 TS 定義,現(xiàn)在使用 TS 開(kāi)發(fā)成本已經(jīng)只剩下你是不是會(huì) TS 語(yǔ)法了,在這種情況下是否支持 TS 則是開(kāi)發(fā)模式在未來(lái)走不走的遠(yuǎn)的重要原因。
目前 SFC 只能通過(guò)shim讓 TS 可以引入.vue文件,但是對(duì)于所有 SFC 的組件的定義都是一樣的:
declare module '*.vue' {
import { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, {}, any>
export default component
}
也就是說(shuō)你引入的 SFC 組件,TS 是不知道這個(gè)組件的 Props 應(yīng)該接收什么的。所以你無(wú)法享受到這些 TS 的優(yōu)勢(shì):
當(dāng)然你會(huì)說(shuō)既然 Vue 官方能開(kāi)發(fā)處 SFC 的語(yǔ)法,自然會(huì)支持這些特性。我表示這當(dāng)然有可能,但是這個(gè)難度是非常大的,需要很多方面的支持,甚至可能需要 TS 官方團(tuán)隊(duì)愿意協(xié)助, 但是我想不到 TS 官方有什么理由來(lái)支持 SFC,因?yàn)檫@只是 Vue 自己創(chuàng)建的方言,在其他場(chǎng)景下是沒(méi)有使用的,TS 是面向全社區(qū)的,我覺(jué)得他們不會(huì)考慮主動(dòng)來(lái)支持 SFC。
那么有同學(xué)要問(wèn)了,JSX 不也是非原生的 JS 語(yǔ)法么,他怎么就能讓 TS 官方支持了呢,是不是 FB 和微硬之間有什么 PY 交易?
這就涉及第二點(diǎn)了,JSX 和靜態(tài)模板的靈活性區(qū)別。
很多人弄錯(cuò)了一個(gè)問(wèn)題,就是覺(jué)得 SFC 的模板語(yǔ)法和 JSX 是一樣的,都是一種別人發(fā)明的語(yǔ)法,并不是 JS 原生的。這是事實(shí),但又有一些區(qū)別,這個(gè)區(qū)別主要是體現(xiàn)在對(duì)于 JSX 的認(rèn)知上。
一句話概括:JSX 并沒(méi)有擴(kuò)展 JS 的語(yǔ)法,他只是縮略了 JS 的寫(xiě)法!其本質(zhì)就是 JS 的語(yǔ)法糖
就像 es6 給增加的語(yǔ)法糖,比如
const a = 1
const b = 2
const obj = { a, b }
// 其實(shí)就等價(jià)于
const obj = { a: a, b: b }
這種寫(xiě)法并沒(méi)有擴(kuò)展 JS 的能力,只是簡(jiǎn)便了寫(xiě)法,JSX 也是一樣的。
JSX 其實(shí)就是方法調(diào)用,他和 JS 是有一對(duì)一對(duì)應(yīng)關(guān)系的,我們來(lái)看一個(gè)例子:
const element = <div id="root">Hello World</div>
這里的 JSX 語(yǔ)法編譯之后其實(shí)就是:
const element = createElement('div', { id: 'root' }, 'Hello World')
而 JSX 就是這些了,沒(méi)有什么更多的內(nèi)容,所以說(shuō) JSX 只是方便我們寫(xiě)嵌套的函數(shù)調(diào)用的語(yǔ)法糖,而其本身沒(méi)有擴(kuò)展任何其他的內(nèi)容。
但是 SFC 就不一樣了。
SFC 定義的不僅是語(yǔ)法,更是文件。
SFC 的具體定義是單文件組件,它本身就是把一個(gè)文件看作一個(gè)單位,所以他的約束性是要大很多的,你必須具有固定的文件結(jié)構(gòu)才能使用 SFC,這做了很多的限制:
我們一點(diǎn)點(diǎn)來(lái)講
這個(gè)說(shuō)實(shí)話非常非常不方便,很多時(shí)候我們寫(xiě)一個(gè)頁(yè)面的時(shí)候其實(shí)經(jīng)常會(huì)需要把一些小的節(jié)點(diǎn)片段拆分到小組件里面進(jìn)行復(fù)用(如果你現(xiàn)在沒(méi)有這個(gè)習(xí)慣可能就是因?yàn)?SFC 的限制讓你習(xí)慣了全部寫(xiě)在一個(gè)文件內(nèi))。
React 生態(tài)中豐富的 css-in-js 方案就是很好的例子,我們可以通過(guò):
const StyledButton = styled('button', {
color: 'red',
})
如果我們這個(gè)頁(yè)面需要使用特定樣式的按鈕,通過(guò)這種方式在頁(yè)面文件里面封裝一下是非常常見(jiàn)的。因?yàn)闆](méi)必要把這個(gè)組件拆分出去,他也不是一個(gè)可復(fù)用的組件,拆分出去了還要多一次import。
Vue 生態(tài)基本沒(méi)有 css-in-js 的成熟方案其實(shí)跟這個(gè)限制也很有關(guān)系。
再來(lái)一個(gè)例子,比如我們封裝了一個(gè) Input 組件,我們希望同時(shí)導(dǎo)出 Password 組件和 Textarea 組件來(lái)方便用戶根據(jù)實(shí)際需求使用,而這兩個(gè)組件本身內(nèi)部就是用的 Input 組件,只是定制了一些 props:
const Input = { ... }
export default Input
export const Textarea = (props) => <Input multiline={true} {...props} />
export const Password = (props) => <Input type="password" {...props} />
在 JSX 中可以非常簡(jiǎn)單地實(shí)現(xiàn),但是如果通過(guò) SFC,你可能就要強(qiáng)行拆成三個(gè)文件,另外為了方便,你可能還要增加一個(gè)index.js來(lái)導(dǎo)出這三個(gè)組件,你能想象這多了多少工作量么。
我不知道有多少同學(xué)看過(guò) Vue 的 template 編譯出來(lái)之后的代碼,以我的經(jīng)驗(yàn)來(lái)說(shuō)看過(guò)的可能不會(huì)超過(guò) 50%(樂(lè)觀估計(jì)),建議同學(xué)們?nèi)绻€不了解的,可以去嘗試看一下。
為什么要看這個(gè)呢?因?yàn)槟憧戳酥竽銜?huì)發(fā)現(xiàn),你在 template 里面寫(xiě)的類似 HTMl 的內(nèi)容,其實(shí)跟 HTML 根本沒(méi)啥關(guān)系,他們也會(huì)被編譯成類似 JSX 編譯出來(lái)的結(jié)果。
{
render(h) {
return h('div', {on: {}, props: {}}, h('span'))
}
}
類似這樣的結(jié)果,而這里面h函數(shù)調(diào)用的結(jié)果就是一個(gè) VNode,是 Vue 中的節(jié)點(diǎn)的基礎(chǔ)單元。那么既然這些單元就是一個(gè)對(duì)象,其實(shí)理所當(dāng)然的,他們是可以作為參數(shù)傳遞的。 也就是說(shuō),理論上他們是可以通過(guò)props把節(jié)點(diǎn)當(dāng)作參數(shù)傳遞給其他組件的。
這個(gè)做法在 React 中非常常見(jiàn),叫做renderProps,并且其非常靈活:
const Comp = () => <Layout header={<MyHeader />} footer={<MyFooter />} />
但是因?yàn)?SFC 模板的限制,我們很難在 SFC 里面的 props 上寫(xiě)節(jié)點(diǎn):
<template>
<Layout :header="<MyHeader/>"></Layout>
</template>
這樣寫(xiě)是不行的,因?yàn)?SFC 定義了:header綁定接受的只能是 js 表達(dá)式,而<MyHeader/>顯然不是。
因?yàn)橥ㄟ^(guò) props 傳遞不行,所以 Vue 才發(fā)明了 slot 插槽的概念
雖然我們一直再說(shuō) Vue 簡(jiǎn)單,但是事實(shí)上ScopedSlots一度成為新手理解 Vue 的噩夢(mèng),很多同學(xué)都被這個(gè)繞來(lái)繞去的作用域整的死去活來(lái)。
我們看一個(gè)ScopedSlots的例子:
<template>
<Comp>
<template v-slot:scope="ctx">
<div>{{ctx.name}}</div>
</template>
</Comp>
</template>
這里ctx是Comp里面的屬性,通過(guò)這種方式傳遞出來(lái),讓我們?cè)诋?dāng)前組件可以調(diào)用父組件里面的屬性。這簡(jiǎn)直就是理解的噩夢(mèng),但是如果用 JSX 實(shí)現(xiàn)類似功能就非常簡(jiǎn)單:
<Comp scope={name => <div>{name}</div>} />
我們只是給一個(gè)叫做scope的 props 傳遞來(lái)一個(gè)函數(shù),這個(gè)函數(shù)接受一個(gè)name屬性,在Comp里面會(huì)調(diào)用這個(gè)函數(shù)并傳入name。 簡(jiǎn)單來(lái)說(shuō)我們傳入的就是一個(gè)構(gòu)建節(jié)點(diǎn)片段的函數(shù),就是這么簡(jiǎn)單。
這就是因?yàn)?SFC 的模板的限制,導(dǎo)致靈活性不足,Vue 需要去創(chuàng)造概念,創(chuàng)造關(guān)鍵字來(lái)抹平這些能力的不足,而創(chuàng)造的概念自然就引入了學(xué)習(xí)成本。
所以其實(shí)我一直不認(rèn)可 Vue 比 React 好學(xué)的說(shuō)法的,如果你真的認(rèn)真研究所有用法,并且總是嘗試用最合理的方式實(shí)現(xiàn)功能,那么 Vue 絕對(duì)不會(huì)比 React 簡(jiǎn)單。
這個(gè)體現(xiàn)在兩個(gè)方面,一個(gè)是我們定義在全局的一些固定數(shù)據(jù)如果要在組件內(nèi)使用的話,就要通過(guò)this掛載到組件上。
比如我們緩存了一份城市數(shù)據(jù),這種數(shù)據(jù)基本上是不會(huì)改的,所以也沒(méi)必要掛載到組件上讓其能夠響應(yīng)式。但是在 SFC 里面這是做不到的, 因?yàn)槟0宓膱?zhí)行上下文是在編譯時(shí)綁定。你在模板里面訪問(wèn)的變量,都會(huì)在編譯時(shí)自動(dòng)綁定到this上,因?yàn)槟0逍枰幾g,其本身也是字符串不具有作用域的概念。
而這在 JSX 中則不復(fù)存在:
const citys = []
const Comp = () => {
return citys.map(c => <div>{c}</div>)
}
另外一個(gè)方面則是在組件使用上,在 SFC 中,組件必須事先注冊(cè),因?yàn)槲覀冊(cè)谀0謇锩鎸?xiě)的只能是字符串而不能是具體某個(gè)組件變量。 那么模板中的組件和真實(shí)的組件對(duì)象只能通過(guò)字符串匹配來(lái)實(shí)現(xiàn)綁定。這帶來(lái)了以下問(wèn)題:
在 JSX 中則沒(méi)有這些問(wèn)題,因?yàn)?JSX 里面直接使用組件引用作為參數(shù):
const Comp = {...}
const App = () => <Comp />
其實(shí)上面能看出來(lái),除了 SFC 本身的問(wèn)題之外,Vue 使用字符串模板也會(huì)帶來(lái)很多的靈活性問(wèn)題。 最直接的證據(jù),就是 Vue 使用了directive來(lái)擴(kuò)展功能(當(dāng)然這不是 Vue 發(fā)明的,老早的模板引擎就有類似問(wèn)題)。
為什么說(shuō)directive是不得已的選擇呢?因?yàn)殪o態(tài)模板缺失邏輯處理的能力。我們拿列表循環(huán)舉例,在 JS 中我們可以非常方便地通過(guò)map函數(shù)來(lái)創(chuàng)建列表:
const list = arr.map(name => <span key={name}>{name}</span>)
而因?yàn)?JSX 本身就是函數(shù)調(diào)用,所以上面的代碼和 JSX 結(jié)合起來(lái)也非常自然:
const App = () => (
<div>
<Header />
{arr.map(name => (
<span key={name}>{name}</span>
))}
</div>
)
上面的例子對(duì)應(yīng)到 JS 如下:
const App = () =>
createElement('div', {}, [
<Header />,
arr.map(name => createElement('span', { key: name }, name)),
])
這仍然是因?yàn)?JSX 只是 JS 的語(yǔ)法糖的原因,所有能在 JS 中實(shí)現(xiàn)的在 JSX 里面都能實(shí)現(xiàn)。
而 SFC 的模板是基于字符串編譯的,其本身就是一段字符串,我們不能直接在模板里面寫(xiě)map來(lái)循環(huán)節(jié)點(diǎn),(當(dāng)然我們可以在可以接收表達(dá)式的地方寫(xiě),比如v-on里面)。
那么我們不能循環(huán)節(jié)點(diǎn),有需要這樣的功能來(lái)渲染列表,怎么辦呢?就是發(fā)明一個(gè)標(biāo)志來(lái)告訴編譯器這里需要循環(huán),在 Vue 中的體現(xiàn)就是v-for指令。
同學(xué)們可能要問(wèn)了,既然 Vue 能實(shí)現(xiàn)v-for,為什么不直接實(shí)現(xiàn)表達(dá)式循環(huán)列表呢?他當(dāng)然也可以實(shí)現(xiàn),但是他肯定不會(huì)這么選,因?yàn)槌杀咎吡恕?他要這么做就相當(dāng)于他要實(shí)現(xiàn)一個(gè) JS 引擎,而其實(shí)里面很多內(nèi)容又是不必須的,一個(gè)v-for其實(shí)就能夠適用大部分情況了。
但有了v-for就需要v-if,那么后面還會(huì)需要其他各種能力,這就是一種方言的產(chǎn)生和發(fā)展的過(guò)程。
當(dāng)然指令也不僅僅是 JS 表達(dá)式的代替品,其本身也是增加了一些其他能力的,比如它能夠讓我們更方便地訪問(wèn) DOM 節(jié)點(diǎn), 但是嘛,我們用框架的理由不就是為了能夠盡可能的屏蔽 DOM 操作嘛~
以上就是我對(duì)應(yīng)該選擇使用 JSX 還是 SFC 進(jìn)行開(kāi)發(fā)的分析,其實(shí)歸根到底 SFC 的問(wèn)題在于其沒(méi)有擁抱 JS, 他的語(yǔ)法是自己發(fā)明的,他需要有一個(gè) JS 實(shí)現(xiàn)的 compiler 來(lái)讓其最終能在 JS 環(huán)境中運(yùn)行,這本質(zhì)上就是一種發(fā)明, 我們不能否認(rèn)發(fā)明確實(shí)有優(yōu)點(diǎn),但我們也不能只看有點(diǎn)不看問(wèn)題,沒(méi)能擁抱 JS 自然就很難完全復(fù)用 JS 社區(qū)的優(yōu)勢(shì) 而 JS 社區(qū)一直在蓬勃發(fā)展,好用的工具一直在涌現(xiàn),而 SFC 想要使用 JS 社區(qū)的這些工具還要自己再實(shí)現(xiàn)一份,我們可以細(xì)數(shù)以下 SFC 做了哪些兼容
基本上常用的工具我們都需要等待 Vue 社區(qū)或者官方開(kāi)發(fā)了插件之后才能運(yùn)行。而 JSX 因?yàn)橛?babel 和 typescript 的官方支持, 基本上所有新的 JS 生態(tài)工具原生都是支持的。
在這 Vue3 開(kāi)始預(yù)備發(fā)力的階段,我們還是希望 Vue 社區(qū)能夠使用更優(yōu)秀更規(guī)范的方式來(lái)進(jìn)行開(kāi)發(fā), 其實(shí)如果我們直接使用 JSX 開(kāi)發(fā) Vue3,我們會(huì)發(fā)現(xiàn)很多時(shí)候我們都不需要用到emit、attrs這些概念, 甚至如果 Vue3 的 JSX 插件支持,我們甚至能夠拋棄slots。
但是因?yàn)?Vue3 一定要考慮兼容 Vue2,導(dǎo)致本身潛力很好的 Vue3 總是顯得縮手縮腳,這不得不說(shuō)是一種遺憾。
<標(biāo)簽名 style="屬性1:屬性值1; 屬性2:屬性值2; 屬性3:屬性值3;"> 內(nèi)容 </標(biāo)簽名>
實(shí)際上任何HTML標(biāo)簽都擁有style屬性,用來(lái)設(shè)置行內(nèi)式。
<div style="color: red; font-size: 12px;">青春不常在,抓緊談戀愛(ài)</div>
<head>
<style type="text/CSS">
選擇器(選擇的標(biāo)簽) {
屬性1: 屬性值1;
屬性2: 屬性值2;
屬性3: 屬性值3;
}
</style>
</head>
<style>
div {
color: red;
font-size: 12px;
}
</style>
<style>
/*選擇器{屬性:值;}*/
p {
color:#06C;
font-size:14px;
} /*文字的顏色是 藍(lán)色*/
h4 {
color:#900;
}
h1 {
color:#090;
font-size:16px;
}
body {
background:url(bg2.jpg);
}
</style>
<head>
<link rel="stylesheet" type="text/css" href="css文件路徑">
</head>
屬性 | 作用 |
rel | 定義當(dāng)前文檔與被鏈接文檔之間的關(guān)系,在這里需要指定為“stylesheet”,表示被鏈接的文檔是一個(gè)樣式表文件。 |
type | 定義所鏈接文檔的類型,在這里需要指定為“text/CSS”,表示鏈接的外部文件為CSS樣式表。我們都可以省略 |
href | 定義所鏈接外部樣式表文件的URL,可以是相對(duì)路徑,也可以是絕對(duì)路徑。 |
樣式表 | 優(yōu)點(diǎn) | 缺點(diǎn) | 使用情況 | 控制范圍 |
行內(nèi)樣式表 | 書(shū)寫(xiě)方便,權(quán)重高 | 沒(méi)有實(shí)現(xiàn)樣式和結(jié)構(gòu)相分離 | 較少 | 控制一個(gè)標(biāo)簽(少) |
內(nèi)部樣式表 | 部分結(jié)構(gòu)和樣式相分離 | 沒(méi)有徹底分離 | 較多 | 控制一個(gè)頁(yè)面(中) |
外部樣式表 | 完全實(shí)現(xiàn)結(jié)構(gòu)和樣式相分離 | 需要引入 | 最多,強(qiáng)烈推薦 | 控制整個(gè)站點(diǎn)(多) |
標(biāo)簽名{屬性1:屬性值1; 屬性2:屬性值2; 屬性3:屬性值3; }
類選擇器使用“.”(英文點(diǎn)號(hào))進(jìn)行標(biāo)識(shí),后面緊跟類名.
命名規(guī)范: 見(jiàn)附件(Web前端開(kāi)發(fā)規(guī)范手冊(cè).doc)
命名是我們通俗約定的,但是沒(méi)有規(guī)定必須用這些常用的命名。
課堂案例:
<head>
<meta charset="utf-8">
<style>
.blue {
color: blue;
font-size: 100px;
}
.red {
color: red;
font-size: 100px;
}
.orange {
color: orange;
font-size: 100px;
}
.green {
color: green;
font-size: 100px;
}
</style>
</head>
<body>
<span class="blue">G</span>
<span class="red">o</span>
<span class="orange">o</span>
<span class="blue">g</span>
<span class="green">l</span>
<span class="red">e</span>
</body>
我們可以給標(biāo)簽指定多個(gè)類名,從而達(dá)到更多的選擇目的。
注意:
<div class="pink fontWeight font20">亞瑟</div>
<div class="font20">劉備</div>
<div class="font14 pink">安其拉</div>
<div class="font14">貂蟬</div>
id選擇器使用#進(jìn)行標(biāo)識(shí),后面緊跟id名
id選擇器和類選擇器最大的不同在于 使用次數(shù)上。
總結(jié)他們**
* { 屬性1:屬性值1; 屬性2:屬性值2; 屬性3:屬性值3; }
例如下面的代碼,使用通配符選擇器定義CSS樣式,清除所有HTML標(biāo)記的默認(rèn)邊距。
* {
margin: 0; /* 定義外邊距*/
padding: 0; /* 定義內(nèi)邊距*/
}
選擇器 | 作用 | 缺點(diǎn) | 使用情況 | 用法 |
標(biāo)簽選擇器 | 可以選出所有相同的標(biāo)簽,比如p | 不能差異化選擇 | 較多 | p { color:red;} |
類選擇器 | 可以選出1個(gè)或者多個(gè)標(biāo)簽 | 可以根據(jù)需求選擇 | 非常多 | .nav { color: red; } |
id選擇器 | 一次只能選擇器1個(gè)標(biāo)簽 | 只能使用一次 | 不推薦使用 | #nav {color: red;} |
通配符選擇器 | 選擇所有的標(biāo)簽 | 選擇的太多,有部分不需要 | 不推薦使用 | * {color: red;} |
選擇器
p {
font-size:20px;
}
注意:
p{ font-family:"微軟雅黑";}
p{font-family: Arial,"Microsoft Yahei", "微軟雅黑";}
常用技巧:
1. 各種字體之間必須使用英文狀態(tài)下的逗號(hào)隔開(kāi)。
2. 中文字體需要加英文狀態(tài)下的引號(hào),英文字體一般不需要加引號(hào)。當(dāng)需要設(shè)置英文字體時(shí),英文字體名必須位于中文字體名之前。
3. 如果字體名中包含空格、#、$等符號(hào),則該字體必須加英文狀態(tài)下的單引號(hào)或雙引號(hào),例如font-family: "Times New Roman";。
4. 盡量使用系統(tǒng)默認(rèn)字體,保證在任何用戶的瀏覽器中都能正確顯示。
字體名稱 | 英文名稱 | Unicode 編碼 |
宋體 | SimSun | B8BF53 |
新宋體 | NSimSun | B0B8BF53 |
黑體 | SimHei | ED1F53 |
微軟雅黑 | Microsoft YaHei | FAEF6FC5ED1 |
楷體_GB2312 | KaiTi_GB2312 | 77F53_GB2312 |
隸書(shū) | LiSu | B6E66 |
幼園 | YouYuan | E7C06 |
華文細(xì)黑 | STXihei | 4E87EC6ED1 |
細(xì)明體 | MingLiU | EC60EF53 |
新細(xì)明體 | PMingLiU | B0EC60EF53 |
屬性值 | 描述 |
normal | 默認(rèn)值(不加粗的) |
bold | 定義粗體(加粗的) |
100~900 | 400 等同于 normal,而 700 等同于 bold 我們重點(diǎn)記住這句話 |
提倡:
我們平時(shí)更喜歡用數(shù)字來(lái)表示加粗和不加粗。
font-style屬性用于定義字體風(fēng)格,如設(shè)置斜體、傾斜或正常字體,其可用屬性值如下:
屬性 | 作用 |
normal | 默認(rèn)值,瀏覽器會(huì)顯示標(biāo)準(zhǔn)的字體樣式 font-style: normal; |
italic | 瀏覽器會(huì)顯示斜體的字體樣式。 |
小技巧:
平時(shí)我們很少給文字加斜體,反而喜歡給斜體標(biāo)簽(em,i)改為普通模式。
font屬性用于對(duì)字體樣式進(jìn)行綜合設(shè)置
選擇器 { font: font-style font-weight font-size/line-height font-family;}
屬性 | 表示 | 注意點(diǎn) |
font-size | 字號(hào) | 我們通常用的單位是px 像素,一定要跟上單位 |
font-family | 字體 | 實(shí)際工作中按照?qǐng)F(tuán)隊(duì)約定來(lái)寫(xiě)字體 |
font-weight | 字體粗細(xì) | 記住加粗是 700 或者 bold 不加粗 是 normal 或者 400 記住數(shù)字不要跟單位 |
font-style | 字體樣式 | 記住傾斜是 italic 不傾斜 是 normal 工作中我們最常用 normal |
font | 字體連寫(xiě) | 1. 字體連寫(xiě)是有順序的 不能隨意換位置 2. 其中字號(hào) 和 字體 必須同時(shí)出現(xiàn) |
表示表示 | 屬性值 |
預(yù)定義的顏色值 | red,green,blue,還有我們的御用色 pink |
十六進(jìn)制 | #FF0000,#FF6600,#29D794 |
RGB代碼 | rgb(255,0,0)或rgb(100%,0%,0%) |
屬性 | 解釋 |
left | 左對(duì)齊(默認(rèn)值) |
right | 右對(duì)齊 |
center | 居中對(duì)齊 |
一般情況下,行距比字號(hào)大7.8像素左右就可以了。
line-height: 24px;
1em 就是一個(gè)字的寬度 如果是漢字的段落, 1em 就是一個(gè)漢字的寬度
p {
/*行間距*/
line-height: 25px;
/*首行縮進(jìn)2個(gè)字 em 1個(gè)em 就是1個(gè)字的大小*/
text-indent: 2em;
}
text-decoration 通常我們用于給鏈接修改裝飾效果
值 | 描述 |
none | 默認(rèn)。定義標(biāo)準(zhǔn)的文本。 取消下劃線(最常用) |
underline | 定義文本下的一條線。下劃線 也是我們鏈接自帶的(常用) |
overline | 定義文本上的一條線。(不用) |
line-through | 定義穿過(guò)文本下的一條線。(不常用) |
屬性 | 表示 | 注意點(diǎn) |
color | 顏色 | 我們通常用 十六進(jìn)制 比如 而且是簡(jiǎn)寫(xiě)形式 #fff |
line-height | 行高 | 控制行與行之間的距離 |
text-align | 水平對(duì)齊 | 可以設(shè)定文字水平的對(duì)齊方式 |
text-indent | 首行縮進(jìn) | 通常我們用于段落首行縮進(jìn)2個(gè)字的距離 text-indent: 2em; |
text-decoration | 文本修飾 | 記住 添加 下劃線 underline 取消下劃線 none |
Emmet的前身是Zen coding,它使用縮寫(xiě),來(lái)提高h(yuǎn)tml/css的編寫(xiě)速度。
emment語(yǔ)法
件引用規(guī)范
先說(shuō)加載的規(guī)范,這個(gè)規(guī)范主要是為了提高頁(yè)面加載速度或者是首屏的速度。
1 CSS 文件或樣式在 head 標(biāo)簽中引用。頁(yè)面的渲染需要 CSS,所以盡量早的讓 CSS 文件加載出來(lái)。
2 JS 文件要放在 body 標(biāo)簽尾部。頁(yè)面里加載和運(yùn)行 JS 都會(huì)阻塞頁(yè)面的渲染過(guò)程,所以把 JS 放在尾部可以加快首屏顯示的速度,但對(duì)整個(gè)頁(yè)面完成加載的時(shí)間沒(méi)什么影響。
3 使用壓縮后的文件。線上使用的靜態(tài)文件,盡量都是壓縮好的,CSS 使用 .min.css 形式,JS 使用 .min.js 形式,這樣可以減少文件的體積,從而減少下載的時(shí)間。
4 減少 import 方式引用 css 文件。import 方式引入的 CSS 文件要等原 CSS 文件加載并解析后才會(huì)去請(qǐng)求, 會(huì)拖慢 CSS 文件的加載速度。
屬性的書(shū)寫(xiě)規(guī)范
一、使用縮寫(xiě)
在 CSS 中有很多屬性或?qū)傩灾悼梢钥s寫(xiě), 在能用縮寫(xiě)的地方盡量使用縮寫(xiě)。
1、屬性的縮寫(xiě)。CSS 中有些屬性是可以合并的, 如:
margin-top: 10px;
margin-bottom: 0;
margin-left: 5px;
margin-right: 5px;
上面這幾組 margin 相關(guān)的屬性占了四條樣式, 我們可以使用一條 margin 屬性代替這四個(gè)方向的 margin:
margin: 10px 5px 0 5px;
一般帶有方向的屬性, 縮寫(xiě)的時(shí)候各個(gè)方向的值都是按著"上 右 下 左"的順序?qū)懙摹A硗馊绻膫€(gè)方向值一樣,可以直接用一個(gè)值代替四個(gè)方向;如果左右方向的值一樣,則可以省略最后一個(gè)左側(cè)的值。
上面這條縮寫(xiě)也可以寫(xiě)成:
margin: 10px 5px 0;
2、顏色的縮寫(xiě)。在使用十六進(jìn)制顏色的時(shí)候, 如果 rgb 三個(gè)顏色位置中, 每?jī)晌坏念伾迪嗤? 可以把六位的顏色寫(xiě)成三位。
如:color: #22ffcc;
就可以寫(xiě)成:
color: #2fc;
這兩種寫(xiě)法是等效的, 但要注意的是如果需要兼容低版本 IE 瀏覽器, 還是要用六位的顏色值。
3、數(shù)字的縮寫(xiě)。在 CSS 中如果整數(shù)部分是 0 的小數(shù), 可以忽略小數(shù)點(diǎn)前面的 0; 如果屬性值是 0, 則可以忽略屬性值的單位。
如: font-size: 0.8rem; padding: 0px;
這兩條屬性就可以做簡(jiǎn)寫(xiě):
font-size: .8rem; padding: 0;
二、屬性順序的規(guī)范
理論上, CSS 的屬性是一條一條解析執(zhí)行的。這種情況下, 就要把能確定大小和位置的屬性寫(xiě)在前面, 把對(duì)布局沒(méi)什么影響的屬性寫(xiě)在后面, 避免返工。
一般說(shuō)的使用順序如下:
1. 位置屬性 (position, top, right, z-index, display, float等)
2. 大小 (width, height, padding, margin)
3. 文字系列 (font, line-height, letter-spacing, color- text-align等)
4. 背景 (background, border等) 5. 其他 (animation, transition等)
注釋規(guī)范
一 文件頭注釋
/*
* @Author: zhangsan
* @Date: 2023-04-18 20:09:21
* @Last Modified by: zhangsan
* @Last Modified time: 2023-05-05 10:21:21
*/
二 普通注釋
/* 頭部導(dǎo)航 */
.nav-top{
background: #ccc;
}
CSS-Reset
*請(qǐng)認(rèn)真填寫(xiě)需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。