沐鳴平台網站_巧用CSS3的calc()寬度計算做響應模式布局

calc()從字面我們可以把他理解為一個函數function。其實calc是英文單詞calculate(計算)的縮寫,是css3的一個新增的功能,用來指定元素的長度。比如說,你可以使用calc()給元素的border、margin、pading、font-size和width等屬性設置動態值。為何說是動態值呢?因為我們使用的表達式來得到的值。不過calc()最大的好處就是用在流體布局上,可以通過calc()計算得到元素的寬度。

calc()能做什麼?
calc()能讓你給元素的做計算,你可以給一個div元素,使用百分比、em、px和rem單位值計算出其寬度或者高度,比如說“width:calc(50% + 2em)”,這樣一來你就不用考慮元素div的寬度值到底是多少,而把這個煩人的任務交由瀏覽器去計算。

calc()語法
calc()語法非常簡單,就像我們小時候學加 (+)、減(-)、乘(*)、除(/)一樣,使用數學表達式來表示:

width: calc(expression);

其中”expression”是一個表達式,用來計算長度的表達式。

calc()的運算規則
calc()使用通用的數學運算規則,但是也提供更智能的功能:

  1. 使用“+”、“-”、“*” 和 “/”四則運算;
  2. 可以使用百分比、px、em、rem等單位;
  3. 可以混合使用各種單位進行計算;
  4. 表達式中有“+”和“-”時,其前後必須要有空格,如”widht: calc(12%+5em)”這種沒有空格的寫法是錯誤的;
  5. 表達式中有“*”和“/”時,其前後可以沒有空格,但建議留有空格。

瀏覽器的兼容性

我們來個例子,我們做一個三列並排的模塊,寬度按百分比、有padding值、有border值、還有margin-right,而且這三個值是px,

li{
float:left;

width:33.3333%;
height:50px;

padding:10px;
margin-right:10px;

background:#FF6666;
border:5px solid #DAC8A7;
}

效果圖:

它是不會好好並列的,在這種情況下就不好算了,就算算出來也有那麼一點誤差,不是嗎?現在我們就用到了calc(),

li{
float:left;

//width:33.3333%;
height:50px;

padding:10px;
margin-right:15px;

background:#FF6666;
border:5px solid #DAC8A7;

width:calc(33.3333% - (10px + 5px) * 2 - 15px )

}

意思是(width-(padding+border)*2-margin)
現在可以並排了

好了,到這就告一段絡了,再稍微優化一下左右邊15px的空距,讓兩邊都挨邊。就在父級上加個margin-right:-15px,OK 搞定,

現在拿這個去做響應模式應該很方便了

站長推薦

1.雲服務推薦: 國內主流雲服務商,各類雲產品的最新活動,優惠券領取。地址:阿里雲騰訊雲華為雲

2.廣告聯盟: 整理了目前主流的廣告聯盟平台,如果你有流量,可以作為參考選擇適合你的平台點擊進入

鏈接: http://www.fly63.com/article/detial/10019

沐鳴怎麼當代理?_網頁打印css print

最近做表單打印,遂整理了一些打印相關的內容。

說到網頁打印,首先想到的便是@media查詢(即網頁css),通過使用媒體類型print即可解決實際應用的大多數問題,比如實現只打印網頁的某部分內容,調整字體大小、修改布局等使打印出來的紙質文件更簡潔明了。代碼如下:

@media print{

    /*隱藏不打印的元素*/
    .no-print{
        display:none;
    }
    /*其他打印樣式*/
}

但是,就打印表單來說,僅解決上述問題是不夠的,我們無法忍受表單存在打印分頁時內容被截斷、分頁显示頂部沒有留白等問題。那麼如何解決這些問題呢?這就要使用到css打印樣式了,即@page,用來指定頁面盒子的各個方面。

eg1:尺寸、頁邊距設置

@page{
     size: 5.5in 8.5in;       
     margin: 30px;
}

注:這裏除了可以用長度值聲明尺寸,還可使用紙質尺寸關鍵字”A4″或“legal”;亦可通過關鍵字指定頁面方向“portrait”、“landscape”,默認為portrait垂直方向。當margin設置不起作用時檢查打印機是否邊距是否設置了默認以外的值。

eg2:設置第一頁、奇數頁或偶數頁樣式(以首頁為例)

@page :first { 

    /*首頁設置*/

}

注:left、right分別為偶數頁、奇數頁選擇器。

eg3:避免表格斷開

@page{
    table{
        page-break-after: avoid;
    }  
}

注:page-break-after對tr、td不起作用所以當以整體出現的時候要在同一個table中。

eg4:避免某行文字斷裂

@page{
    table{
        page-break-inside: avoid;
    }  
}

站長推薦

1.雲服務推薦: 國內主流雲服務商,各類雲產品的最新活動,優惠券領取。地址:阿里雲騰訊雲華為雲

2.廣告聯盟: 整理了目前主流的廣告聯盟平台,如果你有流量,可以作為參考選擇適合你的平台點擊進入

鏈接: http://www.fly63.com/article/detial/10017

沐鳴娛樂業務:_try..catch 不能捕獲的錯誤有哪些?注意事項又有哪些?

今天的內容中,我們來學習一下使用try、catch、finally和throw進行錯誤處理。我們還會講一下 js 中內置的錯誤對象(Error, SyntaxError, ReferenceError等)以及如何定義自定義錯誤。

1.使用 try..catch..finally..throw

在 js 中處理錯誤,我們主要使用try、catch、finally和throw關鍵字。

  • try塊包含我們需要檢查的代碼
  • 關鍵字throw用於拋出自定義錯誤
  • catch塊處理捕獲的錯誤
  • finally 塊是最終結果無論如何,都會執行的一個塊,可以在這個塊裏面做一些需要善後的事情

1.1 try

每個try塊必須與至少一個catch或finally塊,否則會拋出SyntaxError錯誤。

