再擼一梭子漸漸你該懂得知識

typeof原理

JS底層存儲變量會在機器碼低位1-3位存儲類型信息,typeof也是據此判斷的,巧合的是null和object的這三位都是000,因此typeof null == typeof {} == ‘object’。

Chrome80對SameSite的使用

之前寫過Chrome80更新,很重要的一點改動就是對sameSite的改動,之前samesite默認是使用none的,Chrome80之後,這個默認值改爲了lax(寬鬆),也就是說,之前設置爲None時,無論是否跨站,默認請求都會攜帶cookie,但是修改之後,跨站是不會攜帶cookie的。

跨站與同源(跨域)不同,只需要判斷頂級域名和二級域名,如http://a.t.com和https://b.t.com,我們可以認爲它是同站。而設置爲Lax之後,除去get 方法提交表單況或者a 標籤發送 get 請求之外,很多跨站方式並不會攜帶請求。

Promise封裝Ajax

之前被問道一次,也沒讓寫,這裏貼出來:

function Ajax(url) {
  return new Promise((resolve, reject) => {
    let xhr = new XMLHttpRequest();
    xhr.open("get", url, true);
    xhr.responseType = "JSON";
    xhr.onreadystatechange = function() {
      if (xhr.readyState === 4 && /^[23]\d{2}$/.test(xhr.status)) {
        let res = xhr.responseText;
        resolve(JSON.parse(res));
      }
    };
    xhr.onerror = function(err) {
      reject(err);
    };
    xhr.send();
  });
}

很可能會忘了parse,那樣的出來的是字符串。

JSONP

原理很簡單,利用了script便籤不受同源協定的約束,把要返回的值序列化放到callback後面拼成一個立函數執行形式,然後在客戶端window對象添加一個對應的函數,在這兒函數種對服務端返回的響應包裹的數據進行處理:

function jsonp({url,params,callback}){
  return new Promise((resolve, reject) => {
    let script = document.body.createElement('script')
    params = JSON.parse(JSON.stringify(params))
    let arr = []
    for(let key in params){
      arr.push(`${key}=${params[key]}`)
    }
    arr.push(`callback=${callback}`)
    script.src = `${url}?${arr.join("&")}`;
    document.appendChild(script)
    window[callback]=function(data){
      if(!data) reject('failed')
      resolve(data) 
      document.body.removeChild(script) 
    }
  })
}

簡單認識websocket

之前對webSocket的簡單瞭解就是實現了服務器主動推送,畢竟在此之前,我們實現推送都是通過輪詢的方式實現的。

首先,WebSocket建立在 TCP 協議之上,與 HTTP 協議有着良好的兼容性。默認端口也是80和443,並且握手階段採用 HTTP協議,同時它的數據格式比較輕量,性能開銷小,通信高效。可以發送文本,也可以發送二進制數據。
還有一點它不受沒有同源限制,客戶端可以與任意服務器通信。協議標識符是ws(如果加密,則爲wss),服務器網址就是 URL。

HTTP握手後,WebSocket基於HTTP協議進行升級,服務端返回101狀態碼標識協議切換,後序的數據交互都按照新的協議進行。建立連接後,後續的操作都是基於數據幀的傳遞。

兩種解決Effect錯誤依賴的方法

看個Demo:

export default function Counter() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const id = setInterval(() => {
      console.log("in");
      setCount(count + 1);
    }, 1000);
    return () => {
      console.log("out");
      clearInterval(id);
    };
  }, []);
  return <h1>{count}</h1>;
}

這裏,我們依賴爲空,只會渲染一次,setInterval導致"in"每隔1秒會輸出,而UseEffect並不會重複執行,因此每次我們的count爲0,+1,返回的總是1。

解決1:

export default function Counter() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const id = setInterval(() => {
      console.log("in");
      setCount(count + 1);
    }, 1000);
    return () => {
      console.log("out");
      clearInterval(id);
    };
  }, [count]);

  return <h1>{count}</h1>;
}

但是這樣只會使得我們每次都要刪除定時器再添加,不符合我們的需求。

解決2:

export default function Counter() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const id = setInterval(() => {
      console.log("in");
      setCount(c=c+ 1);
    }, 1000);
    return () => {
      console.log("out");
      clearInterval(id);
    };
  }, []);

  return <h1>{count}</h1>;
}

使用函數式更新state是最好的解決方法。

關於函數依賴,我們可以使用三個方式:

  1. 把函數寫在useEffect種,確保它不依賴組件其他狀態。
  2. 把函數寫在組件外
  3. 使用useCallback包裹。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章