Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
家好,Echa。
今天來分享常見的瀏覽器數(shù)據(jù)存儲方案:localStorage、sessionStorage、IndexedDB、Cookies。
現(xiàn)代瀏覽器中提供了多種存儲機制,打開瀏覽器的控制臺(Mac 可以使用 Command + Option + J 快捷鍵,Windows 可以使用 Control + Shift + J 快捷鍵)。選擇 Application 選項卡,可以在 Storage中 看到 Local Storage、Session Storage、IndexedDB、Web SQL、Cookies 等:
那數(shù)據(jù)存儲在瀏覽器中有什么使用場景呢?在以下情況下,將數(shù)據(jù)存儲在瀏覽器中成為更可行的選擇:
無論哪種方式,將這些信息保存在客戶端可以減少額外且不必要的服務(wù)器調(diào)用,并幫助提供離線支持。不過,需要注意,由于實現(xiàn)差異,瀏覽器存儲機制在不同瀏覽器中的行為可能會有所不同。除此之外,許多瀏覽器已刪除對 Web SQL 的支持,建議將現(xiàn)有用法遷移到 IndexedDB。
所以下面我們將介紹 Local Storage、Session Storage、IndexedDB、Cookies 的使用方式、使用場景以及它們之間的區(qū)別。
HTML5 引入了 Web Storage,這使得在瀏覽器中存儲和檢索數(shù)據(jù)變得更加容易。Web Storage API 為客戶端瀏覽器提供了安全存儲和輕松訪問鍵值對的機制。Web Storage 提供了兩個 API 來獲取和設(shè)置純字符串的鍵值對:
Web Storage API 由 4 個方法 setItem()、getItem()、removeItem() 、clear()、key()和一個 length 屬性組成,以 localStorage 為例:
console.log(typeof window.localStorage) // Object
// 存儲數(shù)據(jù)
localStorage.setItem("colorMode", "dark")
localStorage.setItem("username", "zhangsan")
localStorage.setItem("favColor", "green")
console.log(localStorage.length) // 3
// 檢索數(shù)據(jù)
console.log(localStorage.getItem("colorMode")) // dark
// 移除數(shù)據(jù)
localStorage.removeItem("colorMode")
console.log(localStorage.length) // 2
console.log(localStorage.getItem("colorMode")) // null
// 檢索鍵名
window.localStorage.key(0); // favColor
// 清空本地存儲
localStorage.clear()
console.log(localStorage.length) // 0
localStorage 和 sessionStorage 都非常適合緩存非敏感應(yīng)用數(shù)據(jù)??梢栽谛枰鎯ι倭亢唵沃挡⒉唤?jīng)常訪問它們是使用它們。它們本質(zhì)上都是同步的,并且會阻塞主 UI 線程,所以應(yīng)該謹慎使用。
我們可以在瀏覽器上監(jiān)聽 localStorage 和 sessionStorage 的存儲變化。storage 事件在創(chuàng)建、刪除或更新項目時觸發(fā)。偵聽器函數(shù)在事件中傳遞,具有以下屬性:
通常,我們可以使用 window.addEventListener("storage", func) 或使用 onstorage 屬性(如 window.onstorage = func)來監(jiān)聽 storage 事件:
window.addEventListener('storage', e => {
console.log(e.key);
console.log(e.oldValu);
console.log(e.newValue);
});
window.onstorage = e => {
console.log(e.key);
console.log(e.oldValu);
console.log(e.newValue);
});
注意,該功能不會在發(fā)生更改的同一瀏覽器選項卡上觸發(fā),而是由同一域的其他打開的選項卡或窗口觸發(fā)。此功能用于同步同一域的所有瀏覽器選項卡/窗口上的數(shù)據(jù)。因此,要對此進行測試,需要打開同一域的另一個選項卡。
localStorage 和 sessionStorage 只能存儲 5 MB 的數(shù)據(jù),因此需要確保存儲的數(shù)據(jù)不會超過此限制。
localStorage.setItem('a', Array(1024 * 1024 * 5).join('a'))
localStorage.setItem('b', 'a')
// Uncaught DOMException: Failed to execute 'setItem' on 'Storage': Setting the value of `a` exceeded the quota.
在上面的例子中,收到了一個錯誤,首先創(chuàng)建了一個5MB的大字符串,當再添加其他數(shù)據(jù)時就報錯了。
另外,localStorage 和 sessionStorage 只接受字符串??梢酝ㄟ^ JSON.stringify 和 JSON.parse 來解決這個問題:
const user = {
name : "zhangsan",
age : 28,
gender : "male",
profession : "lawyer"
};
localStorage.setItem("user", JSON.stringify(user));
localStorage.getItem("user"); // '{"name":"zhangsan","age":28,"gender":"male","profession":"lawyer"}'
JSON.parse(localStorage.getItem("user")) // {name: 'zhangsan', age: 28, gender: 'male', profession: 'lawyer'}
如果我們直接將一個對象存儲在 localStorage 中,那將會在存儲之前進行隱式類型轉(zhuǎn)換,將對象轉(zhuǎn)換為字符串,再進行存儲:
const user = {
name : "zhangsan",
age : 28,
gender : "male",
profession : "lawyer"
};
localStorage.setItem("user", user);
localStorage.getItem("user"); // '[object Object]'
Web Storage 使用了同源策略,也就是說,存儲的數(shù)據(jù)只能在同一來源上可用。如果域和子域相同,則可以從不同的選項卡訪問 localStorage 數(shù)據(jù),而無法訪問 sessionStorage 數(shù)據(jù),即使它是完全相同的頁面。
另外:
下面來看一個使用 localStorage 的簡單示例,使用 localStorage 來存儲用戶偏好:
<input type="checkbox" id="darkTheme" name="darkTheme" onclick='onChange(this);'>
<label for="darkTheme">黑暗模式</label><br>
html {
background: white;
}
.dark {
background: black;
color: white;
}
function toggle(on) {
if (on) {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
}
function save(on) {
localStorage.setItem('darkTheme', on.toString());
}
function load() {
return localStorage.getItem('darkTheme') === 'true';
}
function onChange(checkbox) {
const value = checkbox.checked;
toggle(value);
save(value);
}
const initialValue = load();
toggle(initialValue);
document.querySelector('#darkTheme').checked = initialValue;
這里的代碼很簡單,頁面上有一個單選框,選中按鈕時將頁面切換為黑暗模式,并將這個配置存儲在 localStorage 中。當下一次再初始頁面時,獲取 localStorage 中的主題設(shè)置。
Cookie 主要用于身份驗證和用戶數(shù)據(jù)持久性。Cookie 與請求一起發(fā)送到服務(wù)器,并在響應(yīng)時發(fā)送到客戶端;因此,cookies 數(shù)據(jù)在每次請求時都會與服務(wù)器交換。服務(wù)器可以使用 cookie 數(shù)據(jù)向用戶發(fā)送個性化內(nèi)容。嚴格來說,cookie 并不是客戶端存儲方式,因為服務(wù)器和瀏覽器都可以修改數(shù)據(jù)。它是唯一可以在一段時間后自動使數(shù)據(jù)過期的方式。
每個 HTTP 請求和響應(yīng)都會發(fā)送 cookie 數(shù)據(jù)。存儲過多的數(shù)據(jù)會使 HTTP 請求更加冗長,從而使應(yīng)用比預期更慢:
Cookie 通常用于會話管理、個性化以及跨網(wǎng)站跟蹤用戶行為。我們可以通過服務(wù)端和客戶端設(shè)置和訪問 cookie。Cookie 還具有各種屬性,這些屬性決定了在何處以及如何訪問和修改它們,
Cookie 分為兩種類型:
下面先來看看如何訪問和操作客戶端和服務(wù)器上的 cookie。
客戶端 JavaScript 可以通過 document.cookie 來讀取當前位置可訪問的所有 cookie。它提供了一個字符串,其中包含一個以分號分隔的 cookie 列表,使用 key=value 格式。
document.cookie;
可以看到,在語雀主頁中獲取 cookie,結(jié)果中包含了登錄的 cookie、語言、當前主題等。
同樣,可以使用 document.cookie 來設(shè)置 cookie 的值,設(shè)置cookie也是用key=value格式的字符串,屬性用分號隔開:
document.cookie = "hello=world; domain=example.com; Secure";
這里用到了兩個屬性 SameSite 和 Secure,下面會介紹。如果已經(jīng)存在同名的 cookie 屬性,就會更新已有的屬性值,如果不存在,就會創(chuàng)建一個新的 key=value。
如果需要經(jīng)常在客戶端處理 Cookie,建議使用像 js-cookie 這樣的庫來處理客戶端 cookie:
Cookies.set('hello', 'world', { domain: 'example.com', secure: true });
Cookies.get('hello'); // -> world
這樣不僅為 cookie 上的 CRUD 操作提供了一個干凈的 API,而且還支持 TypeScript,從而幫助避免屬性的拼寫錯誤。
服務(wù)端可以通過 HTTP 請求的請求頭和響應(yīng)頭來訪問和修改 cookie。每當瀏覽器向服務(wù)端發(fā)送 HTTP 請求時,它都會使用 cookie 頭將所有相關(guān) cookie 都附加到該站點。請求標頭是一個分號分隔的字符串。
這樣就可以從請求頭中讀取這些 cookie。如果在服務(wù)端使用 Node.js,可以像下面這樣從請求對象中讀取它們,將獲得以分號分隔的 key=value 對:
http.createServer(function (request, response) {
const cookies = request.headers.cookie;
// "cookie1=value1; cookie2=value2"
...
}).listen(8124);
如果想要設(shè)置 cookie,可以在響應(yīng)頭中添加 Set-Cookie 頭,其中 cookie 采用 key=value 的格式,屬性用分號分隔:
response.writeHead(200, {
'Set-Cookie': 'mycookie=test; domain=example.com; Secure'
});
通常我們不會直接編寫 Node.js,而是與 ExpressJS 這樣的 Node.js 框架一起使用。使用 Express 可以更輕松地訪問和修改 cookie。只需添加一個像 cookie-parser 這樣的中間件,就可以通過 req.cookies 以 JavaScript 對象的形式獲得所有的 cookie。還可以使用 Express 內(nèi)置的 res.cookie() 方法來設(shè)置 cookie:
const express = require('express')
const cookieParser = require('cookie-parser')
const app = express()
app.use(cookieParser())
app.get('/', function (req, res) {
console.log('Cookies: ', req.cookies)
// Cookies: { cookie1: 'value1', cookie2: 'value2' }
res.cookie('name', 'tobi', { domain: 'example.com', secure: true })
})
app.listen(8080)
下面來深入了解 cookie 的屬性。除了名稱和值之外,cookie 還具有控制很多方面的屬性,包括安全方面、生命周期以及它們在瀏覽器中的訪問位置和方式等。
Domain 屬性告訴瀏覽器允許哪些主機訪問 cookie。如果未指定,則默認為設(shè)置 cookie 的同一主機。因此,當使用客戶端 JavaScript 訪問 cookie 時,只能訪問與 URL 域相同的 cookie。同樣,只有與 HTTP 請求的域共享相同域的 cookie 可以與請求頭一起發(fā)送到服務(wù)端。
注意,擁有此屬性并不意味著可以為任何域設(shè)置 cookie,因為這顯然會帶來巨大的安全風險。此屬性存在的唯一原因就是減少域的限制并使 cookie 在子域上可訪問。例如,如果當前的域是 abc.xyz.com,并且在設(shè)置 cookie 時如果不指定 Domain 屬性,則默認為 abc.xyz.com,并且 cookie 將僅限于該域。但是,可能希望相同的 cookie 也可用于其他子域,因此可以設(shè)置 Domain=xyz.com 以使其可用于其他子域,如 def.xyz.com 和主域 xyz.com。
此屬性指定訪問 cookie 必須存在的請求 URL 中的路徑。除了將 cookie 限制到域之外,還可以通過路徑來限制它。路徑屬性為 Path=/store 的 cookie 只能在路徑 /store 及其子路徑 /store/cart、/store/gadgets 等上訪問。
該屬性用來設(shè)置 cookie 的過期時間。若設(shè)置其值為一個時間,那么當?shù)竭_此時間后,cookie 就會失效。不設(shè)置的話默認值是 Session,意思是cookie會和session一起失效。當瀏覽器關(guān)閉(不是瀏覽器標簽頁) 后,cookie 就會失效。
除此之外,它還可以通過將過期日期設(shè)置為過去來刪除 cookie。
具有 Secure 屬性的 cookie 僅可以通過安全的 HTTPS 協(xié)議發(fā)送到服務(wù)器,而不會通過 HTTP 協(xié)議。這有助于通過使 cookie 無法通過不安全的連接訪問來防止中間人攻擊。除非網(wǎng)站實用不安全的 HTTP 連接,否則應(yīng)該始終將此屬性與所有 cookie 一起使用。
此屬性使 cookie 只能通過服務(wù)端訪問。因此,只有服務(wù)斷可以通過響應(yīng)頭設(shè)置它們,然后瀏覽器會將它們與每個后續(xù)請求的頭一起發(fā)送到服務(wù)器,并且它們將無法通過客戶端 JavaScript 訪問。
這可以在一定程度上幫助保護帶有敏感信息(如身份驗證 token)的 cookie 免受 XSS 攻擊,因為任何客戶端腳本都無法讀取 cookie。但這并不意味著可以完全免受 XSS 攻擊。因為,如果攻擊者可以在網(wǎng)站上執(zhí)行第三方腳本,那可能無法訪問 cookie,相反,他們可以直接向服務(wù)端執(zhí)行相關(guān)的 API 請求。因此,想象一下用戶訪問了一個頁面,黑客在網(wǎng)站上注入了惡意腳本。他們可以使用該腳本執(zhí)行任何 API,并在他們不知道的情況下代表用戶執(zhí)行操作。
Js Cookie 是一個簡單、輕量級的 JavaScript API,用于處理瀏覽器 cookie。其支持 AMD、CommonJS 和 ES 模塊、沒有依賴關(guān)系、經(jīng)過徹底測試、支持自定義編碼和解碼、通用瀏覽器支持。
安裝:
npm i js-cookie
使用:
// 設(shè)置 Cookie
Cookies.set('cookie-name', 'cookie-value', { expires: 14})
// 讀取 Cookie
Cookies.get('cookie-name')
// 刪除 Cookie
Cookies.remove('cookie-name')
React Cookie 是一個專門用于 React 的 cookie 庫,它繼承了 Universal Cookie 庫的功能。它提供了一組組件和 Hooks,使 React 中的 cookie 處理非常簡單。如果使用的是 React 16.8+ 版本,就可以使用 hooks 來處理 cookie。否則,必須使用其提供的組件。
安裝:
npm i react-cookie
React Cookie 提供了 3 個 Hook,分別是 cookie、setCookie 和 removeCookie。可以使用這些 Hook 來處理 React 應(yīng)用中的 cookie。
const [cookies, setCookie, removeCookie] = useCookies(['cookie-name']);
// 設(shè)置 Cookie
setCookie(name, value, [options]);
// 刪除 Cookie
removeCookie(name, [options])
Cookies 是用于 HTTP cookie 配置的流行 NodeJS 模塊之一。可以輕松地將其與內(nèi)置的 NodeJS HTTP 庫集成或?qū)⑵溆米?Express 中間件。它允許使用 Keygrip 對 cookie 進行簽名以防止篡改、支持延遲 cookie 驗證、不允許通過不安全的套接字發(fā)送安全 cookie、允許其他庫在不知道簽名機制的情況下訪問 cookie。
安裝:
npm install cookies
使用:
const cookie = require('cookie');
cookies = new Cookies( request, response, [ options ] )
// 讀取 cookies
cookies.get( name, [ options ] )
// 設(shè)置 cookies
cookies.set( name, [ value ], [ options ] )
IndexedDB 提供了一個類似 NoSQL 的 key/value 數(shù)據(jù)庫,它可以存儲大量結(jié)構(gòu)化數(shù)據(jù),甚至是文件和 blob。每個域至少有 1GB 的可用空間,并且最多可以達到剩余磁盤空間的 60%。
IndexedDB 于 2011 年首次實現(xiàn),并于 2015 年 1 月成為 W3C 標準,它具有良好的瀏覽器支持:
key/value 數(shù)據(jù)庫意味著存儲的所有數(shù)據(jù)都必須分配給一個 key。它將key 與 value 相關(guān)聯(lián),key 用作該值的唯一標識符,這意味著可以使用該 key 跟蹤該值。如果應(yīng)用需要不斷獲取數(shù)據(jù),key/value 數(shù)據(jù)庫使用非常高效且緊湊的索引結(jié)構(gòu)來快速可靠地通過 key 定位值。使用該 key,不僅可以檢索存儲的值,還可以刪除、更新和替換該值。
在說 IndexedDB 之前,先來看一些相關(guān)術(shù)語:
indexedDB 特點如下:
IndexedDB 使用場景:
不同瀏覽器的 IndexedDB 可能使用不同的名稱??梢允褂靡韵路椒z查 IndexedDB 支持:
const indexedDB =
window.indexedDB ||
window.mozIndexedDB ||
window.webkitIndexedDB ||
window.msIndexedDB ||
window.shimIndexedDB;
if (!indexedDB) {
console.log("不支持 IndexedDB");
}
可以使用 indexedDB.open() 來連接數(shù)據(jù)庫:
const dbOpen = indexedDB.open('performance', 1);
indexedDB.open 的第一個參數(shù)是數(shù)據(jù)庫名稱,第二個參數(shù)是可選的版本整數(shù)。
可以使用以下三個事件處理函數(shù)監(jiān)聽 indexedDB 的連接狀態(tài):
在無法建立 IndexedDB 連接時,將觸發(fā)該事件:
// 連接失敗
dbOpen.onerror = e => {
reject(`IndexedDB error: ${ e.target.errorCode }`);
};
如果在無痕模式、隱私模式下運行瀏覽器,可能不支持 IndexedDB,需要禁用這些模式。
一旦數(shù)據(jù)庫連接打開,就會觸發(fā) onupgradeneeded 事件,該事件可用于創(chuàng)建 object store。
dbOpen.onupgradeneeded = e => {
const db = dbOpen.result;
// 創(chuàng)建 object store
const store = db.createObjectStore("cars", { keyPath: "id" });
// 使用自動遞增的id
// const store = db.createObjectStore('cars', { autoIncrement: true });
// 創(chuàng)建索引
store.createIndex("cars_colour", ["colour"], {
unique: true
});
// 創(chuàng)建復合索引
store.createIndex("colour_and_make", ["colour", "make"], {
unique: false,
});
};
IndexedDB 使用了 object store 的概念,其本質(zhì)上是數(shù)據(jù)集合的名稱??梢栽趩蝹€數(shù)據(jù)庫中創(chuàng)建任意數(shù)量的 object store。keyPath是 IndexedDB 將用來識別對象字段名稱,通常是一個唯一的編號,也可以通過 autoIncrement: true 來自動為 store 設(shè)置唯一遞增的 ID。除了普通的索引,還可以創(chuàng)建復合索引,使用多個關(guān)鍵詞的組合進行查詢。
在連接建立并且所有升級都完成時,將觸發(fā)該事件。上面我們已經(jīng)新建了 schema,接下來就可以在onsuccess 中添加、查詢數(shù)據(jù)。
// 連接成功
dbOpen.onsuccess = () => {
this.db = dbOpen.result;
//1
const transaction = db.transaction("cars", "readwrite");
//2
const store = transaction.objectStore("cars");
const colourIndex = store.index("cars_colour");
const makeModelIndex = store.index("colour_and_make");
//3
store.put({ id: 1, colour: "Red", make: "Toyota" });
store.put({ id: 2, colour: "Red", make: "Kia" });
store.put({ id: 3, colour: "Blue", make: "Honda" });
store.put({ id: 4, colour: "Silver", make: "Subaru" });
//4
const idQuery = store.get(4);
const colourQuery = colourIndex.getAll(["Red"]);
const colourMakeQuery = makeModelIndex.get(["Blue", "Honda"]);
// 5
idQuery.onsuccess = function () {
console.log('idQuery', idQuery.result);
};
colourQuery.onsuccess = function () {
console.log('colourQuery', colourQuery.result);
};
colourMakeQuery.onsuccess = function () {
console.log('colourMakeQuery', colourMakeQuery.result);
};
// 6
transaction.oncomplete = function () {
db.close();
};
};
這里總共有六部分:
運行上面的代碼,就會得到以下結(jié)果:
可以在 Chrome Devtools 中查看:
下面來看看如何更新和刪除數(shù)據(jù)。
const subaru = store.get(4);
subaru.onsuccess= function () {
subaru.result.colour = "Green";
store.put(subaru.result);
}
這會將數(shù)據(jù)庫中 Silver 色的 Subaru 的顏色更新為綠色。
const deleteCar = store.delete(1);
deleteCar.onsuccess = function () {
console.log("Removed");
};
如果不知道 key 并且希望根據(jù)值來刪除,可以這樣:
const redCarKey = colourIndex.getKey(["Red"]);
redCarKey.onsuccess = function () {
const deleteCar = store.delete(redCarKey.result);
deleteCar.onsuccess = function () {
console.log("Removed");
};
};
結(jié)果如下:
可以使用基于 Promise 的 Storage API 檢查 Web Storage、IndexedDB 和 Cache API 的剩余空間。異步 .estimate() 方法返回:
(async () => {
if (!navigator.storage) return;
const storage = await navigator.storage.estimate();
console.log(`可用大小: ${ storage.quota / 1024 } Kb`);
console.log(`已用大小: ${ storage.usage / 1024 } Kb`);
console.log(`已用占比: ${ Math.round((storage.usage / storage.quota) * 100) }%`);
console.log(`剩余大小: ${ Math.floor((storage.quota - storage.usage) / 1024) } Kb`);
})();
Storage API 的瀏覽器兼容性如下:
頁布局對改善網(wǎng)站的外觀非常重要。
請慎重設(shè)計您的網(wǎng)頁布局。
在線實例
使用 <div> 元素的網(wǎng)頁布局
如何使用 <div> 元素添加布局。
使用 <table> 元素的網(wǎng)頁布局
如何使用 <table> 元素添加布局。
網(wǎng)站布局
大多數(shù)網(wǎng)站會把內(nèi)容安排到多個列中(就像雜志或報紙那樣)。
大多數(shù)網(wǎng)站可以使用 <div> 或者 <table> 元素來創(chuàng)建多列。CSS 用于對元素進行定位,或者為頁面創(chuàng)建背景以及色彩豐富的外觀。
雖然我們可以使用HTML table標簽來設(shè)計出漂亮的布局,但是table標簽是不建議作為布局工具使用的 - 表格不是布局工具。 |
HTML 布局 - 使用<div> 元素
div 元素是用于分組 HTML 元素的塊級元素。
下面的例子使用五個 div 元素來創(chuàng)建多列布局:
實例
<!DOCTYPEhtml><html><head><metacharset="utf-8"><title>菜鳥教程(runoob.com)</title></head><body><divid="container"style="width:500px"><divid="header"style="background-color:#FFA500;"><h1style="margin-bottom:0;">主要的網(wǎng)頁標題</h1></div><divid="menu"style="background-color:#FFD700;height:200px;width:100px;float:left;"><b>菜單</b><br>HTML<br>CSS<br>JavaScript</div><divid="content"style="background-color:#EEEEEE;height:200px;width:400px;float:left;">內(nèi)容在這里</div><divid="footer"style="background-color:#FFA500;clear:both;text-align:center;">版權(quán) ? runoob.com</div></div></body></html>
上面的 HTML 代碼會產(chǎn)生如下結(jié)果:
HTML 布局 - 使用表格
使用 HTML <table> 標簽是創(chuàng)建布局的一種簡單的方式。
大多數(shù)站點可以使用 <div> 或者 <table> 元素來創(chuàng)建多列。CSS 用于對元素進行定位,或者為頁面創(chuàng)建背景以及色彩豐富的外觀。
即使可以使用 HTML 表格來創(chuàng)建漂亮的布局,但設(shè)計表格的目的是呈現(xiàn)表格化數(shù)據(jù) - 表格不是布局工具! |
下面的例子使用三行兩列的表格 - 第一和最后一行使用 colspan 屬性來橫跨兩列:
實例
<!DOCTYPEhtml><html><head><metacharset="utf-8"><title>菜鳥教程(runoob.com)</title></head><body><tablewidth="500"border="0"><tr><tdcolspan="2"style="background-color:#FFA500;"><h1>主要的網(wǎng)頁標題</h1></td></tr><tr><tdstyle="background-color:#FFD700;width:100px;"><b>菜單</b><br>HTML<br>CSS<br>JavaScript</td><tdstyle="background-color:#eeeeee;height:200px;width:400px;">內(nèi)容在這里</td></tr><tr><tdcolspan="2"style="background-color:#FFA500;text-align:center;">版權(quán) ? runoob.com</td></tr></table></body></html>
上面的 HTML 代碼會產(chǎn)生以下結(jié)果:
HTML 布局 - 有用的提示
Tip: 使用 CSS 最大的好處是,如果把 CSS 代碼存放到外部樣式表中,那么站點會更易于維護。通過編輯單一的文件,就可以改變所有頁面的布局。如需學習更多有關(guān) CSS 的知識,請訪問我們的CSS 教程。
Tip: 由于創(chuàng)建高級的布局非常耗時,使用模板是一個快速的選項。通過搜索引擎可以找到很多免費的網(wǎng)站模板(您可以使用這些預先構(gòu)建好的網(wǎng)站布局,并優(yōu)化它們)。
HTML 布局標簽
標簽 | 描述 |
---|---|
<div> | 定義文檔區(qū)塊,塊級(block-level) |
<span> | 定義 span,用來組合文檔中的行內(nèi)元素。 |
如您還有不明白的可以在下面與我留言或是與我探討QQ群308855039,我們一起飛!
TML5方興未艾,但也有不少遺憾。下面提了10點希望在HTML6中看到的特性,歡迎評論。
我們可能永遠不會解決與壓縮編解碼器的爭斗,但我們可以與之配合。不同的壓縮算法可能需要更多的工作來實現(xiàn),但是它們提供競爭。能對展現(xiàn)在頁面上的視頻幀提供更多控制的方式會是更好的方案。當前的標準是使用視頻中的一系列幀填充一個矩形。然后提供了一個帶有注釋,字幕和其他內(nèi)容的文本軌道的控制。一些聰明的人已經(jīng)開始將注釋與其他DOM對象同步。但是如果有回調(diào)鉤子和同步機制是不是更好?例如,DOM與視頻混合的能力如何?
照片在屏幕上看起來要漂亮,需要多少像素?這個答案根據(jù)根據(jù)設(shè)備的不同而不同。即使窗口的大小也會改變最小分辨率。但HTML標準
<img>
標簽只能獲得一個SRC,它指向一個可能有太多或太少像素的圖像文件。如果它太多,瀏覽器必須降級圖像才能顯示,這就浪費網(wǎng)絡(luò)帶寬和時間。如果像素太少,效果又太差。更好的HTML協(xié)議應(yīng)該為圖像提出所需的寬度或高度,以便服務(wù)器可以提供最佳分辨率。
標準的HTML瀏覽器使用且只是用JavaScript。但由于某些原因,我們需要用script標簽的type屬性設(shè)定為text/javascript來指定語言類型。從html4開始,type一直就沒有默認值。
HTML4的建議稿覺得有人可能會使用像text/tcl或text/vbscript這樣的類型,但是實際上有沒有人使用這些?微軟已經(jīng)棄用了IE11的text/vbscript,而且近年來Sun在使用tcl。
Google正在慢慢推Dart,但包括Dart的Chromium(Chrome的開發(fā)版)確有一個不祥的警告 :“不要使用Dartium作為主瀏覽器,不要將Dartium分發(fā)給用戶!”說明Google對Dart也不是很有信心。
但在未來,我們可以擁有更強大的可插拔語言。它將為開發(fā)人員增加更多的靈活性和設(shè)計選擇。會不會把互聯(lián)網(wǎng)弄壞?如果有一個穩(wěn)固的開源實現(xiàn),它就可以被所有瀏覽器采用??赡芎茈y讓網(wǎng)站使用可插入語言來為廣泛的受眾提供內(nèi)容 - JavaScript會可以繼續(xù)擁有廣泛的網(wǎng)絡(luò)基礎(chǔ) - 但是對于使用專門語言的更專業(yè)的擴展來說,這可能是一個很好的選擇。
想超越JavaScript的開發(fā)人員可以有另外一個解決方案,就是將其他語言轉(zhuǎn)換為JavaScript。許多開發(fā)人員已經(jīng)使用一些翻譯語言(如CoffeeScript)的預處理器。
杰里米·阿什肯納斯(Jeremy Ashkenas) 列出來了可以編譯成JavaScript的語言列表,范圍很廣。Lisp,Python,Ruby,Erlang,Scala - 列表還在繼續(xù)擴大。
這樣的提案將會付出代價。當一種語言被交叉編譯成JavaScript時,通常會在同一時間進行細化,生成一個更小的更容易通過互聯(lián)網(wǎng)傳輸?shù)陌姹?。在部署過程中執(zhí)行此操作比在每個人的瀏覽器上執(zhí)行的效率要高得多。
但是,縮小的版本有其缺點。開放一直是網(wǎng)絡(luò)的巨大優(yōu)勢之一。我們能夠通過閱讀通常仍然以人類可讀的形式寫的JavaScript代碼來學習和調(diào)試。交叉編譯和縮小的代碼對于其他人是無價值的。它正在慢慢打破Web的開放性。
在瀏覽器中執(zhí)行此轉(zhuǎn)換還有其他優(yōu)點。每臺機器都有不同,轉(zhuǎn)換過程需要利用到RAM大小、視頻卡庫等知識。當前版本的HTML假定采用JavaScript的一般版本,這使得為本地機器優(yōu)化代碼變得更難。
JavaScript編程的世界已經(jīng)被jQuery以及其他標準庫改造了。然而,幾乎每個網(wǎng)站仍然要加載自己加載某個版本的副本。在加載jQuery時浪費的能量可能足以照亮一個小國家,治愈癌癥或兩者兼而有之。
一些網(wǎng)站使用像Google或Yahoo這樣的公司托管的標準緩存版本,這樣可以節(jié)省帶寬,但下一個HTML標準應(yīng)該比這更好。如果大量設(shè)計人員同意,則可以使用瀏覽器進行分發(fā)。這將節(jié)省更多時間再次刷新jQuery的緩存版本。
瀏覽器已經(jīng)可以共享位置信息。期待更多國家加入。人們通常希望在自己設(shè)備的聯(lián)系信息庫里面放入電子郵件地址或電話號碼?,F(xiàn)在他們必須剪切和粘貼。為什么不讓JavaScript挖掘并保存所有的剪切和粘貼?這對移動設(shè)備來說是非常棒的。在交互上可以提供細粒度的控制,允許人們來自某些域的代碼可以自動訪問到聯(lián)系信息,而其他域不行。
在網(wǎng)絡(luò)攝像頭和手機的多攝像頭提供的設(shè)備基礎(chǔ)上,用戶與瀏覽器交互的場景少不了鏡頭和麥克風。W3C已經(jīng)在探索一種向表單添加照片或視頻捕獲的方法 。一些瀏覽器已經(jīng)支持自己的版本,如
webkitGetUserMedia
。很容易想到更多。表單元素還可以訪問存儲在設(shè)備中的存儲空間,并且該設(shè)備可以更好地控制攝像機和捕獲速率。這將讓網(wǎng)站與專門的應(yīng)用程序競爭。
鑒于構(gòu)建可信硬件是多么困難的事情,因此我們可能會提供很多硬性和快速認證的方式。而瀏覽器可以為此提供更多的功能。瀏覽器可以使用嵌入式Key進行簽名,而不是Cookie。這些可以以硬化的芯片存儲在設(shè)備之外,以防止人們提取密鑰。向瀏覽器添加API將允許網(wǎng)站要求更好的數(shù)字簽名。如果把太多的信任放在其中,這可能是危險的,但這將是cookie和會話身份驗證的一個步驟。
文章底部的注釋部分只是我們?nèi)绾巫⑨屛恼碌拈_始,但是一個標準的結(jié)構(gòu)可以添加與段落、句子、甚至單詞相關(guān)的注釋。復雜的版本甚至可以允許對視頻內(nèi)的圖像或某個時間點進行注釋。有些網(wǎng)站正在開始提供這些功能,但在標準化API方面會使所有網(wǎng)站和瀏覽器都以相同的方式處理基本注釋。W3C有一個研究該領(lǐng)域并提供基本標準的小組。
HTML標簽區(qū)分標題,段落和頁腳,但還不夠多。為什么不創(chuàng)建一個標準的方法來指定其他常見的細節(jié),例如地址或電話號碼的部分?當然,用于描繪電子郵件地址的標準標簽可以使垃圾郵件發(fā)送者的生活變得更輕松,但標準的一組標簽可以加速網(wǎng)頁抓取工具和搜索引擎,這將有利于我們所有人。W3C一直在探索微格式來標記數(shù)據(jù),并曾經(jīng)認為它們是HTML5的一部分,盡管它們不是。我們可以為地點,時間,日期,出售物品,參考書目以及所有標準數(shù)據(jù)使用更全面的標記。
*請認真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。