我們單獨使用try塊進行驗證:

try {
  throw new Error('Error while executing the code');
}
ⓧ Uncaught SyntaxError: Missing catch or finally after try

1.2 try..catch

建議將try與catch塊一起使用,它可以優雅地處理try塊拋出的錯誤。

try {
  throw new Error('Error while executing the code');
} catch (err) {
  console.error(err.message);
}
Error while executing the code

1.2.1 try..catch 與 無效代碼

try..catch 無法捕獲無效的 JS 代碼,例如try塊中的以下代碼在語法上是錯誤的,但它不會被catch塊捕獲。

try {
  ~!$%^&*
} catch(err) {
  console.log("這裏不會被執行");
}
  Uncaught SyntaxError: Invalid or unexpected token

1.2.2 try..catch 與 異步代碼

同樣,try..catch無法捕獲在異步代碼中引發的異常,例如setTimeout:

try {
  setTimeout(function() {
    noSuchvariable;   // undefined variable
  }, 1000);
} catch (err) {
  console.log("這裏不會被執行");
}

未捕獲的ReferenceError將在1秒后引發:

Uncaught ReferenceError: noSuchVariable is not defined

所以 ,我們應該在異步代碼內部使用 try..catch 來處理錯誤:

setTimeout(function() {
  try {
    noSuchVariable;
  } catch(err) {
    console.log("error is caught here!");
  }
}, 1000);

1.2.3 嵌套 try..catch

我們還可以使用嵌套的try和catch塊向上拋出錯誤,如下所示:

try {
  try {
    throw new Error('Error while executing the inner code');
  } catch (err) {
    throw err;
  }
} catch (err) {
  console.log("Error caught by outer block:");
  console.error(err.message);
}
Error caught by outer block:
 ⓧ Error while executing the code

1.3 try..finally

不建議僅使用 try..finally 而沒有 catch 塊,看看下面會發生什麼:

try {
  throw new Error('Error while executing the code');
} finally {
  console.log('finally');
}
finally
 ⓧ Uncaught Error: Error while executing the code

這裏注意兩件事:

  • 即使從try塊拋出錯誤后,也會執行finally塊
  • 如果沒有catch塊,錯誤將不能被優雅地處理,從而導致未捕獲的錯誤

1.4 try..catch..finally

建議使用try…catch塊和可選的finally塊。

try {
  console.log("Start of try block");
  throw new Error('Error while executing the code');
  console.log("End of try block -- never reached");
} catch (err) {
  console.error(err.message);
} finally {
  console.log('Finally block always run');
}
console.log("Code execution outside try-catch-finally block continue..");
Start of try block
 ⓧ Error while executing the code
Finally block always run
Code execution outside try-catch-finally block continue..

這裏還要注意兩件事:

  • 在try塊中拋出錯誤后往後的代碼不會被執行了
  • 即使在try塊拋出錯誤之後,finally塊仍然執行

finally塊通常用於清理資源或關閉流,如下所示:

try {
  openFile(file);
  readFile(file);
} catch (err) {
  console.error(err.message);
} finally {
  closeFile(file);
}

1.5 throw

throw語句用於引發異常。

throw <expression>
// throw primitives and functions
throw "Error404";
throw 42;
throw true;
throw {toString: function() { return "I'm an object!"; } };

// throw error object
throw new Error('Error while executing the code');
throw new SyntaxError('Something is wrong with the syntax');
throw new ReferenceError('Oops..Wrong reference');

// throw custom error object
function ValidationError(message) {
  this.message = message;
  this.name = 'ValidationError';
}
throw new ValidationError('Value too high');

2. 異步代碼中的錯誤處理

對於異步代碼的錯誤處理可以Promise和async await。

2.1 Promise 中的 then..catch

我們可以使用then()和catch()鏈接多個 Promises,以處理鏈中單個 Promise 的錯誤,如下所示:

Promise.resolve(1)
  .then(res => {
      console.log(res);  // 打印 '1'

      throw new Error('something went wrong');  // throw error

      return Promise.resolve(2);  // 這裏不會被執行
  })
  .then(res => {
      // 這裏也不會執行,因為錯誤還沒有被處理
      console.log(res);    
  })
  .catch(err => {
      console.error(err.message);  // 打印 'something went wrong'
      return Promise.resolve(3);
  })
  .then(res => {
      console.log(res);  // 打印 '3'
  })
  .catch(err => {
      // 這裏不會被執行
      console.error(err);
  })

我們來看一個更實際的示例,其中我們使用fetch調用API,該 API 返回一個promise對象,我們使用catch塊優雅地處理 API 失敗。

function handleErrors(response) {
    if (!response.ok) {
        throw Error(response.statusText);
    }
    return response;
}

fetch("http://httpstat.us/500")
    .then(handleErrors)
    .then(response => console.log("ok"))
    .catch(error => console.log("Caught", error));
Caught Error: Internal Server Error
    at handleErrors (<anonymous>:3:15)

2.2 try..catch 和 async await

在 async await 中 使用 try..catch 比較容易:

(async function() {
    try {
        await fetch("http://httpstat.us/500");
    } catch (err) {
        console.error(err.message);
    }
})();

讓我們看同一示例,其中我們使用fetch調用API,該API返回一個promise對象, 我們使用try..catch塊優雅地處理API失敗。

function handleErrors(response) {
    if (!response.ok) {
        throw Error(response.statusText);
    }
}

(async function() {
    try {
      let response = await fetch("http://httpstat.us/500");
      handleErrors(response);
      let data = await response.json();
      return data;
    } catch (error) {
        console.log("Caught", error)
    }
})();
Caught Error: Internal Server Error
    at handleErrors (<anonymous>:3:15)
    at <anonymous>:11:7

3. JS 中的內置錯誤

3.1 Error

