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
一篇《WordPress 網站全方位速度優化:主機篇》講的是關于WordPress 網站所在主機的設置,這次我們來講網站內部臃腫導致加載變慢。
還是上一篇那個例子,一個網站首頁總大小,如果從3MB下降到1MB。即便是1M 帶寬的主機,加載時間也會從25秒下降到8秒,也是很可觀的。但是要給網站減肥可不是一件容易的事兒,我盡可能的詳細介紹:
訪客的瀏覽器從遠程主機上抓取網頁,先抓取首頁的HTML 文件,然后再從 HTML 文件里提取出 CSS、JS、圖片、視頻等文件分別加載,有的 JS 和 CSS 里還會加載更多的 CSS、圖片、視頻。
有一個工具可以看到網頁加載過程,比如:文件數量、加載順序、每個元素的響應時間、明細等信息。谷歌Chrome瀏覽器自帶的“檢查”工具,火狐 Firefox 的FireBug 工具都可以完成以上的工作。此外360瀏覽器,Safari 瀏覽器,IE 新版本都集成了這個功能。(如圖:minify是個 css 文件,大小426KB)
如果是咱們自己寫的 HTML、CSS、JS 文件,可以輕易瘦身,自己熟悉代碼哪里能優化,但 WordPress 主題的 HTML、CSS、JS 我們是無能為力,只能通過Gzip壓縮解決。(如下圖,經過 Gzip 壓縮,minify 文件 從426KB變成了57KB)
Gzip是服務器或者虛機提供的一種組件服務,簡單地說:Gzip開啟后,從主機到訪客之間傳送的文件會被壓縮處理,這樣就會減小通過網絡傳輸的數據量,提高瀏覽的速度。比如一個首頁150KB,但是經過壓縮真實傳輸大小是25KB。(如下圖)
Gzip具體使用方法:主機不同調用方法也不同,有的是寫.htaccess,有的是安裝個插件,不管是那種,可以到 Chinaz 站長工具里面檢測(網址:http://tool.chinaz.com/Gzips/)。比如小紅公司的網站:www.jianzhan1.cn的 html 文件是150KB,Gzip 壓縮之后變成26KB,然后在火狐里用 FireBug 檢查首頁果然是25.9KB。雙重驗證說明 Gzip 生效了。此外Gzip 對 CSS 這類文本類的文件也會壓縮,比如有個CSS 文件是426KB,壓縮之后是57KB。
上圖為 ChinaZ 網站檢查結果,我們也可以從其他網站看出Gzip 是否生效,另外也可以用瀏覽器檢查工具檢查 header 是否有 Gzip。
通常Gzip只會壓縮 HTML 和 TXT 之類的文本文件,不建議用它來壓縮圖片,因為這樣會增加服務器 CPU 的負擔,還會增加圖片的體積,具體原因大家百度一下。后面會說給圖片瘦身。
網站上用的圖片大概這么幾種:1 頭部Slider的背景圖和前景圖。2 產品和案例的圖片。3 其他裝飾圖片。
不論什么圖片,第一步先看寬高尺寸,大小夠用就好,切忌貪大,尺寸越大,容量越大,下載越慢,特別是產品圖,有的同學直接上傳2000px寬的2MB 圖片。(很多同學不了解常識)
此外圖片還分透明圖片和不透明圖片:透明圖比如說去掉背景的產品圖,還有特殊字體的文字也需要做成透明圖片,可以把他們放到背景圖上。不透明的圖片比如說背景圖片和產品展示圖等。
先說透明圖片,常用PNG格式,當然 PNG 圖片也有透明和不透明之分,還有8位和24位的區別。總而言之,透明圖片我們用 PNG,但是 PNG 圖片很大,解決辦法是,到 TingPNG 網站優化壓縮,網址:https://tinypng.com/,通常可以得到比較好的壓縮比,圖片質量幾乎沒變化。因為這種壓縮是在線壓縮,需要上傳和下載,有點麻煩,但是一次麻煩終身受益。
再說經常用到的JPG 圖片,通常我們直接在PhotoShop 里修改,裁切大小,另存為 web 格式壓縮,jpg 質量60左右。這個大家都會,我再分享個秘籍:“WP Smush”,這是一個 WordPress 插件,每次上傳圖片時會自動在線壓縮,壓縮比很高,質量損失很小,速度稍慢,絕對值得,一般人我不告訴他。
PNG 透明圖和 JPG 圖的究極壓縮方法都是在線工具,小而精 小而美,這是他們的獨門秘籍,不會輕易外傳,在線提供服務也是一種保護。
網站上用的視頻通常有兩種方式,一種是托管在視頻網站,比如優酷,我們在自己網站上引用優酷視頻的地址,通常會有優酷的標志或者廣告。另外一種方式是把視頻存放在本地主機上,我們主要說這種。這種視頻往往容量很大,用戶下載慢,使用時一定要注意。下面說說如何優化:
以小紅建站公司網站首頁為例,第一屏有個背景視頻,1000kb碼率的MP4格式,36秒,5.4MB,嚴重影響打開速度。壓縮成384kb碼率的webm格式視頻后,變成1.4MB,但畫質很粗糙,顯得很low。最后把視頻剪輯成22秒,壓縮成512kb碼率的webm是1.4MB,質量好些,在視頻上覆蓋一層灰色,遮住粗糙的視頻,整體顯得高檔。
這樣做還有個問題,IE11瀏覽器 和 微軟Edge瀏覽器 不支持webm 格式的視頻,這需要額外增加mp4格式的視頻給微軟的瀏覽器。訪客瀏覽器如果是支持webm視頻的谷歌等瀏覽器,網站直接給他看webm視頻;訪客如果是 IE 瀏覽器,網站會給他看 MP4視頻。
同樣22秒 512k的碼率MP4也是1.4MB,但是質量差很多,不得不提升768k碼率,視頻質量和webm的512k碼率類似。吐槽Edge瀏覽器,播放MP4的質量好差,同樣一段視頻比IE11差不少,馬賽克嚴重。
以上是對站內HTML,CSS,JS,圖片,視頻的優化壓縮,木桶理論的兩塊木板“主機提速”和“站內減肥”介紹完了,下集將是最后一集,講谷歌這個“外患”,還有外鏈,緩存,調用系統中文字體微軟雅黑,。
注:相關網站建設技巧閱讀請移步到建站教程頻道。
動菜單通常是指一個下拉框的選項值發生改變后,另一個下拉框的選項值會發生對應的變化。在 HTML 頁面中,可以使用 JavaScript 結合 HTML DOM 來實現這一功能。下面我來舉一個例子。
假設我們有三個下拉框,分別是“省份”、“城市”和“區縣”。當“省份”下拉框的選項值發生改變時,我們需要動態更新“城市”下拉框的選項值,并且根據“城市”的選項值動態更新“區縣”下拉框的選項值。具體實現步驟如下:
1 首先在 HTML 文件中定義三個下拉框,并分別給它們一個唯一的 ID,如下所示:
<label>省份:</label>
<select id="province"></select>
<label>城市:</label>
<select id="city"></select>
<label>區縣:</label>
<select id="district"></select>
2 在 JavaScript 中定義三個函數,分別用于更新“城市”、“區縣”下拉框的選項值,以及初始化頁面時的默認值:
// 更新城市下拉框內容
function updateCity() {
var provinceSelect = document.getElementById("province");
var citySelect = document.getElementById("city");
citySelect.innerHTML = ""; // 清空城市下拉框內容
// 根據選中的省份,獲取該省份對應的城市列表
var provinceName = provinceSelect.value;
var cityList = getCityList(provinceName);
// 根據城市列表,動態生成城市下拉框的選項
for (var i = 0; i < cityList.length; i++) {
var option = document.createElement("option");
option.text = cityList[i];
citySelect.add(option);
}
// 觸發區縣下拉框更新
updateDistrict();
}
// 更新區縣下拉框內容
function updateDistrict() {
var citySelect = document.getElementById("city");
var districtSelect = document.getElementById("district");
districtSelect.innerHTML = ""; // 清空區縣下拉框內容
// 根據選中的城市,獲取該城市對應的區縣列表
var cityName = citySelect.value;
var districtList = getDistrictList(cityName);
// 根據區縣列表,動態生成區縣下拉框的選項
for (var i = 0; i < districtList.length; i++) {
var option = document.createElement("option");
option.text = districtList[i];
districtSelect.add(option);
}
}
// 初始化頁面
function initPage() {
var provinceSelect = document.getElementById("province");
var citySelect = document.getElementById("city");
var districtSelect = document.getElementById("district");
// 根據省份列表,動態生成省份下拉框的選項
for (var i = 0; i < provinceList.length; i++) {
var option = document.createElement("option");
option.text = provinceList[i];
provinceSelect.add(option);
}
// 觸發城市下拉框更新
updateCity();
}
現在我們已經完成了省份和城市兩個下拉框的聯動效果,接下來我們需要再次綁定城市下拉框的change事件,以實現城市與區縣下拉框的聯動。
首先,我們需要在HTML中添加第三個下拉框,用于選擇區縣:
<select id="county"></select>
然后,我們需要更新updateCity和initPage兩個函數,使其能夠更新城市和區縣兩個下拉框:
function updateCity() {
var province = document.getElementById('province').value;
var cityOptions = '';
for (var i = 0; i < cities[province].length; i++) {
cityOptions += '<option value="' + cities[province][i] + '">' + cities[province][i] + '</option>';
}
document.getElementById('city').innerHTML = cityOptions;
// 清空區縣下拉框
document.getElementById('county').innerHTML = '<option value="">--請選擇--</option>';
}
function updateCounty() {
var province = document.getElementById('province').value;
var city = document.getElementById('city').value;
var countyOptions = '';
for (var i = 0; i < counties[province][city].length; i++) {
countyOptions += '<option value="' + counties[province][city][i] + '">' + counties[province][city][i] + '</option>';
}
document.getElementById('county').innerHTML = countyOptions;
}
function initPage() {
// 初始化省份下拉框
var provinceOptions = '<option value="">--請選擇--</option>';
for (var province in cities) {
provinceOptions += '<option value="' + province + '">' + province + '</option>';
}
document.getElementById('province').innerHTML = provinceOptions;
// 綁定省份下拉框的change事件
document.getElementById('province').addEventListener('change', updateCity);
// 初始化城市下拉框
updateCity();
// 綁定城市下拉框的change事件
document.getElementById('city').addEventListener('change', updateCounty);
// 初始化區縣下拉框
updateCounty();
}
在updateCity函數中,我們添加了清空區縣下拉框的代碼,以確保每次更改城市時,區縣下拉框都會被清空。
在updateCounty函數中,我們根據選擇的省份和城市,動態生成區縣下拉框的選項。
在initPage函數中,我們綁定了城市下拉框的change事件,并調用updateCounty函數初始化區縣下拉框的選項。
最后,我們需要在JavaScript代碼中定義counties變量,以存儲每個城市對應的區縣信息:
var counties = {
"北京市": {
"市轄區": ["東城區", "西城區", "崇文區", "宣武區", "朝陽區", "豐臺區", "石景山區", "海淀區", "門頭溝區", "房山區", "通州區", "順義區", "昌平區", "大興區", "懷柔區", "平谷區"],
"縣": ["密云縣", "延慶縣"]
},
"上海市": {
"市轄區": ["黃浦區", "盧灣區", "徐匯區", "長寧區", "靜安區", "普陀區", "閘北區", "虹口區", "楊浦區", "閔行區", "寶山區", "嘉定區", "浦東新區", "金山區", "松江區", "青浦區", "南匯區", "奉賢區"],
"縣": ["崇明縣"]
},
// 省略部分數據...
};
接下來是第三個函數setDefaultValue(),用于初始化頁面時設置默認值。在這個函數中,我們先根據省份的默認值設置省份下拉框的選中項,然后根據省份和城市的默認值,從數據中獲取相應的區縣數據,并設置區縣下拉框的選項。
function setDefaultValue() {
// 設置省份下拉框默認選中項
var provinceSelect = document.getElementById("province");
for (var i = 0; i < provinceSelect.options.length; i++) {
if (provinceSelect.options[i].value === defaultProvince) {
provinceSelect.selectedIndex = i;
break;
}
}
// 根據省份和城市設置區縣下拉框選項
var citySelect = document.getElementById("city");
var districtSelect = document.getElementById("district");
var districtData = data[defaultProvince][defaultCity];
districtSelect.options.length = 0; // 清空區縣下拉框
for (var i = 0; i < districtData.length; i++) {
var option = new Option(districtData[i], districtData[i]);
if (districtData[i] === defaultDistrict) {
option.selected = true; // 設置默認選中項
}
districtSelect.options.add(option);
}
}
在這個函數中,我們首先獲取省份下拉框的DOM元素,并通過循環找到選中項為默認省份的選項,并設置為選中狀態。然后獲取城市和區縣的DOM元素,并從數據中獲取對應的區縣數據。最后根據區縣數據動態創建選項,并設置默認選中項。注意,在設置區縣下拉框的選項時,我們先要將下拉框的長度設為0,以清空之前的選項。同時,我們還需要為新創建的選項設置selected屬性,以設置默認選中項。
以上就是一個簡單的基于JavaScript和HTML DOM實現聯動菜單的示例,可以根據具體的業務需求進行擴展和修改。
者開始學習Javascript的時候,對模塊不太懂,不知道怎么導入模塊,導出模塊,就胡亂一通試
比如 import xx from 'test.js' 不起作用,就加個括號 import {xx} from 'test.js'
反正總是靠蒙,總有一種寫法是對的,其實還是沒有理解,還是不懂
尤其是在當初寫 www.helloworld.net 網站的時候,一遇到這種問題,就懵逼了,尤其是引入第三方庫的時候
這種情況下更多,此篇文章也是為了怕以后忘記,自查用的,也希望能幫助更多的朋友,此篇文章只是針對ES6的模塊相關知識
我們知道,JS 模塊導入導出,使用 import , export 這兩個關鍵字
也就是說使用 export 導出一個模塊之后,其它文件就可以使用 import 導入相應的模塊了
下面我們具體看看, import 和 export 到底怎么用?怎么導出模塊(比如變量,函數,類,對象等)
//a.js 導出一個變量,語法如下
export var site = "www.helloworld.net"
//b.js 中使用import 導入上面的變量
import { site } from "/.a.js" //路徑根據你的實際情況填寫
console.log(site) //輸出: www.helloworld.net
上面的例子是導出單個變量,那么如何導出多個變量呢
//a.js 中定義兩個變量,并導出
var siteUrl="www.helloworld.net"
var siteName="helloworld開發者社區"
//將上面的變量導出
export { siteUrl ,siteName }
// b.js 中使用這兩個變量
import { siteUrl , siteName } from "/.a.js" //路徑根據你的實際情況填寫
console.log(siteUrl) //輸出: www.helloworld.net
console.log(siteName) //輸出: helloworld開發者社區
導出函數和導出變量一樣,需要添加{ }
//a.js 中定義并導出一個函數
function sum(a, b) {
return a + b
}
//將函數sum導出
export { sum }
//b.js 中導入函數并使用
import { sum } from "/.a.js" //路徑根據你的實際情況填寫
console.log( sum(4,6) ) //輸出: 10
js中一切皆對象,所以對象一定是可以導出的,并且有兩種寫法
使用 export default 關鍵字導出,如下
//a.js 中,定義對象并導出, 注意,使用export default 這兩個關鍵字導出一個對象
export default {
siteUrl:'www.helloworld.net',
siteName:'helloworld開發者社區'
}
//b.js 中導入并使用
import obj from './a.js' //路徑根據你的實際情況填寫
console.log(obj.siteUrl) //輸出:www.helloworld.net
console.log(obj.siteName) //輸出:helloworld開發者社區
同樣是使用export default 關鍵字,如下
//a.js 中定義對象,并在最后導出
var obj = {
siteUrl:'www.helloworld.net',
siteName:'helloworld開發者社區'
}
export default obj //導出對象obj
//b.js 中導入并使用
import obj from './a.js' //路徑根據你的實際情況填寫
console.log(obj.siteUrl) //輸出:www.helloworld.net
console.log(obj.siteName) //輸出:helloworld開發者社區
導出類與上面的導出對象類似,同樣是用 export default 關鍵字,同樣有兩種寫法
//a.js 中定義一個類并直接導出
export default class Person {
//類的屬性
site = "www.helloworld.net"
//類的方法
show(){
console.log(this.site)
}
}
//b.js 中導入并使用
//導入類
import Person from './a.js'
//創建類的一個對象person
let person = new Person()
//調用類的方法
person.show() //輸出:www.helloworld.net
//a.js 中定義一個類,最后導出
class Person {
//類的屬性
site = "www.helloworld.net"
//類的方法
show(){
console.log(this.site)
}
}
//導出這個類
export default Person
//b.js 中導入并使用
//導入類
import Person from './a.js'
//創建類的一個對象person
let person = new Person()
//調用類的方法
person.show() //輸出:www.helloworld.net
下面我們簡單總結一下
export與export default的區別
對于 import ,export , export default ,他們的用法上面的例子已經很詳細的列出了,忘記的時候,可以當作參考看看
最重要的還是要明白為什么要這么寫,實在不明白記住就行了。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。