Keys 是 React 用於追蹤哪些列表中元素被修改、被添加或者被移除的輔助標識。javascript
render () {
return (
<ul>
{this.state.todoItems.map(
({item, key}) => {
return <li key={key}>{item}</li>
})
}
</ul>
)}
複製代碼
在開發過程當中,咱們須要保證某個元素的 key 在其同級元素中具備惟一性。在 React Diff 算法中 React 會藉助元素的 Key 值來判斷該元素是新近建立的仍是被移動而來的元素,從而減小沒必要要的元素重渲染。此外,React 還須要藉助 Key 值來判斷元素與本地狀態的關聯關係,所以咱們毫不可忽視轉換函數中 Key 的重要性。css
// 手機號碼
function checkPhone(phone){
if(!(/^1[3456789]\d{9}$/.test(phone))){
alert("手機號碼有誤,請重填");
return false;
}
}
// 判斷字符串以字母開頭,後面能夠是數字,下劃線,字母,長度爲6-30
function checout(str){
var reg=/^[a-zA-Z]\w{5,29}$/;
if(str && reg.test(str)){
alert('正確')
}
}
// 寫一個function,清除字符串先後的空格。
function trim(str) {
if (str & typeof str === "string") {
return str.replace(/(^s*)|(s*)$/g,"");
}
}
複製代碼
string,boolean,number,undefined,function,objecthtml
答案:強制(parseInt,parseFloat,number) 隱式(== ===)前端
答案:前者是將字符串切割成數組的形式,後者是將數組轉換成字符串vue
相同點:改變函數的this指向java
var obj = {name: 'lisi'}
function fn() {
console.log(this)
}
fn.call(null) //this指向window
fn.apply(null) //this指向window
fn.call(obj) //this指向obj
fn.apply(obj) //this指向obj
複製代碼
不一樣點: call傳參形式是,從第二個開始一個一個傳,apply的第二個參數爲數組,數組的每一項爲函數的參數react
Object.call(this,obj1,obj2,obj3)
Object.apply(this,arguments)
複製代碼
利用事件冒泡的原理,讓本身的所觸發的事件,讓他的父元素代替執行!git
***閉包***就是可以讀取其餘函數內部變量的函數,使得函數不被GC回收,若是過多使用閉包,容易致使內存泄露(再也不用到的內存,沒有及時釋放,就叫作內存泄漏) 閉包的好處 但願一個變量長期駐紮在內存當中(不被垃圾回收機制回收), 避免全局變量的污染,私有成員的存在,安全性提升 閉包使用場景: 函數做爲返回值;函數做爲參數傳遞;閉包實際應用中主要用於封裝變量,收斂權限;web
阻止事件冒泡:ev.stopPropagation();何阻止默認事件: (1)return false;(2) ev.preventDefault();面試
動態建立script標籤,回調函數,Ajax是頁面無刷新請求數據操做
前者會自動轉換類型,再判斷是否相等,後者不會自動類型轉換,直接去比較
在Javscript中,解析器在向執行環境中加載數據時,對函數聲明和函數表達式並不是是一視同仁的,解析器會率先讀取函數聲明,並使其在執行任何代碼以前可用(能夠訪問),至於函數表達式,則必須等到解析器執行到它所在的代碼行,纔會真正被解析執行。
// 函數聲明
function add(){}
// 函數表達式
var del = function del(){} // 命名函數函數表達式
var update= function(){} // 命名函數函數表達式
function(){} // 匿名函數表達式
複製代碼
函數表達式能夠直接在函數定義後面加小括號執行,而函數聲明則不行
var mult = function(x,y){ return(x*y); }();//正常
function div(x,y){ return(x/y); }()//報錯
複製代碼
var User = {
count: 1,
getCount: function() {
return this.count;
}
};
console.log(User.getCount()); // what?
var func = User.getCount;
console.log(func()); // what?
複製代碼
問兩處console輸出什麼?爲何? 答案:是1和undefined。 func是在window的上下文中被執行的,因此不會訪問到count屬性。
for(var i = 1; i <= 3; i++){ //建議使用let 可正常輸出i的值
setTimeout(function(){
console.log(i);
},0);
};
複製代碼
答案:4 4 4。 緣由:Javascript事件處理器在線程空閒以前不會運行。
事件代理
var a = null;
alert(typeof a);
答案:object
複製代碼
解釋:null是一個只有一個值的數據類型,這個值就是null。表示一個空指針對象,因此用typeof檢測會返回」object」。
<script>
var a = 100;
function test(){
alert(a);
a = 10; //去掉了var 就變成定義了全局變量了
alert(a);
}
test();
alert(a);
</script>
複製代碼
正確答案是: 100, 10, 10
var oldObject ="sdf";
var newObject = JSON.parse(JSON.stringify(oldObject));
console.log(newObject);
複製代碼
function(url, fn) {
// XMLHttpRequest對象用於在後臺與服務器交換數據
var obj = new XMLHttpRequest();
obj.open('GET', url, true);
obj.onreadystatechange = function() {
if(obj.readyState == 4 && obj.status == 200||obj.status == 304){
loading.style.display = "none"
} else {
alert("不能點擊,哈哈哈!");
}
};
obj.send(null);
}
複製代碼
// 建立一個1-10000的數組集合
var arr = new Array(10000).fill('').map((item, index) => {
return index + 1
}
)
// 篩選出了全部帶0的數字
var nerArrrr = arr.filter(item => /0/.test(item))
var length = nerArrrr.reduce((count, item) => {
return count + (String(item).match(/0/g)).length
}, 0)
console.log(length)
複製代碼
var arr = [[0,1,2,3], [4,5,6,7], [8,9,0,1], [2,3,4,5]];
// 方法一
var result = [];
for(var i=0;i<arr.length;i++){
for(var j=0;j<arr[i].length;j++){
result.push(arr[i][j]);
}
}
// 方法二
var result = [];
for(var i=0;i<arr.length;i++){
result = result.concat(arr[i]);
}
// 方法三
function Jw(obj){
return Array.prototype.concat.apply([],obj);
}
Jw(arr);
複製代碼
function getUrlDic(){
var queryDec = window.location.search.substring(1).split("&")
var decObect = {}
for(var i = 0; i < queryDec.length; i++){
var searchHash = queryDec[i].split("=")
var key = decodeURIComponent(searchHash[0])
var value = decodeURIComponent(searchHash[1])
decObect[key] = value
}
console.log(decObect)
}
getUrlDic()
複製代碼
let str = 'asfjasiofoivnoi';
function count(str){
let obj = {},
arr = str.split('');
//遍歷數組
arr.forEach(function(val,index){
//將數組的元素存入對象,初始值爲1,若是後面遍歷的元素以前已存在就+1
if(obj[val]){
obj[val]+=1;
}else{
obj[val]=1
}
})
//遍歷對象中的屬性(字符),值(出現的次數)
let num=0
for(let key in obj){
if(num < obj[key]){
//將最多的次數賦給num
num = obj[key];
}
}
for(let key in obj){
if(num == obj[key]){
console.log('最多的字符串是'+key+', 出現次數是'+num);
}
}
}
count(str);
複製代碼
一、首先看一個判斷題:null和undefined 是否相等
console.log(null==undefined)//true
console.log(null===undefined)//false
typeof null; // "object"
typeof undefined; // "undefined"
複製代碼
二、那到底何時是null,何時是undefined呢?null表示"沒有對象",即該處不該該有值。典型用法是
做爲函數的參數,表示該函數的參數不是對象。
做爲對象原型鏈的終點。
undefined表示"缺乏值",就是此處應該有一個值,可是尚未定義。典型用法是:
咱們知道 new 運算符是用來實例化一個類,從而在內存中分配一個實例對象。
new共通過了4幾個階段 一、建立一個空對象
var obj=new Object();
複製代碼
二、設置原型鏈
obj.__proto__= Base.prototype;
複製代碼
三、讓Base中的this指向obj,並執行Base的函數體。
var result =Base.call(obj);
複製代碼
四、判斷Base的返回值類型:若是是值類型,返回obj。若是是引用類型,就返回這個引用類型的對象。
if (typeof(result) == "object"){
Base=result;
}
else{
Base=obj;;
}
複製代碼
defer和async都是可選的,且只對外部腳本文件有效
<script src="main.js"></script>
複製代碼
瀏覽器會當即加載並執行指定的腳本,「當即」指在渲染該script標籤之下的文檔元素以前,也就是說不等待後續載入的文檔元素,讀到就加載並執行。
<script async src="main.js"></script>
複製代碼
瀏覽器會當即下載腳本,但不妨礙頁面中的其餘操做,好比下載其餘資源或等待加載其餘腳本。加載和渲染後續文檔元素的過程和main.js的加載與執行並行進行(異步)。
async不保證按照腳本出現的前後順序執行,所以,確保二者以前互不依賴很是重要,指定async屬性的目的是不讓頁面等待兩個腳本的下載和執行,從而異步加載頁面其餘內容,建議異步腳本不要在加載期間修改DOM。
異步腳本必定會在頁面的load事件前執行,但可能會在DOMContentLoaded事件觸發以前或以後執行。
<script defer="defer" src="main1.js"></script>
<script defer="defer" src="main2.js"></script>
複製代碼
表示腳本會被延遲到文檔徹底被解析和顯示以後再執行,加載後續文檔元素的過程將和main.js的加載並行進行(異步)。HTML5規範要求腳本按照它們出現的前後順序執行,所以第一個延遲腳本會先於第二個延遲腳本執行,而這兩個腳本會先於DOMContentLoaded事件。在現實當中,延遲腳本並不必定會按照順序執行,也不必定會在DOMContentLoaded事件觸發前執行,所以***最好只包含一個延遲腳本。***
defer和async、動態建立DOM方式(建立script,插入到DOM中,加載完畢後callBack)、按需異步載入js
首先傳輸對象的雙向數據綁定 Object.defineProperty(target, key, decription),在decription中設置get和set屬性(此時應注意description中get和set不能與描述屬性共存) 數組的實現與對象不一樣。
let obj = {}
let input = document.getElementById('input')
let span = document.getElementById('span')
Object.defineProperty(obj, 'text', {
configurable: true,
enumerable: true,
get() {
console.log('獲取數據了')
},
set(newVal) {
console.log('數據更新了')
input.value = newVal
span.innerHTML = newVal
}
})
input.addEventListener('keyup', function(e) {
obj.text = e.target.value
})
複製代碼
同時運用觀察者模式實現wather, 完成用戶數據和view視圖的更新
function getQueryVariable(variable)
{
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("=");
if(pair[0] == variable){return pair[1];}
}
return(false);
}
複製代碼
setState() 將老是觸發一次重繪,除非在 shouldComponentUpdate() 中實現了條件渲染邏輯。若是可變對象被使用了,但又不能在 shouldComponentUpdate() 中實現這種邏輯,僅在新 state 和以前的 state 存在差別的時候調用 setState() 能夠避免沒必要要的從新渲染。
react setState後:
setState—常規狀況:在同一個方法中屢次setState是會被合併的,而且對相同屬性的設置只保留最後一次的設置 參考詳情
初始化階段,這是組件即將開始其生命之旅並進入 DOM 的階段。
getDefaultProps:獲取實例的默認屬性
getInitialState:獲取每一個實例的初始化狀態
componentWillMount:組件即將被裝載、渲染到頁面上,在渲染以前執行,在客戶端和服務器端都會執行
render:組件在這裏生成虛擬的 DOM 節點
componentDidMount:僅在第一次渲染後在客戶端執行,組件真正在被裝載以後(請求數據)
運行中狀態;一旦組件被添加到 DOM,它只有在 prop 或狀態發生變化時纔可能更新和從新渲染。這些只發生在這個階段。
componentWillReceiveProps:經過父組件修props改時候調用,當從父類接收到 props 而且在調用另外一個渲染器以前調用。
shouldComponentUpdate:(nextProps及nextState)組件接受到新屬性或者新狀態的時候(能夠返回 false,接收數據後不更新,阻止 render 調用,後面的函數不會被繼續執行了)
componentWillUpdate:在 DOM 中進行渲染以前調用,組件即將更新不能修改屬性和狀態
render:組件從新描繪
componentDidUpdate:在渲染髮生後當即調用,組件已經更新
銷燬階段,這是組件生命週期的最後階段,組件被銷燬並從 DOM 中刪除
componentWillUnmount:組件被卸載的時候調用。在此方法中執行任何須要的清理,通常在componentDidMount裏面註冊的事件須要在這裏刪除,例如使計時器無效、取消網絡請求或清除在組件,清理內存空間
Cookies就是服務器暫存放在你的電腦裏的文本文件,好讓服務器用來辨認你的計算機。當你在瀏覽網站的時候,Web服務器會先送一小小資料放在你的計算機上,Cookies 會幫你在網站上所打的文字或是一些選擇都記錄下來。當下次你再訪問同一個網站,Web服務器會先看看有沒有它上次留下的Cookies資料,有的話,就會依據Cookie裏的內容來判斷使用者,送出特定的網頁內容給你。
方法一:Array.from()方法能夠將Set結構轉化爲數組結構
function unique(array) {
return Array.from(new Set(array));
}
unique([1,2,3,3]);
複製代碼
方法二:擴展運算符(…)內部使用for…of循環
let arr = [1,2,3,3];
let unique = [...new Set(arr)];
複製代碼
方法三
function unique(arr){
var isRepeated, result = [];
for(var i=0; i<arr.length; i++){
isRepeated = false;
for(var j=0; j<result.length; j++){
if(arr[i] === result[j]){
isRepeated = true;
break;
}
}
if(!isRepeated){
result.push(arr[i]);
}
}
return result;
}
var arr = [1,2,3,4,3,2,1,2,3];
console.log(unique(arr));
複製代碼
對內:模塊模式
對外:繼承
代碼重用
避免全局變量(命名空間,封閉空間,模塊化mvc..)
拆分函數避免函數過於臃腫
註釋
子構造函數中執行父構造函數,並用call\apply改變this 克隆父構造函數原型上的方法
react總體是函數式的思想,把組件設計成純組件,狀態和邏輯經過參數傳入,因此在react中,是單向數據流,推崇結合immutable來實現數據不可變。react在setState以後會從新走渲染的流程,若是shouldComponentUpdate返回的是true,就繼續渲染,若是返回了false,就不會從新渲染,PureComponent就是重寫了shouldComponentUpdate,而後在裏面做了props和state的淺層對比。
而vue的思想是響應式的,也就是基因而數據可變的,經過對每個屬性創建Watcher來監聽,當屬性變化的時候,響應式的更新對應的虛擬dom。
總之,react的性能優化須要手動去作,而vue的性能優化是自動的,可是vue的響應式機制也有問題,就是當state特別多的時候,Watcher也會不少,會致使卡頓,因此大型應用(狀態特別多的)通常用react,更加可控。
// 第一種
#container{
position:relative;
}
#center{
width:100px;
height:100px;
position:absolute;
top:50%;
left:50%;
transform: translate(-50%,-50%);
}
// 第二種
#container{
position:relative;
}
#center{
width:100px;
height:100px;
position:absolute;
top:50%;
left:50%;
margin:-50px 0 0 -50px;
}
// 第三種
#container{
position:relative;
}
#center{
position:absolute;
margin:auto;
top:0;
bottom:0;
left:0;
right:0;
}
// 第四種 flex
#container{
display:flex;
justify-content:center;
align-items: center;
}
複製代碼
JSON.stringify(obj)==JSON.stringify(obj);//true
複製代碼
router-link
router.go(1)
router.push('/')
複製代碼
router 是 hash 改變
location.href 是頁面跳轉,刷新頁面
複製代碼
部分渲染樹(或者整個渲染樹)須要從新分析而且節點尺寸須要從新計算。這被稱爲重排。注意這裏至少會有一次重排-初始化頁面佈局。 因爲節點的幾何屬性發生改變或者因爲樣式發生改變,例如改變元素背景色時,屏幕上的部份內容須要更新。這樣的更新被稱爲重繪。
git stash //將本次修改存到暫存區(緊急切換分支時)
git stash list
git stash pop //將全部暫存區的內容取出來
複製代碼
git add # 將工做區的修改提交到暫存區
git commit # 將暫存區的修改提交到當前分支
git reset # 回退到某一個版本
git stash # 保存某次修改
git pull # 從遠程更新代碼
git push # 將本地代碼更新到遠程分支上
git reflog # 查看歷史命令
git status # 查看當前倉庫的狀態
git diff # 查看修改
git log # 查看提交歷史
git revert # 回退某個修改
複製代碼
html文件是自上而下的執行方式,但引入的css和javascript的順序有所不一樣,css引入執行加載時,程序仍然往下執行,而執行到script腳本是則中斷線程,待該script腳本執行結束以後程序才繼續往下執行。 因此,大部分網上討論是將script腳本放在body以後,那樣dom的生成就不會由於長時間執行script腳本而延遲阻塞,加快了頁面的加載速度。 但又不能將全部的script放在body以後,由於有一些頁面的效果的實現,是須要預先動態的加載一些js腳本。因此這些腳本應該放在body以前。 其次,不能將須要訪問dom元素的js放在body以前,由於此時尚未開始生成dom,因此在body以前的訪問dom元素的js會出錯,或者無效 script放置位置的原則「頁面效果實現類的js應該放在body以前,動做,交互,事件驅動,須要訪問dom屬性的js均可以放在body以後
npm install
npm run dev
npm run build
安裝模塊;
-save-dev 是指將包信息添加到 package.json 裏的 devDependencies節點,表示開發時依賴的包。
npm install --save-dev
-save 是指將包信息添加到 package.json 裏的dependencies節點,表示發佈時依賴的包。
npm install --save
複製代碼
keep-alive是Vue.js的一個內置組件。它可以把不活動的組件實例保存在內存中,而不是直接將其銷燬,它是一個抽象組件,不會被渲染到真實DOM中,也不會出如今父組件鏈中。 它提供了include與exclude兩個屬性,容許組件有條件地進行緩存。
(1)域名解析 在瀏覽器地址欄輸入URL,瀏覽器查看緩存,判斷請求資源是否新鮮,瀏覽器解析URL獲取協議,主機,端口,path。瀏覽器組裝一個HTTP(GET)請求報文,瀏覽器獲取主機ip地址(從緩存、hosts、路由、DNS解析等)
(2)TCP鏈接HTTP協議是使用TCP協議做爲其傳輸層協議的,在拿到服務器的IP地址後,瀏覽器客戶端會與服務器創建TCP鏈接。該過程包括三次握手
第一次握手:創建鏈接時,客戶端向服務端發送請求報文 第二次握手:服務器收到請求報文後,如贊成鏈接,則向客戶端發送確認報文 第三次握手,客戶端收到服務器的確認後,再次向服務器給出確認報文,完成鏈接。
三次握手主要是爲了防止已經失效的請求報文字段發送給服務器,浪費資源。 **(3)瀏覽器發送HTTP請求 瀏覽器構建http請求報文,並經過TCP協議傳送到服務器的指定端口。http請求報文一共包括三個部分: 請求行:指定http請求的方法、url、http協議版本等 請求頭:描述瀏覽器的相關信息,語言、編碼等,是否包含緩存驗證信息若是驗證緩存新鮮,返回304 請求正文:當發送POST,PUT等請求時,一般須要向服務器傳遞數據。這些數據就儲存在請求正文中。
(4)瀏覽器接受相應
而後根據狀況選擇關閉TCP鏈接或者保留重用; 若是資源可緩存,進行緩存; 對響應進行解碼(例如gzip壓縮); 根據資源類型決定如何處理(假設資源爲HTML文檔);
(6)瀏覽器頁面渲染 解析HTML文檔,構件DOM樹,下載資源,構造CSSOM樹,執行js腳本,這些操做沒有嚴格的前後順序,如下分別解釋 構建DOM樹: 根據HTML規範將字符流解析爲標記 詞法分析將標記轉換爲對象並定義屬性和規則 根據HTML標記關係將對象組成DOM樹 解析過程當中遇到圖片、樣式表、js文件,啓動下載 構建CSSOM樹: 字符流轉換爲標記流 根據標記建立節點 節點建立CSSOM樹 根據DOM樹和CSSOM樹構建渲染樹: 從DOM樹的根節點遍歷全部可見節點,不可見節點包括:
- script,meta這樣自己不可見的標籤
- 被css隱藏的節點,如display: none
複製代碼
對每個可見節點,找到恰當的CSSOM規則並應用 發佈可視節點的內容和計算樣式
js解析以下:
瀏覽器建立Document對象並解析HTML,將解析到的元素和文本節點添加到文檔中,此時document.readystate爲loading HTML解析器遇到沒有async和defer的script時,將他們添加到文檔中,而後執行行內或外部腳本。這些腳本會同步執行,而且在腳本下載和執行時解析器會暫停。這樣就能夠用document.write()把文本插入到輸入流中。同步腳本常常簡單定義函數和註冊事件處理程序,他們能夠遍歷和操做script和他們以前的文檔內容 當解析器遇到設置了async屬性的script時,開始下載腳本並繼續解析文檔。腳本會在它下載完成後儘快執行,可是解析器不會停下來等它下載。異步腳本禁止使用document.write(),它們能夠訪問本身script和以前的文檔元素 當文檔完成解析,document.readState變成interactive 全部defer腳本會按照在文檔出現的順序執行,延遲腳本能訪問完整文檔樹,禁止使用document.write() 瀏覽器在Document對象上觸發DOMContentLoaded事件 此時文檔徹底解析完成,瀏覽器可能還在等待如圖片等內容加載,等這些內容完成載入而且全部異步腳本完成載入和執行,document.readState變爲complete,window觸發load事件 顯示頁面(HTML解析過程當中會逐步顯示頁面)
引入JsBridge(安卓)或WebViewJavascriptBridge(iOS)庫的方案,首先安卓、iOS、web前端三方要在一塊兒定義好須要使用的接口的方法名及傳遞的參數,三方統一,定義好各個方法及傳遞的方式
redux中間件中間件提供第三方插件的模式,自定義攔截 action -> reducer 的過程。變爲 action -> middlewares -> reducer 。這種機制可讓咱們改變數據流,實現如異步 action ,action 過濾,日誌輸出,異常報告等功能。常見的中間件:
根據組件的職責一般把組件分爲UI組件和容器組件。UI 組件負責 UI 的呈現,容器組件負責管理數據和邏輯。二者經過React-Redux 提供connect方法聯繫起來。、
虛擬dom至關於在js和真實dom中間加了一個緩存,利用dom diff算法避免了沒有必要的dom操做,從而提升性能。
具體實現步驟以下:用 JavaScript 對象結構表示 DOM 樹的結構;而後用這個樹構建一個真正的 DOM 樹,插到文檔當中當狀態變動的時候,從新構造一棵新的對象樹。而後用新的樹和舊的樹進行比較,記錄兩棵樹差別把2所記錄的差別應用到步驟1所構建的真正的DOM樹上,視圖就更新了。
把樹形結構按照層級分解,只比較同級元素。給列表結構的每一個單元添加惟一的key屬性,方便比較。React 只會匹配相同class的component (這裏面的class指的是組件的名字)合併操做,調用 component 的 setState 方法的時候, React 將其標記爲 dirty.到每個事件循環結束, React 檢查全部標記 dirty 的component從新繪製.選擇性子樹渲染。開發人員能夠重寫shouldComponentUpdate提升diff的性能。