JavaScript 有內置的錯誤對象,它通常由try塊拋出,並在catch塊中捕獲,Error 對象包含以下屬性:

  • name:是錯誤的名稱,例如 “Error”, “SyntaxError”, “ReferenceError” 等。
  • message:有關錯誤詳細信息的消息。
  • stack:是用於調試目的的錯誤的堆棧跟蹤。

我們創建一個Error 對象,並查看它的名稱和消息屬性:

const err = new Error('Error while executing the code');

console.log("name:", err.name);
console.log("message:", err.message);
console.log("stack:", err.stack);
name: Error
message: Error while executing the code
stack: Error: Error while executing the code
    at <anonymous>:1:13

JavaScript 有以下內置錯誤,這些錯誤是從 Error 對象繼承而來的

3.2 EvalError

EvalError 表示關於全局eval()函數的錯誤,這個異常不再由 JS 拋出,它的存在是為了向後兼容。

3.3 RangeError

當值超出範圍時,將引發RangeError。

 [].length = -1
ⓧ Uncaught RangeError: Invalid array length

3.4 ReferenceError

當引用一個不存在的變量時,將引發 ReferenceError

 x = x + 1;
 Uncaught ReferenceError: x is not defined

3.5 SyntaxError

當你在 JS 代碼中使用任何錯誤的語法時,都會引發SyntaxError。

 function() { return 'Hi!' }
ⓧ Uncaught SyntaxError: Function statements require a function name  1 = 1 ⓧ Uncaught SyntaxError: Invalid left-hand side in assignment  JSON.parse("{ x }"); ⓧ Uncaught SyntaxError: Unexpected token x in JSON at position 2

3.6 TypeError

如果該值不是預期的類型,則拋出TypeError。

 1();
 Uncaught TypeError: 1 is not a function

 null.name;
 Uncaught TypeError: Cannot read property 'name' of null

3.7 URIError

如果以錯誤的方式使用全局 URI 方法,則會拋出URIError。

 decodeURI("%%%");
ⓧ Uncaught URIError: URI malformed

4. 定義並拋出自定義錯誤

我們也可以用這種方式定義自定義錯誤。

class CustomError extends Error {
  constructor(message) {
    super(message);
    this.name = "CustomError";
  } 
};

const err = new CustomError('Custom error while executing the code');

console.log("name:", err.name);
console.log("message:", err.message);
name: CustomError
message: Custom error while executing the code

我們還可以進一步增強CustomError對象以包含錯誤代碼

class CustomError extends Error {
  constructor(message, code) {
    super(message);
    this.name = "CustomError";
    this.code = code;
  } 
};

const err = new CustomError('Custom error while executing the code', "ERROR_CODE");

console.log("name:", err.name);
console.log("message:", err.message);
console.log("code:", err.code);
name: CustomError
message: Custom error while executing the code
code: ERROR_CODE

在try..catch塊中使用它:

try{
  try {
    null.name;
  }catch(err){
    throw new CustomError(err.message, err.name);  //message, code
  }
}catch(err){
  console.log(err.name, err.code, err.message);
}

CustomError TypeError Cannot read property ‘name’ of null

原文:https://codings.com/

站長推薦

1.雲服務推薦: 國內主流雲服務商,各類雲產品的最新活動,優惠券領取。地址:阿里雲騰訊雲華為雲

2.廣告聯盟: 整理了目前主流的廣告聯盟平台,如果你有流量,可以作為參考選擇適合你的平台點擊進入

鏈接: http://www.fly63.com/article/detial/10054

沐鳴娛樂業務:_Css幾種水平垂直居中的方式的利弊

css 中實現水平垂直居中的方式很多。別看到水平垂直居中就準備右上角 x 掉,本文的重點不是羅列有多少種方式實現水平垂直居中方式,而是探討一下常見的幾種水平垂直居中的方式的利弊。

嗯哼?也就是:

  • 那麼多種水平垂直居中的方式,如果真的在業務中需要使用了,你腦海里第一時間會想到哪個?
  • 不同的水平垂直居中方式,它們肯定存在差異,那麼最顯著的不同是什麼?
  • 有沒有所謂的最完美的水平垂直居中?

本文將討論 4 種水平垂直居中的方式,分別是,並且每個起個名字方面下面看圖:

  1. absolute: position: absolute 配合 top:50%;left:50%;transform:translate(-50%, -50%)
  2. autobot: display:flex 配合 margin:auto
  3. flex: display:flex 配合 align-items:center、justify-content:center
  4. grid: display:grid 配合 place-content:center;

居中單個元素

對於如下簡單的結構:

<div class="g-container">
    <div class="sub"></div>
</div>

居中單個元素而言,上述 4 種方法都很好,沒有問題。

居中多個元素

對於如下稍微複雜點的結構:

<div class="g-container">
    <div class="sub">1</div>
    <div class="sub">123</div>
    <div class="sub">123456</div>
</div>

那麼如果是居中多個子元素,上述 4 種方法,就能體現出明顯的不一樣。稍微也修改一下子元素,不給它設定寬度,通過 padding 撐開即可:

.sub {
    border: 1px solid deeppink;
    padding: 10px;
    border-radius: 5px;
}

看看結果如何:

簡單分析分析:

  1. absolute 的方法明顯有問題,由於用的絕對定位,其實 3 個子元素都疊在了一起
  2. flex 和 grid 的方法,如果不手動添加邊距(margin 或者 gap),會貼在一起
  3. 不限制方向的話,flex 默認是水平排列,grid 是豎直排列
  4. 非常重要的一點,grid 布局下的子元素的寬度,所以子元素的寬度會被強行拉伸至最寬的一個子元素的內容的寬度

對於多個子元素,absolute 方法明顯不適用, 接下來主要看剩餘 3 個方法在一些細節上的差異。

控制間距

如果我們希望控制每個元素之間的間距呢?我們給 autobot、flex、grid 的容器各自加上 gap: 5px,再看看:

.g-container{
    gap: 5px;
}

