HTML中如何引入圖標
在頭部引用在HTML中里面引用一個東西,。在頭部引用<script defer src=";
然后在網上搜索font awesome??梢赃M那個官方(外國網站比較卡)。以下為點進那個中文網–字體圖標
點擊右上角圖標庫
3隨便點一個進去
4復制<i class="fa fa-address-book-o" aria-hidden="true"></i>
引入你的代碼中<span><i class="fa fa-address-book-o" aria-hidden="true"></i>></span>
<div><i class="fa fa-address-book-o" aria-hidden="true"></i>></div>
1
在div或span里引用,可以實現塊狀元素和行內元素的功能,不用管i標簽,改變圖標大小用font-size,調上下高度line-height,左右位置text-align。
部分圖標可以引用不了,大致樣式
3.完美是最無情的禁錮
是什么
ES5提供的數組的方法。
reduce() 方法接收一個函數作為回調函數(accumulator),數組中的每個值(從左到右)開始縮減(其實就是從左往右開始對每個數執行回調函數),最終為一個值。
PS: 回調函數的返回結果類型和傳入的初始值相同
語法以及參數
arr.reduce( callback(accumulator, currentValue,index ,array ) ,initialValue )
1
initialValue 可選
如果有的話則作為,第一次調用 callback函數時的第一個參數的值。
如果沒有提供初始值,callback則使用數組的第一個元素,作為第一次調用的初始值。
在沒有初始值的空數組上調用 reduce 將報錯。
accumulator
默認傳入上一次調用回調函數的的返回值。
初始值: initialValue存在的話,則是initialValue 若沒有則是數組的第一個元素
currentValue
數組中正在處理的元素。
index 可選
數組中正在處理的當前元素的索引。 如果提供了initialValue,則起始索引號為0,否則從索引1起始。
array可選
調用reduce()的數組
一個小小的例子
例1 無initialValue
var arr = [1, 2, 3, 4, 5];
sum = arr.reduce(function(result, cur, index, arr) {
console.log(result, cur, index,arr);
return result+ cur;
})
console.log(sum) // 最后的結果是15
result cur index arr
第1次 1 2 1 [1, 2, 3, 4, 5]
第2次 3 3 2 [1, 2, 3, 4, 5]
第3次 6 4 3 [1, 2, 3, 4, 5]
第4次 10 5 4 [1, 2, 3, 4, 5]
例2 有initialValue 傳入10
var arr = [1, 2, 3, 4, 5];
sum = arr.reduce(function(result, cur, index, arr) {
console.log(result, cur, index,arr);
return result+ cur;
},10)
console.log(sum) // 最后的結果是25
result cur index arr
第1次 10 1 0 [1, 2, 3, 4, 5]
第2次 11 2 1 [1, 2, 3, 4, 5]
第3次 13 3 2 [1, 2, 3, 4, 5]
第4次 16 4 3 [1, 2, 3, 4, 5]
第5次 20 5 4 [1, 2, 3, 4, 5]
回調函數的返回值
上面的例子返回的都是一個整型數字,如果希望返回其他類型的數據呢?
這個就跟accumulator的初始值有關系了。
下面的例子我們傳入的是一個object {sum: 0}
var items = [0,1,2,3,4];
var reducer = function add(sumT, item) {
console.log(sumT)
sumT.sum = sumT.sum + item;
return sumT;
};
var total = items.reduce(reducer, {sum: 0});
console.log(total); // {sum:1130}
運行結果
{sum: 0}
{sum: 1}
{sum: 3}
{sum: 6}
{sum: 10}
reduce()的應用
node系列之數據接口注冊登陸接口的實現
1、使用express腳手架創建項目
2、了解項目的目錄結構
3、準備數據庫相關文件
4、編寫注冊接口
5、編寫登陸接口
6、驗證登陸實現
7、預告
1、使用express腳手架創建項目
// 安裝腳手架,只需安裝一次
npm i express-generator -g
// 創建express項目
express myapp --view=ejs
cd myapp
// 安裝依賴
npm i
// 安裝需要使用的模塊
// 數據庫模塊 用戶唯一id模塊 密碼加密模塊 token模塊
npm i mongoose node-uuid bcryptjs jsonwebtoken -S
2、了解項目的目錄結構
bin
www ------- 服務器啟動
node_modules ------- 項目的依賴文件
public ------- 靜態資源文件夾
images ------- 靜態圖片
javascripts ------- 靜態的js文件
stylesheets ------- 靜態的樣式表文件
routes ------- 路由文件
index.js ------- 默認的路由
users.js ------- 用戶相關的路由
views ------- 路由對應的頁面
index.ejs ------- 默認的首頁
error.ejs ------- 錯誤頁面
app.js ------- 使用中間件,注冊路由
package.json ------- 描述文件
3、準備數據庫相關文件
大勛在node系列之數據庫mongoose的封裝中給大家介紹了如何封裝mongoose,可以先行查看如何封裝,封裝的文件夾為sql,如果不想看的,可以直接通過網盤下載該文件夾
將該sql文件放置項目的跟目錄下
Patch和Diff算法
網上看了好多的博客和源碼教程,感覺很多仔細的地方沒有說清,而且在一些復雜的部分加了好多的描述,所以就想自己也寫下心得, 方便自己, 方便他人,有興趣的同學可以關注我的github里面有我之前一些博文 github/193Eric
我們知道的,在數據更改后,會觸發getter,然后通過dep.notify()來通知watcher觸發update進而更新視圖,最終是通過Diff算法來對比新老Vnode的差異,并把差異更新到Dom視圖上
Diff
我們知道的,Virtual DOM是一顆樹,而diff算法主要把兩顆樹進行對比,找出之間的差異,來渲染頁面
diff 算法是通過同層的樹節點進行比較而非對樹進行逐層搜索遍歷的方式,所以時間復雜度只有 O(n),是一種相當的算法
1.調用patch函數比較Vnode和OldVnode,如果不一樣直接return Vnode即將Vnode真實化后替換掉DOM中的節點
2.如果OldVnode和Vnode值得進一步比較則調用patchVnode方法進行進一步比較,分為以下幾種情況:
Vnode有子節點,但是OldVnode沒有,則將Vnode的子節點真實化后添加到真實DOM上
Vnode沒有子節點,但是OldVnode上有,則將真實DOM上相應位置的節點刪除掉
Vnode和OldVnode都有文本節點但是內容不一樣,則將真實DOM上的文本節點替換為Vnode上的文本節點
Vnode和OldVnode上都有子節點,需要調用updateChildren函數進一步比較
updateChildren比較規則
提取出Vnode和OldVnode中的子節點分別為vCh和OldCh,并且提出各自的起始和結尾變量標記為 oldS oldE newS newE
如果是oldS和newE匹配上了,那么真實dom中的第一個節點會移到最后
如果是oldE和newS匹配上了,那么真實dom中的最后一個節點會移到最前,匹配上的兩個指針向中間移動
如果都沒有,在沒有key的情況下直接在DOM的oldS位置的前面添加newS,同時newS+1。在有key的情況下會將newS和Oldch上的所有節點對比,如果有相同的則移動DOM并且將舊節點中這個位置置為null且newS+1。如果還沒有則直接在DOM的oldS位置的前面添加newS且newS+1
直到出現任意一方的start>end,則有一方遍歷結束,整個比較也結束
updateChildren例子:
假設:
真實dom為 A、B、C
oldDom為 A1、B1、C1
newDom為 A2、D2、C2、B2
先確定oldS = A1 ; oldE = C1; newS = A2; newE = B2
先對比oldS和newS,oldE和newE,發現oldS = newS 所以真實dom的A固定不動。排序為 A、B、C
然后oldS = B1 ; oldE = C1; newS = D2; newE = B2
對比發現 oldS = newE , 所以真實dom,B要插入到后面去
真實dom排序為:A、C、B
然后oldS = C1; oldE = C1; newS = D2; newE = B2
對比發現兩兩都不對等,所以走第三步。
假設有key存在,所以newS直接和oldDom里面的所有節點對比,發現沒有存在,然后插入到oldS前面,且newS+1
真實dom排序為:A、D、C、B
然后重新開始,oldS++ > oldE-- ,結束了。
這就是updateChildren,之后就是一直遍歷,運行updateChildren直到沒有
1, JavaScript的Ajax
Ajax的全稱是Asynchronous JavaScript and XML,意思就是用JavaScript執行異步網絡請求,而不需要重載(刷新)整個頁面。
Ajax使用XMLHttpRequest對象取得新數據,然后再通過 DOM 將新數據插入到頁面中。另外,雖然名字中包含 XML 的成分,但 Ajax 通信與數據格式無關; 這種技術就是無須刷新頁面即可從服務器取得數據,但不一定是 XML 數據。
對于IE7+和其他瀏覽器,可以直接使用XMLHttpRequest對象,對于IE6及以前的瀏覽器,使用ActiveXObject對象。
使用方法如下:
var xhr;
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else {
xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
1
2
3
4
5
6
啟動請求:
xhr.open(method, url, boolean);
xhr.send();
1
2
注:
1,xhr.open參數含義:
method:請求方式,post、get等
url: 請求鏈接,只能向同源的url發送請求
boolean:是否異步請求,true:異步, false: 同步,默認為true
2,調用 open()方法并不會真正發送請求, 而只是啟動一個請求以備發送。
3,send()方法接收一個參數,即要作為請求主體發送的數據(post方法會使用,get方法直接傳null)。如果不需要通過請求主體發送數據,則必須傳入 null,因為這個參數對有些瀏覽器來說是必需的。調用send()之后,請求就會被分派到服務器。
XMLHttpRequest對象的異步請求示例如下:
function success(text) {
console.log(text);
}
function fail(code) {
console.log(code);
}
var xhr = new XMLHttpRequest(); // 新建XMLHttpRequest對象
xhr.onreadystatechange = function () {
// 狀態發生變化時,函數被回調
if (xhr.readyState === 4) { // 成功完成
// 判斷響應結果:
if (xhr.status === 200) {
// 成功,通過responseText拿到響應的文本:
return success(xhr.responseText);
} else {
// 失敗,根據響應碼判斷失敗原因:
return fail(xhr.status);
}
} else {
// HTTP請求還在繼續...
}
}
// 發送請求:
xhr.open('get', '/api/categories');
xhr.send(null);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
xhr的屬性含義如下:
responseText: 作為響應主體被返回的文本。
responseXML: 如果響應的內容類型是"text/xml"或"application/xml",這個屬性中將保存響應數據的 XML DOM 文檔。
status: 響應的 HTTP 狀態。
statusText: HTTP 狀態的說明。
readyState :表示請求/響應過程的當前活動階段??扇≈等缦?。
0: 未初始化。尚未調用 open()方法。
1: 啟動。已經調用 open()方法,但尚未調用 send()方法。
2: 發送。已經調用 send()方法,但尚未接收到響應。
3: 接收。已經接收到部分響應數據。
4: 完成。已經接收到全部響應數據,而且已經可以在客戶端使用了。
只要 readyState 屬性的值由一個值變成另一個值,都會觸發一次 readystatechange 事件??梢岳眠@個事件來檢測每次狀態變化后readyState 的值。通常,我們只對 readyState 值為 4 的階段感興趣,因為這時所有數據都已經就緒。不過,必須在調用 open()之前指定 onreadystatechange事件處理程序才能確??鐬g覽器兼容性。
另外,在接收到響應之前還可以調用 abort()方法來取消異步請求:
xhr.abort();
1
調用這個方法后,XHR 對象會停止觸發事件,而且也不再允許訪問任何與響應有關的對象屬性。在終止請求之后,還應該對 XHR 對象進行解引用操作。由于內存原因,不建議重用 XHR 對象。
2, jQuery的Ajax
$.ajax({
url:"",
type:"GET",
contentType: '',
async:true,
data:{},
dataType:"",
success: function(){
}
});
1
2
3
4
5
6
7
8
9
10
url 必填項,規定把請求發送到哪個 URL。
type 以什么樣的方式獲取數據,是get或post
contentType:發送POST請求的格式,默認值為’application/x-www-form-urlencoded;
charset=UTF-8’,也可以指定為text/plain、application/json
async 是否異步執行AJAX請求,默認為true,千萬不要指定為false
data 發送的數據,可以是字符串、數組或object。如果是GET請求,data將被轉換成query附加到URL上,如果是POST請求,根據contentType把data序列化成合適的格式;
dataType
接收的數據格式,可以指定為’html’、‘xml’、‘json’、'text’等,缺省情況下根據響應的Content-Type猜測。
success 可選。執行成功時返回的數據。
缺點:
是基于XHR原生開發的,目前已有的fetch可替代。本身是針對mvc的編程模式,不太適合目前mvvm的編程模式。jQuery本身比較大,如果單純的使用ajax可以自己封裝一個,不然會影響性能體驗。
3,Axios
Vue2.0之后,axios開始受到更多的歡迎。其實axios也是對原生XHR的一種封裝,不過是Promise實現版本。它是一個用于瀏覽器和 nodejs 的 HTTP 客戶端,符合的ES規范。
axios具有以下特征:
從瀏覽器中創建 XMLHttpRequest
支持 Promise API
客戶端支持防止CSRF
提供了一些并發請求的接口
從 node.js 創建 http 請求
攔截請求和響應
轉換請求和響應數據
取消請求
自動轉換JSON數據
PS:防止CSRF:就是讓你的每個請求都帶一個從cookie中拿到的key, 根據瀏覽器同源策略,假冒的網站是拿不到你cookie中得key的,這樣,后臺就可以輕松辨別出這個請求是否是用戶在假冒網站上的誤導輸入,從而采取正確的策略。
設置全局的 axios 默認值
axios.defaults.baseURL = '
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'
1
2
3
注:axios 的 headers的 content-type 默認是 “application/json ”
默認情況下,axios將JavaScript對象序列化為JSON,如果是get請求,對請求參數不用做任何處理,但是如果是post請求,并且Content-Type 為application/x-www-form-urlencoded,需要使用URLSearchParams API格式化請求參數, 否則Content-Type依然是application/json
var params = new URLSearchParams();
params.append('param1', 'value1');
params.append('param2', 'value2');
1
2
3
get請求,以下3中寫法完全等價
axios.get('/user?id=12345&name=xiaoming')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
1
2
3
4
5
6
7
axios.get('/user', {
params: {
id: '12345',
name: 'xiaoming'
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
1
2
3
4
5
6
7
8
9
10
11
12
axios({
url: '/user',
method: 'get',
params: {
id: '12345',
name: 'xiaoming'
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
post請求,以下2種寫法完全等價
axios({
url: '/user',
method: 'post',
headers: {
'Content-Type': 'application/json'
},
data: {
id: '12345',
name: 'xiaoming'
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var url = '/user';
var data = {
id: '12345',
name: 'xiaoming'
};
axios.post(url, data, {
headers: {
'Content-Type': 'application/json'
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
執行多個并發請求
function getUserAccount() {
return axios.get('/user/12345');
}
function getUserPermissions() {
return axios.get('/user/12345/permissions');
}
axios.all([getUserAccount(), getUserPermissions()])
.then(axios.spread(function (acct, perms) {
// 兩個請求現在都執行完成
}));
1
2
3
4
5
6
7
8
9
10
11
12
創建實例
可以使用自定義配置新建一個 axios 實例
axios.create([config])
var instance = axios.create({
baseURL: '
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'}
});
1
2
3
4
5
6
配置會以一個優先順序進行合并,順序由低到高為
1,在 node_modules/axios/lib/defaults.js 找到的庫的默認值
2,實例的 defaults 屬性
3,請求的 config 參數
// 使用由庫提供的配置的默認值來創建實例
// 此時超時配置的默認值是 0
var instance = axios.create();
// 覆寫庫的超時默認值
// 現在,所有請求都會等待 2.5 秒
instance.defaults.timeout = 2500;
// 為已知需要花費很長時間的請求覆寫超時設置
instance.get('/longRequest', {
timeout: 5000
});
1
2
3
4
5
6
7
8
9
10
11
12
攔截器
在請求發出之前或響應被 then 或 catch 處理前攔截它們做預處理。
// 添加請求攔截器
axios.interceptors.request.use(function (config) {
// 在發送請求之前做些什么
}, function (error) {
// 對請求錯誤做些什么
});
// 添加響應攔截器
axios.interceptors.response.use(function (response) {
// 對響應數據做點什么
}, function (error) {
// 對響應錯誤做點什么
});
1
2
3
4
5
6
7
8
9
10
11
12
13
可以在稍后移除攔截器:
var myInterceptor = axios.interceptors.request.use(function () {/.../});
axios.interceptors.request.eject(myInterceptor);
1
2
可以為自定義 axios 實例添加攔截器
var instance = axios.create();
instance.interceptors.request.use(function () {/.../});
1
2
4, fetch
window 自帶了 window.fetch 方法, 在版的 Firefox 和 Chrome 中已經提供支持,其他瀏覽器還有兼容性問題,要做兼容性處理。fetch 是一個 基于promise設計的low-level API,不是ajax的進一步封裝,而是原生js,它注定不會像你習慣的 $.ajax 或是 axios 等庫幫你封裝各種各樣的功能或實現.
interface GlobalFetch {
fetch(input: RequestInfo, init?: RequestInit): Promise<Response>;
}
1
2
3
fetch()是一個全局的函數,返回一個promise對象。它有兩個參數,第一個參數是請求的地址,第二個參數是可選,RequestInit是個對象格式如下:
interface RequestInit {
body?: any;
cache?: RequestCache;
credentials?: RequestCredentials;
headers?: HeadersInit;
integrity?: string;
keepalive?: boolean;
method?: string;
mode?: RequestMode;
redirect?: RequestRedirect;
referrer?: string;
referrerPolicy?: ReferrerPolicy;
window?: any;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
優點:
符合關注分離,沒有將輸入、輸出和用事件來跟蹤的狀態混雜在一個對象里
更好更方便的寫法
更加底層,提供的API豐富
脫離了XHR,是ES規范里新的實現方式
fetch中可以設置mode為"no-cors"(不跨域)
缺點:
fetch不支持同步請求
fetch只對網絡請求報錯,對400,500都當做成功的請求,需要封裝去處理
fetch默認不會帶cookie,需要添加配置項
fetch不支持abort,不支持超時控制,使用setTimeout及Promise.reject的實現的超時控制并不能阻止請求過程繼續在后臺運行,造成了流量的浪費
fetch沒有辦法原生監測請求的進度,而XHR可以
fetch的使用示例:
window.fetch(url)
.then(response => {
if (response.ok) {
//通過 response 原型上的 json 方法將 response.body 轉換為 JS 對象,再返回出去
return response.json();
}
}
).then(result => {
console.log(result);
}).catch(error => {
console.log(error);
})
1
2
3
4
5
6
7
8
9
10
11
12
需要注意以下幾點:
1,用 response.ok判斷fetch請求是否成功
2,服務端只返回了response對象,而真正的請求結果,即 response.body,則是一個 ReadableStream。fetch 將 response.body 設計成 ReadableStream 在請求大體積文件時變得非常有用。然而,在我們的日常使用中,還是短小的 JSON 片段更加常見。而為了兼容不常見的設計,我們不得不多一次 response.json() 的調用。不僅是調用變得麻煩,如果你的服務端采用了嚴格的 REST 風格,對于某些特殊情況并沒有返回 JSON 字符串,而是用了 HTTP 狀態碼(如:204 No Content),那么在調用 response.json() 時則會拋出異常。
3,Response 限制了響應內容的重復讀取和轉換,response .json / response.text 方法只能使用一個并且只能使用一次,同時使用兩個,或使用兩次都會報如下錯誤:
Uncaught (in promise) TypeError: Failed to execute 'json' on 'Response': body stream is locked
1
為什么不能使用兩次?
因為數據流只能讀取一次,一旦讀取,數據流變空,再次讀取會報錯。
————————————————
版權聲明:本文為CSDN博主「Sherry慈」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_41480546/article/details/102805864
這里我截取的是一個圖片,實際上是會動的。廢話不多說,上代碼。
HTML:
<canvas id="canvas"></canvas>
1
CSS:
/css reset /
body,p,div,ol,ul,li,dl,dt,dd,h1,h2,h3,h4,h5,h6,form,input,iframe,nav {
margin: 0;
padding: 0;
}
html,body {
width: 100%;
height: 100%;
}
body {
font: 14px Microsoft YaHei;
-webkit-text-size-adjust:100%;
-moz-user-select: none;
-webkit-user-select: none;
user-select: none;
position: relative;
background: #000;
}
width: 100%;
height: 100%;
display: block;
opacity: .8;
}
// 音量大小,0.01-1
//宇宙
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d'),
w = canvas.width = window.innerWidth,
h = canvas.height = window.innerHeight,
hue = 217,
stars = [],
count = 0,
maxStars = 1100; //星星數量,默認1300
var canvas2 = document.createElement('canvas'),
ctx2 = canvas2.getContext('2d');
canvas2.width = 100;
canvas2.height = 100;
var half = canvas2.width / 2,
gradient2 = ctx2.createRadialGradient(half, half, 0, half, half, half);
gradient2.addColorStop(0.025, '#CCC');
gradient2.addColorStop(0.1, 'hsl(' + hue + ', 61%, 33%)');
gradient2.addColorStop(0.25, 'hsl(' + hue + ', 64%, 6%)');
gradient2.addColorStop(1, 'transparent');
ctx2.fillStyle = gradient2;
ctx2.beginPath();
ctx2.arc(half, half, half, 0, Math.PI 2);
ctx2.fill();
// End cache
function random(min, max) {
if (arguments.length < 2) {
max = min;
min = 0;
}
if (min > max) {
var hold = max;
max = min;
min = hold;
}
return Math.floor(Math.random() (max - min + 1)) + min;
}
function maxOrbit(x, y) {
var max = Math.max(x, y),
diameter = Math.round(Math.sqrt(max max + max max));
return diameter / 2;
//星星移動范圍,值越大范圍越小,
}
var Star = function() {
this.orbitRadius = random(maxOrbit(w, h));
this.radius = random(60, this.orbitRadius) / 10; //星星大小,值越大星星越小,默認8
this.orbitX = w / 2;
this.orbitY = h / 2;
this.timePassed = random(0, maxStars);
this.speed = random(this.orbitRadius) / 80000; //星星移動速度,值越大越慢,默認5W
this.alpha = random(2, 10) / 10;
count++;
stars[count] = this;
}
Star.prototype.draw = function() {
var x = Math.sin(this.timePassed) this.orbitRadius + this.orbitX,
y = Math.cos(this.timePassed) this.orbitRadius + this.orbitY,
twinkle = random(10);
if (twinkle === 1 && this.alpha > 0) {
this.alpha -= 0.05;
} else if (twinkle === 2 && this.alpha < 1) {
this.alpha += 0.05;
}
ctx.globalAlpha = this.alpha;
ctx.drawImage(canvas2, x - this.radius / 2, y - this.radius / 2, this.radius, this.radius);
this.timePassed += this.speed;
}
for (var i = 0; i < maxStars; i++) {
new Star();
}
function animation() {
ctx.globalCompositeOperation = 'source-over';
ctx.globalAlpha = 0.5; //尾巴
ctx.fillStyle = 'hsla(' + hue + ', 64%, 6%, 2)';
ctx.fillRect(0, 0, w, h)
ctx.globalCompositeOperation = 'lighter';
for (var i = 1,
l = stars.length; i < l; i++) {
stars[i].draw();
};
window.requestAnimationFrame(animation);
}
animation();
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務。
開發工具與關鍵技術:Adobe Dreamweaver CC
作者:黃燦
撰寫時間:2019.1.16
在模仿華為官方網頁的練習當中我發現華為官網中有一個遮罩層是隨便點擊遮罩層的背景也能關閉掉遮罩層,但唯獨點擊內容區域不會關閉掉遮罩層。于是我開始模仿這個寫案例,連內容也一模一樣(因為這個練習就是要寫出和華為關一樣的效果或則比它更好的效果),一開始我是這樣子寫的(圖1)
圖1
class=Select_Region_bj 我給了一個灰色半透明的背景樣式,后來在Javascript中寫onclick事件無論這么寫,點擊內容區也是會關閉掉遮罩層。我百思不得其解到底怎么樣寫才能點擊內容區不會關閉遮罩層,后來下課期間我看見我同學他寫的帶能點擊內容區不會關閉遮罩層。我問他你是這么寫的,他告訴我:“把他們分離就可以的了?!蔽宜伎剂艘粫?,腦補:分離?怎么分離?補著補著補著就補出了背景和內容區分離。分離寫(圖2)
圖2
把背景層和內容區分開來寫,不要在背景層中包裹內容,這樣子點擊內容區就不會關閉掉遮罩層了!
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務。
vue中關于插槽的文檔說明很短,語言又寫的很凝練,再加上其和methods,data,computed等常用選項使用頻率、使用先后上的差別,這就有可能造成初次接觸插槽的開發者容易產生“算了吧,回頭再學,反正已經可以寫基礎組件了”,于是就關閉了vue說明文檔。
實際上,插槽的概念很簡單,下面通過分三部分來講。這個部分也是按照vue說明文檔的順序來寫的。
進入三部分之前,先讓還沒接觸過插槽的同學對什么是插槽有一個簡單的概念:插槽,也就是slot,是組件的一塊HTML模板,這塊模板顯示不顯示、以及怎樣顯示由父組件來決定。 實際上,一個slot最核心的兩個問題這里就點出來了,是顯示不顯示和怎樣顯示。
由于插槽是一塊模板,所以,對于任何一個組件,從模板種類的角度來分,其實都可以分為非插槽模板和插槽模板兩大類。
非插槽模板指的是html模板,指的是‘div、span、ul、table’這些,非插槽模板的顯示與隱藏以及怎樣顯示由插件自身控制;插槽模板是slot,它是一個空殼子,因為它顯示與隱藏以及最后用什么樣的html模板顯示由父組件控制。但是插槽顯示的位置確由子組件自身決定,slot寫在組件template的哪塊,父組件傳過來的模板將來就顯示在哪塊。
首先是單個插槽,單個插槽是vue的官方叫法,但是其實也可以叫它默認插槽,或者與具名插槽相對,我們可以叫它匿名插槽。因為它不用設置name屬性。
單個插槽可以放置在組件的任意位置,但是就像它的名字一樣,一個組件中只能有一個該類插槽。相對應的,具名插槽就可以有很多個,只要名字(name屬性)不同就可以了。
下面通過一個例子來展示。
父組件:
-
<template>
-
<div class="father">
-
<h3>這里是父組件</h3>
-
<child>
-
<div class="tmpl">
-
<span>菜單1</span>
-
<span>菜單2</span>
-
<span>菜單3</span>
-
<span>菜單4</span>
-
<span>菜單5</span>
-
<span>菜單6</span>
-
</div>
-
</child>
-
</div>
-
</template>
子組件:
-
<template>
-
<div class="child">
-
<h3>這里是子組件</h3>
-
<slot></slot>
-
</div>
-
</template>
在這個例子里,因為父組件在<child></child>里面寫了html模板,那么子組件的匿名插槽這塊模板就是下面這樣。也就是說,子組件的匿名插槽被使用了,是被下面這塊模板使用了。
-
<div class="tmpl">
-
<span>菜單1</span>
-
<span>菜單2</span>
-
<span>菜單3</span>
-
<span>菜單4</span>
-
<span>菜單5</span>
-
<span>菜單6</span>
-
</div>
最終的渲染結果如圖所示:
-
-
注:所有demo都加了樣式,以方便觀察。其中,父組件以灰色背景填充,子組件都以淺藍色填充。
匿名插槽沒有name屬性,所以是匿名插槽,那么,插槽加了name屬性,就變成了具名插槽。具名插槽可以在一個組件中出現N次。出現在不同的位置。下面的例子,就是一個有兩個具名插槽和單個插槽的組件,這三個插槽被父組件用同一套css樣式顯示了出來,不同的是內容上略有區別。
父組件:
-
<template>
-
<div class="father">
-
<h3>這里是父組件</h3>
-
<child>
-
<div class="tmpl" slot="up">
-
<span>菜單1</span>
-
<span>菜單2</span>
-
<span>菜單3</span>
-
<span>菜單4</span>
-
<span>菜單5</span>
-
<span>菜單6</span>
-
</div>
-
<div class="tmpl" slot="down">
-
<span>菜單-1</span>
-
<span>菜單-2</span>
-
<span>菜單-3</span>
-
<span>菜單-4</span>
-
<span>菜單-5</span>
-
<span>菜單-6</span>
-
</div>
-
<div class="tmpl">
-
<span>菜單->1</span>
-
<span>菜單->2</span>
-
<span>菜單->3</span>
-
<span>菜單->4</span>
-
<span>菜單->5</span>
-
<span>菜單->6</span>
-
</div>
-
</child>
-
</div>
-
</template>
子組件:
-
<template>
-
<div class="child">
-
// 具名插槽
-
<slot name="up"></slot>
-
<h3>這里是子組件</h3>
-
// 具名插槽
-
<slot name="down"></slot>
-
// 匿名插槽
-
<slot></slot>
-
</div>
-
</template>
顯示結果如圖:
可以看到,父組件通過html模板上的slot屬性關聯具名插槽。沒有slot屬性的html模板默認關聯匿名插槽。
最后,就是我們的作用域插槽。這個稍微難理解一點。官方叫它作用域插槽,實際上,對比前面兩種插槽,我們可以叫它帶數據的插槽。什么意思呢,就是前面兩種,都是在組件的template里面寫
-
匿名插槽
-
<slot></slot>
-
具名插槽
-
<slot name="up"></slot>
但是作用域插槽要求,在slot上面綁定數據。也就是你得寫成大概下面這個樣子。
-
<slot name="up" :data="data"></slot>
-
export default {
-
data: function(){
-
return {
-
data: ['zhangsan','lisi','wanwu','zhaoliu','tianqi','xiaoba']
-
}
-
},
-
}
我們前面說了,插槽最后顯示不顯示是看父組件有沒有在child下面寫模板,像下面那樣。
-
<child>
-
html模板
-
</child>
寫了,插槽就總得在瀏覽器上顯示點東西,東西就是html該有的模樣,沒寫,插槽就是空殼子,啥都沒有。
OK,我們說有html模板的情況,就是父組件會往子組件插模板的情況,那到底插一套什么樣的樣式呢,這由父組件的html+css共同決定,但是這套樣式里面的內容呢?
正因為作用域插槽綁定了一套數據,父組件可以拿來用。于是,情況就變成了這樣:樣式父組件說了算,但內容可以顯示子組件插槽綁定的。
我們再來對比,作用域插槽和單個插槽和具名插槽的區別,因為單個插槽和具名插槽不綁定數據,所以父組件是提供的模板要既包括樣式由包括內容的,上面的例子中,你看到的文字,“菜單1”,“菜單2”都是父組件自己提供的內容;而作用域插槽,父組件只需要提供一套樣式(在確實用作用域插槽綁定的數據的前提下)。
下面的例子,你就能看到,父組件提供了三種樣式(分別是flex、ul、直接顯示),都沒有提供數據,數據使用的都是子組件插槽自己綁定的那個人名數組。
父組件:
-
<template>
-
<div class="father">
-
<h3>這里是父組件</h3>
-
<!--第一次使用:用flex展示數據-->
-
<child>
-
<template slot-scope="user">
-
<div class="tmpl">
-
<span v-for="item in user.data">{{item}}</span>
-
</div>
-
</template>
-
-
</child>
-
-
<!--第二次使用:用列表展示數據-->
-
<child>
-
<template slot-scope="user">
-
<ul>
-
<li v-for="item in user.data">{{item}}</li>
-
</ul>
-
</template>
-
-
</child>
-
-
<!--第三次使用:直接顯示數據-->
-
<child>
-
<template slot-scope="user">
-
{{user.data}}
-
</template>
-
-
</child>
-
-
<!--第四次使用:不使用其提供的數據, 作用域插槽退變成匿名插槽-->
-
<child>
-
我就是模板
-
</child>
-
</div>
-
</template>
子組件:
-
<template>
-
<div class="child">
-
-
<h3>這里是子組件</h3>
-
// 作用域插槽
-
<slot :data="data"></slot>
-
</div>
-
</template>
-
-
export default {
-
data: function(){
-
return {
-
data: ['zhangsan','lisi','wanwu','zhaoliu','tianqi','xiaoba']
-
}
-
}
-
}
結果如圖所示:
以上三個demo就放在GitHub了,有需要的可以去取。使用非常方便,是基于vue-cli搭建工程。
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務。
前言:平時寫頁面的時候有些樣式使用完發現沒過多久就忘記了,這篇文章主要是用來記錄開發過程中容易忘記的CSS樣式,與其總是去網上查,還不如一個一個記錄下來,雖然說之前的都沒有記錄,但是知識的累積不論什么時候開始做都不會晚的。
首先 記錄幾個好用的插件網站:
layDate日期與時間組件: https://www.layui.com/laydate/
Vant移動端插件庫: https://youzan.github.io/vant/#/zh-CN/intro
Element組件庫: https://element.eleme.cn/#/zh-CN/component/installation
Vue.js框架: https://cn.vuejs.org/v2/guide/
Bootstrap框架: https://v2.bootcss.com/index.html
菜鳥教程官網: https://www.runoob.com/
w3school官網: https://www.w3school.com.cn/
下面是遇到的一些想累積的css樣式:(內容會隨時間累積的越來越多)
1、一個 div 中的內容實現上下滑動效果(而不是超出body的高以后上下滑動):overflow:auto;
簡單的描述:body 中的一個 div 內,如果設置了固定的 height,而內容的總 height 超出了 div 的高,則超出的部分就會被覆蓋,而想實現超出的部分變成滑動的效果而不被覆蓋,則用 overflow:auto; 實現。
2、修改 前端框架封裝好的css樣式: border-radius: 20px!important;(注意使用英文的 ! 嘆號)
簡單的描述:在開發過程中經常使用一些前端框架(bootstrap,vue.js,laydate,Vant等等),在使用link導入css文件以后,發現有些css是在標簽內使用內嵌的方式實現的,優先級最高,那么我們怎么修改呢?
比如:css文件中的邊框弧度樣式為10px:border-radius: 10px;
我們想改成20px,則在后面加上 !important 即可:border-radius: 20px!important;
這篇文章主要是以后回頭復習或者忘記了的時候給我自己看的,但是如果恰好也幫助到了你,那是更加的有意義,在以后的開發過程中,該文章的內容一定會累積的越來越多
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務。
普通數字轉會計金額格式(保留兩位小數)
我們可以用數字的toLocaleString()方法將普通數字轉為會計金額格式,但是這種方式無法保留兩位小數(四舍五入),如果是整數或者小數長度只有一位的時候無法自動補0
例如:
思路:
利用toLocaleString()以及toFixed()先對數字進行一個轉換得到最多保留了2位小數的金額,然后判斷數字是為整數還是帶有小數,如果帶有小數則進行切割,判斷小數長度為1時自動補0
// 普通數字轉會計金額格式 第一種
function toThousandsFormates(num) {
// 判斷傳進來的數字是否為非空數字
if (!isNaN(parseFloat(num))) {
var reg = /./g
var newNum = Number(Number(num).toFixed(2)).toLocaleString()
// 判斷轉換后的數字是否帶有小數
if (reg.test(newNum)) {
var numArr = newNum.split('.')
// 判斷小數點后數字長度為1,則自動補0
numArr[1] = numArr[1].length === 1 ? numArr[1] + '0' : numArr[1]
return numArr.join('.')
} else {
// 整數直接在后面補上0.00
return newNum + '.00'
}
} else {
return ''
}
}
console.log(toThousandsFormates('0')); // 0.00
console.log(toThousandsFormates('')); // ''
console.log(toThousandsFormates(966)); // 966.00
console.log(toThousandsFormates(966.3)); // 966.30
console.log(toThousandsFormates(9669228.55)); // 9,669,228.55
console.log(toThousandsFormates(96566.56954)); // 96,566.57
經過查閱資料后,發現toLocaleString()它里面自帶屬性可以檢查到最少保留了幾位小數,不夠自動補0,這樣我們上面的代碼其實可以更加簡單,如下:
// 普通數字轉會計金額格式 第二種
function toThousandsFormates2(num) {
// 判斷傳進來的數字是否為非空數字
if (!isNaN(parseFloat(num))) {
var newNum = Number(Number(num).toFixed(2)).toLocaleString('zh', { minimumFractionDigits: 2 })
return newNum
} else {
return ''
}
}
console.log(toThousandsFormates2('0')); // 0.00
console.log(toThousandsFormates2('')); // ''
console.log(toThousandsFormates2(966)); // 966.00
console.log(toThousandsFormates2(966.3)); // 966.30
console.log(toThousandsFormates2(9669228.55)); // 9,669,228.55
console.log(toThousandsFormates2(96566.56954)); // 96,566.57
// 結果一模一樣
會計金額格式轉普通數字(利用正則)
// 會計金額格式轉為普通數字
function rMoney(num) {
return parseFloat(num.replace(/[^\d\.-]/g, ''))
}
console.log(rMoney('96,566.57')); // 96566.57
console.log(rMoney('966.30')); // 966.3
console.log(rMoney('9,669,228.55')); // 9669228.55
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務。
藍藍設計的小編 http://www.syprn.cn