margin: auto 由於需要均分剩餘空間,所以表現並不好,無法按照我們設想的 5px 寬度進行間隔

讓元素多到溢出

OK,接下來,我們讓內容再多一點,多到溢出整個容器,看看有什麼不一樣。

再來一張豎直方向排列的:

可以看到:

  1. 非常重要的一點,由於沒有了剩餘空間,margin: auto 已經無法做到均勻分配,水平垂直居中了,而是一邊貼着容器邊,另外一邊溢出
  2. flex 和 grid 都做到了即便超出容器空間,依然是水平垂直居中的

總結一下

經由上述幾個 DEMO 可以看出來,在目前比較常用的水平垂直居中方案當中。flex 方案應該是目前而言最優的選擇,它能夠在各種環境下都保持內部元素的水平垂直居中並且不改變子元素的某些特徵:

  1. 便捷的水平垂直居中單個元素
  2. 便捷的水平垂直居中多個元素,無論是橫向、豎向,亦或內容超出
  3. 非常方便控制子元素之間的間距
  4. 不會改變子元素的寬度

當然,美中不足的是,可能相對而言,要敲多幾個字符。

而 margin: auto 和 grid 則或多或少有一些小問題。absolute 無法應付多個元素。

站長推薦

1.雲服務推薦: 國內主流雲服務商,各類雲產品的最新活動,優惠券領取。地址:阿里雲騰訊雲華為雲

2.廣告聯盟: 整理了目前主流的廣告聯盟平台,如果你有流量,可以作為參考選擇適合你的平台點擊進入

鏈接: http://www.fly63.com/article/detial/10044

沐鳴平台註冊登錄_10個JavaScript 字符串技巧

我們稱一個字符序列為字符串。這幾乎是所有編程語言中都有的基本類型之一。這裏跟大家展示關於 js 字符串的10個很棒的技巧,你可能還不知道哦?

1.如何多次複製一個字符串

js 字符串允許簡單的重複,與純手工複製字符串不同,我們可以使用字符串的repeat方法。

const laughing = '小智'.repeat(3)
consol.log(laughing) // "小智小智小智"

const eightBits = '1'.repeat(8)
console.log(eightBits) // "11111111"

2. 如何填充一個字符串到指定的長度

有時,我們希望字符串具有特定長度。 如果字符串太短,則需要填充剩餘空間,直到達到指定的長度為止。

過去,主要還是使用庫 left-pad。 但是,今天我們可以使用padStart和SpadEnd方法,選擇哪種方法取決於是在字符串的開頭還是結尾填充字符串。

// 在開頭添加 "0",直到字符串的長度為 8。
const eightBits = '001'.padStart(8, '0')
console.log(eightBits) // "00000001"

//在末尾添加“ *”,直到字符串的長度為5。
const anonymizedCode = "34".padEnd(5, "*")
console.log(anonymizedCode) // "34***"

3.如何將字符串拆分為字符數組

有多種方法可以將字符串分割成字符數組,我更喜歡使用擴展操作符(…):

const word = 'apple'
const characters = [...word]
console.log(characters) // ["a", "p", "p", "l", "e"]

注意,這並不總是像預期的那樣工作。有關更多信息,請參見下一個技巧。

4.如何計算字符串中的字符

可以使用length屬性。

const word = "apple";
console.log(word.length) // 5

但對於中文來說,這個方法就不太靠譜。

const word = "

站長推薦

1.雲服務推薦: 國內主流雲服務商,各類雲產品的最新活動,優惠券領取。地址:阿里雲騰訊雲華為雲

2.廣告聯盟: 整理了目前主流的廣告聯盟平台,如果你有流量,可以作為參考選擇適合你的平台點擊進入

鏈接: http://www.fly63.com/article/detial/10062

沐鳴總代理_編寫高質量 JS 變量的5種最佳做法

變量無處不在,即使我們在寫一個小的函數,或者一個應用程序:我們總是先聲明,分配和使用變量。編寫好的變量可提高代碼的可讀性和易維護性。

在本文中,主要介紹 5種有關在 JavaScript 中聲明和使用變量的最佳做法。

1.首選 const,再 let

我使用const或let聲明變量,兩者之間的主要區別是const變量需要一個初始值,並且一旦初始化就無法重新分配其值。

另一方面,let聲明不需要初始值,我們可以多次重新分配其值。

// const 需要初始化
const pi = 3.14;
// 不能重新分配const
pi = 4.89; // throws "TypeError: Assignment to constant variable"

另一方面,let聲明不需要初始值,我們可以多次重新分配其值。

// let 初始化是可選的
let result;
// let can be reassigned
result = 14;
result = result * 2;

選擇變量的聲明類型時的一個好習慣是首選const,否則使用let。

function myBigFunction(param1, param2) {
  /* lots of stuff... */

  const result = otherFunction(param1);

  /* lots of stuff... */
  return something;
}

例如,如果我們正在查看函數體,並看到const result = …聲明:

function myBigFunction(param1, param2) {
  /* lots of stuff... */

  const result = otherFunction(param1);

  /* lots of stuff... */
  return something;
}

不知道myBigFunction()內部會發生什麼, 我們可以得出結論,result 變量只分配了一次,聲明之後是只讀的。

在其他情況下,如果必須在執行過程中多次重新分配變量,則可以使用let聲明。

2.最小化變量的範圍

變量存在於它們所創建的作用域內。代碼塊和函數體為const和let變量創建一個作用域。提高變量可讀性的一個好習慣是將變量保持在最小作用域內。

例如,以下函數是二進制搜索算法的實現:

function binarySearch(array, search) {
  let middle;
  let middleItem;
  let left = 0;
  let right = array.length - 1;

  while(left <= right) {
    middle = Math.floor((left + right) / 2);
    middleItem = array[middle];
    if (middleItem === search) { 
      return true; 
    }
    if (middleItem < search) { 
      left = middle + 1; 
    } else {
      right = middle - 1; 
    }
  }
  return false;
}

binarySearch([2, 5, 7, 9], 7); // => true
binarySearch([2, 5, 7, 9], 1); // => false

middle和middleItem變量在函數體的開頭聲明。因此,這些變量在binarySearch()函數體創建的整個作用域內都是可用的。

middle變量保留二進制搜索的中間索引,而middleItem變量保留二進制搜索的中間索引。

但是,middle和middleItem變量只在while循環代碼塊中使用。所以為什麼不直接在while代碼塊中聲明這些變量呢?

function binarySearch(array, search) {
  let left = 0;
  let right = array.length - 1;

  while(left <= right) {
    const middle = Math.floor((left + right) / 2);
    const middleItem = array[middle];
    if (middleItem === search) {
      return true; 
    }
    if (middleItem < search) {
      left = middle + 1; 
    } else {
      right = middle - 1; 
    }
  }
  return false;
}

現在,middle和middleItem變量僅存在於使用變量的作用域。 他們的生命周期和生命周期極短,因此更容易推斷其作用。

3.在接近位置聲明變量

我強烈希望在函數主體的頂部聲明所有變量,尤其是在函數較大的情況下。 不幸的是,這種做法的缺點是使我在函數中使用的意圖變量變得混亂。

盡量在接近使用位置的地方聲明變量。這樣,我們就不用猜了:嘿,我看到了這裏聲明的變量,但是它在哪裡被使用了。

假設我們有一個函數,該函數的主體中包含很多語句。 我們可以在函數的開頭聲明並初始化變量結果,但是只能在return語句中使用result:

function myBigFunction(param1, param2) {
  const result = otherFunction(param1);
  let something;

  /* * calculate something... */

  return something + result;
}

問題在於result 變量在開頭聲明,但僅在結尾使用,沒有足夠的理由在開始時聲明該變量。

讓我們通過將result 變量聲明移到return語句之前來改進這個函數

function myBigFunction(param1, param2) {
  let something;

  /* * calculate something... */

  const result = otherFunction(param1);
  return something + result;
}

現在,result變量在函數中有了它的正確位置。

4.好的命名意味着易於閱讀

從良好的變量命名的眾多規則中,我區分出兩個重要的規則。

第一個很簡單:使用駝峰命名為變量取名,並且在命名所有變量時保持一致。

const message = 'Hello';
const isLoading = true;
let count

有特殊含義的数字或字符串,變量命名通常是大寫的,在單詞之間加下劃線,以區別於常規變量

const SECONDS_IN_MINUTE = 60;
const GRAPHQL_URI = 'http://site.com/graphql';

第二條規則,在變量命名中,我認為這是最重要的:變量名稱應明確無歧義地指出哪些數據保存了該變量。

以下是一些很好的變量命名示例:

let message = 'Hello';
let isLoading = true;
let count;

message 名稱表示此變量包含某種消息,很可能是字符串。

isLoading相同,布爾值指示加載是否在進行中。

count變量表示保存一些計數結果的数字類型變量。

選擇一個明確表明其角色的變量名。

舉個例子,這樣就能看出區別了。假設看到了這樣一個函數:

function salary(ws, r) {
  let t = 0;
  for (w of ws) {
    t += w * r;
  }
  return t;
}

你能總結出這個函數的作用嗎?像ws、r、t、w這樣的變量名幾乎沒有說明它們的意圖。

相反,相同的函數,但使用了解釋性變量命名

function calculateTotalSalary(weeksHours, ratePerHour) {
  let totalSalary = 0;
  for (const weekHours of weeksHours) {
    const weeklySalary = weekHours * ratePerHour;
    totalSalary += weeklySalary;
  }
  return totalSalary;
}

該代碼清楚地說明了它的作用。 這就是良好命名的力量。

5. 引入中間變量

我比較少註釋代碼。我更喜歡編寫代碼即解釋的風格,通過對變量、屬性、函數和類的良好命名來表達意圖。

編寫自文檔代碼的一個好習慣是引入中間變量。 在處理長表達式時很有用。

考慮以下錶達式:

const sum = val1 * val2 + val3 / val4;

我們引入兩个中間變量,增強長表達式的可讀性:

const multiplication = val1 * val2;
const division       = val3 / val4;

const sum = multiplication + division;

另外,讓我們回顧一下二進制搜索實現算法:

function binarySearch(array, search) {
  let left = 0;
  let right = array.length - 1;

  while(left <= right) {
    const middle = Math.floor((left + right) / 2);
    const middleItem = array[middle];
    if (middleItem === search) {
      return true; 
    }
    if (middleItem < search) {
      left = middle + 1; 
    } else {
      right = middle - 1; 
    }
  }
  return false;
}

這裏middleItem是一個保存中間項目的中間變量。 使用中間變量MiddleItem而不是直接使用項目訪問器array [middle]可讀性更好。

與缺少middleItem解釋變量的函數版本進行比較:

function binarySearch(array, search) {
  let left = 0;
  let right = array.length - 1;

  while(left <= right) {
    const middle = Math.floor((left + right) / 2);
    if (array[middle] === search) {
      return true; 
    }
    if (array[middle] < search) {
      left = middle + 1; 
    } else {
      right = middle - 1; 
    }
  }
  return false;
}

這個版本,沒有解釋變量,可讀性就比較差。

6. 總結

變量無處不在,我們總是先聲明,分配和使用變量。

在 js 中使用變量時,第一個好的做法是使用const,否則使用let

試着保持變量的作用域盡可能小。同樣,將變量聲明往盡可能靠近使用位置。

不要低估好的命名的重要性。始終遵循這樣的規則:變量名應該清晰而明確地表示保存變量的數據。不要害怕使用較長的名字:最好是清晰而不是簡潔。

最後,少使用註釋,多寫寫代碼即的效果 。 在高度複雜的地方,我更喜歡引入中間變量。

原文:https://dmitripavlutin.com/

站長推薦

1.雲服務推薦: 國內主流雲服務商,各類雲產品的最新活動,優惠券領取。地址:阿里雲騰訊雲華為雲

2.廣告聯盟: 整理了目前主流的廣告聯盟平台,如果你有流量,可以作為參考選擇適合你的平台點擊進入

鏈接: http://www.fly63.com/article/detial/10060

沐鳴平台註冊登錄_前端WebSocket知識點總結

最近研究了下WebSocket,總結下目前對WebSocket的認知。本文不是基於WebSocket展開的一個從0到1的詳細介紹。如果你從來沒有了解過WebScoket,建議可以先搜一些介紹WebSocket的文章,這類文章還是挺多的,我就不再贅述了。

下面的內容是基於你對WebSocket有基本了解后展開的幾個小的知識點:

  1. ping/pong協議;
  2. 如何使ERROR_INTERNET_DISCONNECTED錯誤信息不显示在控制台;

ping/pong協議

背景:連接WebSocket的時候,發現WebSocket剛連接上沒過多久就斷開了,為了保持長時間的連接,就想到了ping/pong協議。

問題:

  1. ping/pong是一種特殊的幀類型嗎,還是說只是一種設計思想?
  2. js有原生方法支持發送ping/pong消息嗎

通過WebSocket協議,發現ping/pong確實是一種特殊的幀類型:

The Ping frame contains an opcode of 0x9.
The Pong frame contains an opcode of 0xA.

那麼,上面所說的opcode又是什麼東西呢?講opcode就得說到幀數據格式:


通過上圖可以發現,除了最後面的Payload Data,也就是我們要發送的數據之外,還會有一些其他信息。我覺得可以類比http請求的請求頭部分。上圖中第5-8位表示的就是opcode的內容。其餘字段的含義可以參考上述WebSocket規範,或者搜WebSocket協議數據幀格式,這類博客還是挺多的。

拿nodejs舉個例子:
在瀏覽器端發起WebSocket的時候,會發送一個http請求,注意請求頭裡面的Upgrade字段,意思就是我要升級到websocket連接:

GET /chat HTTP/1.1
Host: example.com:8000
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

此時,nodeJS就可以監聽upgrade事件,去做拒絕或者升級操作,注意下這個事件裏面有個參數socket:

socket: <stream.Duplex> Network socket between the server and client

socket有一個write方法,該方法是可以用來寫幀數據的,也就是上面幀格式裏面的全部數據,而不僅僅是Payload Data。

ws倉庫就是使用了socket的write方法發送了根據WebSocket協議定義的ping/pong,部分關鍵代碼如下:

doPing(data, mask, readOnly, cb) {
  this.sendFrame(
    Sender.frame(data, {
      fin: true,
      rsv1: false,
      opcode: 0x09, // ping opcode
      mask,
      readOnly
    }),
    cb
  );
}
doPong(data, mask, readOnly, cb) {
  this.sendFrame(
    Sender.frame(data, {
      fin: true,
      rsv1: false,
      opcode: 0x0a, // pong opcode
      mask,
      readOnly
    }),
    cb
  );
}
sendFrame(list, cb) {
  if (list.length === 2) {
    this._socket.cork();
    this._socket.write(list[0]);
    this._socket.write(list[1], cb);
    this._socket.uncork();
  } else {
    this._socket.write(list[0], cb);
  }
}

所以,nodeJS是可以實現WebSocket協議定義的ping/pong幀的。原因是我們可以拿到socket對象,並且該對象提供了可以發送完整幀數據的方法。那麼瀏覽器端呢?

瀏覽器提供了原生的WebSocket構造函數用來創建一個WebSocket實例,該實例只提供了一個send方法,並且該send方法只能用來發送上述協議中Payload Data的內容,瀏覽器會根據send的參數自動生成一個完整的幀數據。所以,在瀏覽器端是沒法控制除了Payload Data之外的幀內容的,也就是無法自定義opcode。所以,也就實現不了WebSocket規範定義的ping/pong協議。

此時,我們就可以把ping/pong當成一種用來解決特定問題的設計模式。既然我們只能自定義Payload Data的內容,那麼我們可以簡單的在Payload Data裏面添加一個字段用於區分是ping/pong幀,還是普通的數據幀,比如type。當type字段是ping/pong的時候表明是ping/pong幀,如果是其他字段才是普通的數據幀。

如何使ERROR_INTERNET_DISCONNECTED錯誤信息不显示在控制台

當斷網的時候,連接WebSocket會發現瀏覽器控制台會log一個錯誤信息:

WebSocket connection to 'ws://...' failed: Error in connection establishment: net::ERR_INTERNET_DISCONNECTED

原先的開發經驗是,控制台如果有報錯的話,肯定是代碼某個地方有錯誤,並且沒有被我們的代碼捕獲到,所以就會在控制台拋出,如果使用了try catch 或者全局的window.onerror捕獲到了錯誤信息,就不會在控制台打印了。所以,我就嘗試了上述方法,發現捕捉不到,還是會在控制台log。

另外,WebSocket提供了兩個事件,onerror和onclose。當發生上述錯誤信息的時候,onerror和onclose是會被調用的。但是,此時控制台還是會有上述報錯信息。

經過一番查找,發現無法阻止上述錯誤信息显示在控制台。

那麼,為什麼瀏覽器會設計這樣的行為呢?猜測原因如下:
上面說到通過onerror和onclose事件是可以捕捉到WebSocket創建失敗的,但是,查看這兩個事件的參數,我們只能從中找到一個code是1006的屬性,輸出在控制台的錯誤信息ERR_INTERNET_DISCONNECTED在參數裏面找不到。接着,看一下code1006相關的東西:

User agents must not convey any failure information to scripts in a way that would allow a script to distinguish the following situations:

*   A server whose host name could not be resolved.
*   A server to which packets could not successfully be routed.
*   A server that refused the connection on the specified port.
*   A server that failed to correctly perform a TLS handshake (e.g., the server certificate can't be verified).
*   A server that did not complete the opening handshake (e.g. because it was not a WebSocket server).
*   A WebSocket server that sent a correct opening handshake, but that specified options that caused the client to drop the connection (e.g. the server specified a subprotocol that the client did not offer).
*   A WebSocket server that abruptly closed the connection after successfully completing the opening handshake.

In all of these cases, the the WebSocket connection close code would be 1006, as required by WebSocket Protocol. 

Allowing a script to distinguish these cases would allow a script to probe the user's local network in preparation for an attack.

從上述規範可以看到,規範是禁止瀏覽器向腳本傳遞下述造成WebSocket連接失敗的具體原因的,只允許向腳本傳遞一個1006的code碼,否則,用戶就可以探測到局部網的信息,進而發起攻擊。舉個例子,上面那種斷網的情況,腳本中只能得到1006的狀態碼,比如下面這種報錯

Error in connection establishment: net::ERR_CONNECTION_REFUSED

也只能從onerror中獲得一個1006的code碼。

所以,作為開發人員,瀏覽器要怎麼在告訴我們具體的錯誤信息的同時又阻止有可能發生的攻擊呢?答案就是在控制台把具體的錯誤信息log出來。

站長推薦

1.雲服務推薦: 國內主流雲服務商,各類雲產品的最新活動,優惠券領取。地址:阿里雲騰訊雲華為雲

2.廣告聯盟: 整理了目前主流的廣告聯盟平台,如果你有流量,可以作為參考選擇適合你的平台點擊進入

鏈接: http://www.fly63.com/article/detial/10058

沐鳴註冊平台_vue-cli4首次加載速度優化

GZIP壓縮

GZIP壓縮有動態跟靜態兩種
可以將由前端打包GZIP,通過 gzip_static:on會尋找以.gz結尾的文件,直接返回,不會佔用cpu進行壓縮,如果找不到則不進行壓縮

nginx

  #開啟和關閉gzip模式
    gzip on|off;
    
    #gizp壓縮起點,文件大於1k才進行壓縮
    gzip_min_length 1k;
    
    # gzip 壓縮級別,1-9,数字越大壓縮的越好,也越佔用CPU時間
    gzip_comp_level 5;
    
    # 進行壓縮的文件類型。
    gzip_types text/plain application/JavaScript application/x-JavaScript text/css application/xml text/javascript ;
    
    #nginx對於靜態文件的處理模塊,開啟後會尋找以.gz結尾的文件,直接返回,不會佔用cpu進行壓縮,如果找不到則不進行壓縮
    gzip_static on|off
    
    # 是否在http header中添加vary: Accept-Encoding,建議開啟
    gzip_vary on;

    # 設置壓縮所需要的緩衝區大小,以4k為單位,如果文件為7k則申請2*4k的緩衝區 
    gzip_buffers 2 4k;

    # 設置gzip壓縮針對的HTTP協議版本
    gzip_http_version 1.1;

vue.config.js

// npm i -D compression-webpack-plugin
const CompressionPlugin = require('compression-webpack-plugin')

configureWebpack: {
/* 打包時開啟GZIP壓縮 */
  plugins: [
    new CompressionPlugin({
          algorithm: 'gzip', // 使用gzip壓縮
          test: /\.js$|\.html$|\.css$/, // 匹配文件名
          filename: '[path].gz[query]', // 壓縮后的文件名(保持原文件名,後綴加.gz)
          minRatio: 1, // 壓縮率小於1才會壓縮
          threshold: 10240, // 對超過10k的數據壓縮
          deleteOriginalAssets: false, // 是否刪除未壓縮的源文件,謹慎設置,如果希望提供非gzip的資源,可不設置或者設置為false(比如刪除打包后的gz后還可以加載到原始資源文件)
    }),
  ]
}

CDN

const isProd = process.env.NODE_ENV === 'production'
const cdn = {
  externals: {
    // 業務使用示例 => key:包名 value:庫文件對應的全局對象字符串=>可以沖源碼最後獲取
    vue: 'Vue',
    'vue-router': 'VueRouter',
    vuex: 'Vuex',
    axios: 'axios',
    'ant-design-vue': 'antd',
    'vue-ls': 'VueStorage',
  },
  // import的css不要放進來,externals無法過濾掉
  css: [],
  js: [
    '//unpkg.com/vue@2.6.12/dist/vue.min.js',
    '//unpkg.com/vue-router@3.4.9/dist/vue-router.min.js',
    '//unpkg.com/vuex@3.5.1/dist/vuex.min.js',
    '//unpkg.com/axios@0.21.0/dist/axios.min.js',
    '//unpkg.com/ant-design-vue@1.7.2/dist/antd.min.js',
    '//unpkg.com/vue-ls@3.2.1/dist/vue-ls.min.js',
  ]
};

configureWebpack: config => {
  config.externals = isProd ? cdn.externals : {}
},
chainWebpack: config => {
    config.plugin('html').tap(args => {
            // html中添加cdn
            args[0].cdn = cdn
            return args
          })
}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <link rel="icon" href="<%= BASE_URL %>favicon.ico">
  <title><%= htmlWebpackPlugin.options.title %></title>
  <link rel="stylesheet" href="//at.alicdn.com/t/font_1825329_krt0759dhsh.css" />
  <!-- htmlWebpackPlugin.options.cdn 在vue.config.js內配置 -->
  <!-- 使用CDN的CSS文件 -->
  <% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.css) { %>
  <link rel="stylesheet" href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" />
  <% } %>
</head>
<body>
  <noscript>
    <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
      Please enable it to continue.</strong>
  </noscript>
  <div id="app"></div>
  <!-- 使用CDN的JS文件 -->
  <% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.js) { %>
  <script type="text/javascript" src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
  <% } %>
</body>
</html>

路由按需加載

使用 ()=>import(‘xxx’)按需加載路由組件,可以添加magic comments
打包後會單獨生成chunk.[hash].js文件,進一步減小主包大小

// Magic Comments 詳情查看下方鏈接
// https://webpack.docschina.org/api/module-methods/#magic-comments
{
    path: '/login',
    name: 'login',
    component: () => import(/* webpackChunkName: "my-chunk-name" */'@/views/login/Login'),
    hidden: true,
  },

站長推薦

1.雲服務推薦: 國內主流雲服務商,各類雲產品的最新活動,優惠券領取。地址:阿里雲騰訊雲華為雲

2.廣告聯盟: 整理了目前主流的廣告聯盟平台,如果你有流量,可以作為參考選擇適合你的平台點擊進入

鏈接: http://www.fly63.com/article/detial/10057

沐鳴主管:_Js中forEach跳出循環體

背景

在forEach中,不能使用 continue 和 break ,可以使用 return 或 return false 跳出循環,效果與 for 中 continue 一樣。注意該方法無法一次結束所有循環。

跳出本次循環

forEach 跳出本次循環,使用return

    [1,2,3,4,5].forEach(function(item,index){
        if(item == 3){
            return
        }
        console.log(3)// item == 3時,執行不到該部分,結束本次循環
    })

跳出整個循環

forEach 跳出整個循環,需要拋出異常

try {
    [1,2,3,4,5].forEach(function(item,index){
        if(item == 3){
            thorw new Error(); //結束整體循環
        }
    })
} catch(e) {

}

跳出嵌套循環

forEach 跳出嵌套循環

try {
    ["a","b","c"].forEach(function(item,index){

        try {
            [1,2,3,4,5].forEach(function(item,index){
                if(item == 3){
                    thorw new Error(); //結束整體循環
                }
            })
        } finally{}//try不能單獨存在

        <!--catch(e) {-->
            //內層的catch不能存在,不然會捕獲異常,只結束內層forEach
        <!--}-->

    })
} catch(e) { //在最外層捕獲異常,可結束嵌套循環

}

站長推薦

1.雲服務推薦: 國內主流雲服務商,各類雲產品的最新活動,優惠券領取。地址:阿里雲騰訊雲華為雲

2.廣告聯盟: 整理了目前主流的廣告聯盟平台,如果你有流量,可以作為參考選擇適合你的平台點擊進入

鏈接: http://www.fly63.com/article/detial/10052

沐鳴代理_JavaScript中 ?

起因

最近在研究 cron 表達式和時間的互相轉化問題,然後突然看到了一個有意思的語法,於是就拿來研究了一下。

一、js 中神奇的 ?

說到 ? ,大家肯定都不陌生吧,立馬就能夠想到三元表達式,當然還有其它的語法,比如雙問號語法 ?? ,還有在正則表達式中。

1、三元表達式

 var flag = true;
var log = flag ? '真' : '假';
console.log(log);  //  真

大家都知道這個,就是指 ? 前面的表達式為真時會執行 : 前面的語句,否則執行 : 後面的,所以這個地方必定輸出為真。

2、??

有了前面提到的 第1點,我相信這一個很好理解。

說到雙問號語法,就不得不說 || 、 && 這兩個語法了,但是我相信大家都已經很清楚這兩個語法了。

無非就是邏輯運算 或 和 與。

var flag = true;
var log = flag || '邏輯或';
console.log(log);  //  true
var flag = false;
var log = flag || '邏輯或';
console.log(log);  //  邏輯或
var flag = null;
var log = flag || false;
console.log(log);  //  false

嗯…言簡意賅。  

var flag = true;
var log = flag && '邏輯與';
console.log(log);  //  邏輯與
var flag = false;
var log = flag && '邏輯與';
console.log(log);  //  false
var flag = null;
var log = flag && false;
console.log(log);  //  null

嗯…挺明顯的吧,短路操作。  

重頭戲來了,雙 ?? 。

var flag = true;
var log = flag ?? '??';
console.log(log);  //  true
var flag = false;
var log = flag ?? '??';
console.log(log);  //  false
var flag = undefined;
var log = flag ?? '??';
console.log(log);  //  ??
var flag = null;
var log = flag ?? '??';
console.log(log);  //  ??

咳咳,其實感覺和 || 很像,只不過只有在前面的表達式為 undefined 或者 null 時,才會執行後面的語句,否則不論前面的表達式為真還是為假都會執行前面的語句,而 || 的前面只要為假時就會執行後面的語句了。

二、?

如果你以為我只是想說這個,那你就大錯特錯了,因為這些老掉牙的都說過不知道多少遍了,大家都懂,但是下面要說的這個我之前是真的沒見過,可能是我孤陋寡聞吧。
提前尷尬一波。。。

?

大家在取數組或者對象中的值時是不是一定會用到

var arr = [0, 1, 2];
arr[0]; // 0
arr[1]; // 1

var obj = {a: 1, b: 2, c: 3};
obj['a']; // 1
obj['b']; // 2

諸如此類的方法。

但是如果在取值前 arr 或者 obj 為 undefined 或者 null 那麼將會報錯,
所以有了這神奇的操作。

var arr = [0, 1, 2];
arr?.[0]; // 0
arr?.[1]; // 1

var obj = {a: 1, b: 2, c: 3};
obj?.['a']; // 1
obj?.['b']; // 2

可以看到取值其實是一樣的,只不過當 arr 或者 obj 為 undefined 或者 null 時並不會報錯,而是返回 undefined , 如下圖。

來自:https://www.cnblogs.com/nyya/archive/2021/01/08/14251761.html

站長推薦

1.雲服務推薦: 國內主流雲服務商,各類雲產品的最新活動,優惠券領取。地址:阿里雲騰訊雲華為雲

2.廣告聯盟: 整理了目前主流的廣告聯盟平台,如果你有流量,可以作為參考選擇適合你的平台點擊進入

鏈接: http://www.fly63.com/article/detial/10050