安裝
cnpm install typescripy -g
使用
在命令行上,運行TypeScript編譯器:
輸出結果為一個a.js文件,它包含了和輸入文件中相同的JavsScript代碼。
tsc a.ts ---------------- 把a.ts文件編譯成a.js文件
在vscode中自動編譯
- 運行命令:
tsc --init-------> 生成tsconfig.json文件 - 點擊
任務---->運行任務--------->tsc:監(jiān)視 - tsconfig.json
在tsconfig.json文件中:
outDir: 表示js文件的生成目錄
比如:生成在根目錄的js文件夾中 ------------> outDir: './js'
數據類型
- string
- number
- boolean
- 數組
有兩種方法可以定義數組:
(1)第一種,可以在元素類型后面接上 [],表示由此類型元素組成的一個數組
let list: number[] = [1, 2, 3]; -------------- 由number類型元素組成的數組
(2)第二種方式是使用數組泛型,Array<元素類型>:
let list: Array<number> = [1, 2, 3];
- 元組Tuple
tuple:是元組的意思
元組類型允許表示一個已知元素數量和類型的數組,各元素的類型不必相同。
// Declare a tuple type
let x: [string, number];
// Initialize it
x = ['hello', 10]; // OK
// Initialize it incorrectly
x = [10, 'hello']; // Error ------------------- 不能交換位置,只能按順序
6.枚舉enum
enum類型是對JavaScript標準數據類型的一個補充。 像C#等其它語言一樣,使用枚舉類型可以為一組數值賦予友好的名字。
enum Color {Red = 1, Green, Blue} ---- 默認情況下,從0開始為元素編號。 你也可以手動的指定成員的數值。
let c: Color = Color.Green; ---------- 結果是2
- 枚舉類型提供的一個便利是你可以由枚舉的值得到它的名字
enum Color {Red = 1, Green, Blue}
let colorName: string = Color[2];
alert(colorName); // 顯示'Green'因為上面代碼里它的值是
7.Any
有時候,我們會想要為那些在編程階段還不清楚類型的變量指定一個類型。 這些值可能來自于動態(tài)的內容,比如來自用戶輸入或第三方代碼庫。 這種情況下,我們不希望類型檢查器對這些值進行檢查而是直接讓它們通過編譯階段的檢查。 那么我們可以使用 any類型來標記這些變量:
let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false; // okay, definitely a boolean
let list: any[] = [1, true, "free"]; -------------- 成員可以是任何類型
list[1] = 100;
let a: number | undefined
a=20; --------------- true
a=undefined ---------- true
8.Void ------------------------------ 一般用于定義方法沒有返回值
某種程度上來說,void類型像是與any類型相反,它表示沒有任何類型。 當一個函數沒有返回值時,你通常會見到其返回值類型是 void:
function warnUser(): void { ------------------------------- 正確
alert("This is my warning message");
}
function warnUser(): undefined { -------------------------- 錯誤
alert("This is my warning message");
}
function a(): number { ------------------------------- 正確
return 123;
}
- 聲明一個void類型的變量沒有什么大用,因為你只能為它賦予undefined和null:
let unusable: void = undefined; ----------- viod類型的變量只能賦予 undefined和null
9.Null 和 Undefined
TypeScript里,undefined和null兩者各自有自己的類型分別叫做undefined和null。 和 void相似,它們的本身的類型用處不是很大:
- 默認情況下null和undefined是所有類型的子類型。 就是說你可以把 null和undefined賦值給number類型等任意類型的變量。
然而,當你指定了--strictNullChecks標記,null和undefined只能賦值給void和它們各自。
10.Never -----------------------------------------包含null和undefined
never類型表示的是那些永不存在的值的類型。 例如, never類型是那些總是會拋出異?;蚋揪筒粫蟹祷刂档暮瘮当磉_式或箭頭函數表達式的返回值類型; 變量也可能是 never類型,當它們被永不為真的類型保護所約束時。
never類型是任何類型的子類型,也可以賦值給任何類型;然而,沒有類型是never的子類型或可以賦值給never類型(除了never本身之外)。 即使 any也不可以賦值給never。
類型斷言
有時候你會遇到這樣的情況,你會比TypeScript更了解某個值的詳細信息。 通常這會發(fā)生在你清楚地知道一個實體具有比它現有類型更確切的類型。
通過類型斷言這種方式可以告訴編譯器,“相信我,我知道自己在干什么”。 類型斷言好比其它語言里的類型轉換,但是不進行特殊的數據檢查和解構。 它沒有運行時的影響,只是在編譯階段起作用。 TypeScript會假設你,程序員,已經進行了必須的檢查。
類型斷言有兩種形式。
- 其一是“尖括號”語法:
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length; ---------------- someValue一定是一個字符串
- 另一個為as語法:
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;
接口:
關鍵詞: interface
interface LabelledValue { ----------------- interface聲明接口
label: string; ------------------------------- 注意這里是分號,但LabelledValue是個對象
}
function printLabel(labelledObj: LabelledValue) { --- 參數是一個對象,必須有l(wèi)abel屬性,并且是個字符串
console.log(labelledObj.label);
}
let myObj = {size: 10, label: "Size 10 Object"}; ---- 雖然可以傳入size,但是在函數中調用時還是會報錯
printLabel(myObj);
注意:
參數定義在外部,只要包含接口中的屬性就可以,而直接寫在調用函數的內部,則只能是接口中的屬性個數
如果是printLabel({size: 10, label: "Size 10 Object"}); 報錯 -------- 錯
如果是printLabel({ label: "Size 10 Object"}); --------------------- 對
可選屬性 ?
可選屬性就是在接口對象中的屬性后面加上?
- 可選屬性的好處之一是可以對可能存在的屬性進行預定義,
- 好處之二是可以捕獲引用了不存在的屬性時的錯誤。
比如,我們故意將 createSquare里的color屬性名拼錯,就會得到一個錯誤提示:
interface SquareConfig {
color?: string;
width?: number;
}
function createSquare(config: SquareConfig): { color: string; area: number } {
let newSquare = {color: "white", area: 100};
if (config.clor) {
// Error: Property 'clor' does not exist on type 'SquareConfig'
newSquare.color = config.clor;
}
if (config.width) {
newSquare.area = config.width * config.width;
}
return newSquare;
}
let mySquare = createSquare({color: "black"});
訪問修飾符
private表示私有,私有屬性和方法只能在該類中使用,在 子類和實例對象中都不能使用
- public
- private
派生類
關鍵字:extends
- 基類,派生類
- ( 基類 ) 通常叫做 ( 超類 )
- ( 派生類 ) 通常叫做 ( 子類 )
(一) 在Table中,編輯每一行的值,當Antd-Modal-Form-FormItem-initialValue 表單的每項獲得初始值后,改變其中某個input框的值,影響其他行的table-modal-form的input值
( Modal中內嵌Form表單的initialValue值不動態(tài)更新問題 )
( 編輯第一行的input,影響第二行的input )
- 原因分析:當第一個打開modal時,modal被掛載,form獲得initialValue值,再次打開modal時,modal并沒有被重新掛載(只是被css隱藏了), 所以form中是上一次改變后input的值。
- 解決方案: Modal窗口我們都有應用一個Visible來控制是否顯示, 我們只要利用這個值得變化就可以實現Modal組件的重新掛載了。
{
this.state.showModal ? <Modal></Modal> : null
}
false的時候,不掛載Modal
true的時候,掛載
https://blog.csdn.net/u013558749/article/details/79105531/
(二) react-intl 國際化
- 安裝
cnpm install react-intl --save
- 包含的組件
(1) addLocaleData
(2) IntlProvider ----- 包裹需要國際化的根組件 ( local屬性,message屬性 )
- 使用<IntlProvider>組件包裹需要實現國際化的根組件
- intlProvider --- 組件包含兩個屬性 :
local,message
index.js根組件:
import{ addLocaleData, IntlProvider } from 'react-intl'; --- 引入 addLocaleData 和 IntlProvider
添加多種語言對應的文本,自己新建兩個js文件或者json文件
import enus from './locales/en-us';
import zhcn from './locales/zh-cn';
載入語言環(huán)境數據
import enLocaleData from 'react-intl/locale-data/en'
import zhLocaleData from 'react-intl/locale-data/zh'
// addLocaleData(enLocaleData) //注冊區(qū)域設置數據
// addLocaleData(zhLocaleData) //注冊區(qū)域設置數據
addLocaleData([...enLocaleData, ...zhLocaleData]) ------------ 使用addLocalData載入語言環(huán)境數據
<Provider store={store}>
<IntlProvider locale={'zh'} messages={zhcn} > ------------- interProvider組件
<BrowserRouter>
...
</BrowserRouter>
</IntlProvider>
</Provider>
, document.getElementById('root'));
(3) injectIntl 和 FormattedMesssage
React Intl 提供一個API,injectIntl,可以把命令式格式化的 API 注入到任意組件的props中。然后可以在那個組件中通過this.props.intl直接去調用一些API和屬性,
比如this.props.intl.locale的值就是當前語言了。
- FormattedMesssage組件
- injectIntl包裹子組件后,通過this.props.intl.formatMessage({.....})來國際化
<FormattedMessage id="table.edit"/>
---------------
定義:
formatMessage = (...args) => {
const {intl: {formatMessage}} = this.props;
return formatMessage(...args)
};
調用:
this.formatMessage({id: "modal.saveError"})
FormattedMessageFormattedDateFormattedTime- 使用:
zh-cn.js
const b = {
"home.name": "王 {type}"
}
export default b;
------------------------
組件中
import { FormattedMessage, FormattedDate, FormattedTime, injectIntl } from 'react-intl';
<FormattedMessage
id = "home.name"
values={{ type: '學生啊'}}
/>
<FormattedDate
value={ new Date() }
/>
運算符優(yōu)先級
- 最高優(yōu)先級:
----------> 屬性訪問.()[] - 一元操作符是除了屬性訪問操作符外,具有最高的優(yōu)先級
-----------> 一元+,一元-,遞增,遞減,typeof,delete,void等 - 除逗號外,最低優(yōu)先級:
----------> 賦值運算符=
結合性--------------優(yōu)先級相同時的順序
- 左結合:除了一元,三元,賦值以外的,都是左結合
- 右結合:一元運算符,三元運算符,賦值運算符 (從右往左算)

https://www.cnblogs.com/liushui-sky/p/7993122.html
只有一元運算符,三元運算符,賦值運算符是右結合,其他的都是左結合
列子
const a = 2 < 1 ? 20 : 3 > 1 ? 200 : 2000 // 200
因為三元運算符是右結合,所以上面的代碼相當于
const a = 2 < 1 ? 20 : ( 3 > 1 ? 200 : 2000 ) ------------------------- 先算右邊的
事件模型
事件的本質是程序各個組成部分之間的一種通信方式,也是異步編程的一種實現
EventTarget 接口
dom的事件操作,監(jiān)聽和觸發(fā),都定義在eventTarget接口,所有節(jié)點對象都部署了這個接口
EventTarget 接口提供三個實例方法 :
- addEventListener:綁定事件的監(jiān)聽函數
- removeEventListener:移除事件的監(jiān)聽函數
- dispatchEvent:觸發(fā)事件
EventTarget.addEventListener()
EventTarget.addEventListener()綁定事件的監(jiān)聽函數,一旦該事件發(fā)生,就會觸發(fā)執(zhí)行綁定的監(jiān)聽函數,沒有返回值
EventTarget.addEventListener()用于在當前節(jié)點或對象上,定義一個特定事件的監(jiān)聽函數。一旦這個事件發(fā)生,就會執(zhí)行監(jiān)聽函數。
該方法沒有返回值。
target.addEventListener(type, listener, useCapture);
type: 事件名稱,大小寫敏感
listener: 監(jiān)聽函數,事件發(fā)生時,觸發(fā)該事件
useCapture: 監(jiān)聽函數是否在捕獲階段觸發(fā),默認是false,即只在冒泡階段觸發(fā)
關于 ( 參數 ) 需要注意兩個地方:
- 第二個參數除了是
監(jiān)聽函數以外,還可以是一個具有handleEvent 方法的對象
handleEvent詳細介紹: http://www.itdecent.cn/p/13a0e7f4c335
componentDidMount() {
const a = document.getElementById('test');
a.addEventListener('click', {
handleEvent: function(e) {console.log(e)},
},false)
}
- 第三個參數除了是
useCapture布爾值以外,還可以是一個屬性配置對象
capture:布爾值,表示該事件是否在捕獲階段觸發(fā)監(jiān)聽函數。
once:布爾值,表示監(jiān)聽函數是否只觸發(fā)一次,然后就自動移除。
passive:布爾值,表示監(jiān)聽函數不會調用事件的preventDefault方法。
如果監(jiān)聽函數調用了,瀏覽器將忽略這個要求,并在監(jiān)控臺輸出一行警告。
-
addEventListener可以為當前對象的同一事件,添加不同的監(jiān)聽函數,這些函數按照添加順序觸發(fā),即先添加先觸發(fā)。
- 如果為同一個事件多次添加同一個監(jiān)聽函數,該函數只會執(zhí)行一次,多余的添加將自動被去除(不必使用removeEventListener方法手動去除)。
function hello() {
console.log('Hello world');
}
document.addEventListener('click', hello, false);
document.addEventListener('click', hello, false);
執(zhí)行上面代碼,點擊文檔只會輸出一行Hello world。
- 如果希望向監(jiān)聽函數傳遞參數,可以用 匿名函數 包裝 監(jiān)聽函數
function print(x) {
console.log(x);
}
var el = document.getElementById('div1');
el.addEventListener('click', function () { print('Hello'); }, false);
addEventListener(type, listener, useCapture)
-
監(jiān)聽函數內部中的this,指向 ( 當前事件 ) 所在的那個 ( 對象 )
class App extends Component {
componentDidMount() {
const a = document.getElementById('test');
a.addEventListener('click', function(e) {console.log(this.nodeName)}, false)
} ------------------------------ 監(jiān)聽函數中的this,指向當前事件所在的對象 // span
render() {
return (
<div className="App">
<div>aaaa <span id="test">×</span> </div>
</div>
);
}
}
componentDidMount() {
const a = document.getElementById('test');
a.addEventListener('click', function(e) {console.log(this.nodeName)}, false);
a.addEventListener(
'click',
function(e) {console.log(this.nodeName + '可以為同一個對象的同一個事件綁定不同的監(jiān)聽函數')},
false);
a.addEventListener('click', function(){ go('重慶') }, false);
----- 如果要向監(jiān)聽函數傳遞參數,可以用匿名函數來包裝一下監(jiān)聽函數
const b = document.getElementById('test-wrapper');
b.addEventListener('click', {
handleEvent: function(e) {
console.log('第二個參數可以是一個具有 handleEvent方法的對象')
}
}, {
capture: false, ------- 是否在捕獲階段觸發(fā)監(jiān)聽函數
once: false, --------- 是否只觸發(fā)一次監(jiān)聽函數,然后自動移除
passive: true --------- 表示監(jiān)聽函數不會調用事件的preventDefault方法
});
----- 第二個參數可以是具有handleEvent方法的對象,
----- 第三個參數可以省略,默認是false,在冒泡階段觸發(fā),第三個參數也可以是配置對象
function go(params) {
console.log(params)
}
}
EventTarget.removeEventListener()
EventTarget.removeEventListener方法用來移除addEventListener方法添加的事件監(jiān)聽函數。該方法沒有返回值。
- removeEventListener方法的參數,與addEventListener方法完全一致。
- 注意:
removeEventListener()方法移除的監(jiān)聽函數,必須是addEventListener()方法添加的監(jiān)聽函數,并且必須在同一個元素節(jié)點,否則無效。
div.addEventListener('click', function (e) {}, false);
div.removeEventListener('click', function (e) {}, false);
上面代碼中,removeEventListener方法無效,因為監(jiān)聽函數不是同一個匿名函數。
element.addEventListener('mousedown', handleMouseDown, true);
element.removeEventListener("mousedown", handleMouseDown, false);
上面代碼中,removeEventListener方法也是無效的,因為第三個參數不一樣。
EventTarget.dispatchEvent()
EventTarget.dispatchEvent方法在當前節(jié)點上觸發(fā)指定事件,從而觸發(fā)監(jiān)聽函數的執(zhí)行。該方法返回一個布爾值,只要有一個監(jiān)聽函數調用了Event.preventDefault(),則返回值為false,否則為true。
- dispatchEvent() 在當前節(jié)點上觸發(fā)指定事件-----------> 從而觸發(fā)監(jiān)聽函數執(zhí)行
dispatchEvent() 方法的參數是一個Event對象的實例- 有返回值,只有有一個監(jiān)聽函數設置了 preventDefault() 就返回 false
para.addEventListener('click', hello, false); ----------- 觸發(fā)event事件后,會觸發(fā)事件監(jiān)聽函數hello
var event = new Event('click'); ----------- Event構造函數,生成'click'事件實例
para.dispatchEvent(event); ----------------- 在para節(jié)點上,觸發(fā) event 事件
總結:
1. EventTarget.dispatchEvent()觸發(fā)當前節(jié)點指定的事件,參數是Event對象的實例。
2. EventTarget.dispatchEvent()返回boolean值,只要有一個監(jiān)聽函數調用了 preventDefault函數,就返回false
3. EventTarget.dispatchEvent()參數為空,或者不是一個有效的事件對象,就會報錯
- 如果dispatchEvent方法的參數為空,或者不是一個有效的事件對象,將報錯。
監(jiān)聽函數
瀏覽器的事件模型,就是通過監(jiān)聽函數(listener)對事件做出反應。事件發(fā)生后,瀏覽器監(jiān)聽到了這個事件,就會執(zhí)行對應的監(jiān)聽函數。這是事件驅動編程模式(event-driven)的主要編程方式。
JavaScript 有三種方法,可以為事件綁定監(jiān)聽函數。
HTML 的 on- 屬性 ------- 只會在冒泡階段觸發(fā)監(jiān)聽函數
- 元素的事件監(jiān)聽屬性,都是on加上事件名,比如onload就是on + load,表示load事件的監(jiān)聽代碼。
- 注意,
這些屬性的值是將會執(zhí)行的代碼,而不是一個函數。 - 使用這個方法指定的監(jiān)聽代碼,只會在冒泡階段觸發(fā)。
- 直接設置on-屬性,與通過元素節(jié)點的setAttribute方法設置on-屬性,效果是一樣的。
<!-- 正確 -->
<body onload="doSomething()"> ----------- 值是將要執(zhí)行的代碼,而不是函數,即必須調用
<!-- 錯誤 -->
<body onload="doSomething">
<div onClick="console.log(2)">
<button onClick="console.log(1)">點擊</button>
</div>
由于on-屬性的監(jiān)聽代碼,只在冒泡階段觸發(fā),所以點擊結果是先輸出1,再輸出2,
即事件從子元素開始冒泡到父元素。
- 直接設置on-屬性,與通過元素節(jié)點的setAttribute方法設置on-屬性,效果是一樣的。
el.setAttribute('onclick', 'doSomething()');
// 等同于
// <Element onclick="doSomething()">
元素節(jié)點的事件屬性
- 元素節(jié)點對象 的事件屬性,同樣可以指定監(jiān)聽函數。
- 使用這個方法指定的監(jiān)聽函數,也是只會在冒泡階段觸發(fā)。
- 缺點: 同一個事件只能定義一個監(jiān)聽函數
- 注意,
(元素節(jié)點對象的 事件屬性 )這種方法與 HTML 的on-屬性的差異是:
- 元素節(jié)點對象的 事件屬性: ------它的值是函數名(doSomething),
- HTML 的on-屬性: ------必須給出完整的監(jiān)聽代碼(doSomething())。
window.onload = doSomething;
div.onclick = function (event) { ----------------- 注意這種寫法不是駝峰寫法
console.log('觸發(fā)事件');
};
小結
上面三種方法,
第一種“HTML 的 on- 屬性”,違反了 HTML 與 JavaScript 代碼相分離的原則,將兩者寫在一起,不利于代碼分工,因此不推薦使用。
第二種“元素節(jié)點的事件屬性”的缺點在于,同一個事件只能定義一個監(jiān)聽函數,也就是說,如果定義兩次onclick屬性,后一次定義會覆蓋前一次。因此,也不推薦使用。
第三種EventTarget.addEventListener是推薦的指定監(jiān)聽函數的方法。它有如下優(yōu)點:
EventTarget.addEventListener() 優(yōu)點
- 同一個事件可以添加多個監(jiān)聽函數。
- 能夠指定在哪個階段(捕獲階段還是冒泡階段)觸發(fā)監(jiān)聽函數。
- 除了 DOM 節(jié)點,其他對象(比如window、XMLHttpRequest等)也有這個接口,它等于是整個 JavaScript 統(tǒng)一的監(jiān)聽函數接口。
EventTarget.addEventListener()的優(yōu)點:
1. 可以為同一個事件,指定不同的監(jiān)聽函數
2. 可以指定監(jiān)聽函數觸發(fā)的階段,默認是在useCapture捕獲階段觸發(fā)。第三個參數
3. 除了dom節(jié)點,其他對象也有這個接口。 window, XMLHttpRequest等
this 的指向
- 監(jiān)聽函數內部的this, 指向觸發(fā)事件的元素節(jié)點
監(jiān)聽函數中的this, 指向觸發(fā)事件的那個元素節(jié)點
事件的傳播
一個事件發(fā)生后,會在子元素和父元素之間傳播(propagation)。這種傳播分成三個階段。
- 第一階段:從window對象傳導到目標節(jié)點(上層傳到底層),稱為“捕獲階段”(capture phase)。
- 第二階段:在目標節(jié)點上觸發(fā),稱為“目標階段”(target phase)。
- 第三階段:從目標節(jié)點傳導回window對象(從底層傳回上層),稱為“冒泡階段”(bubbling phase)。
事件的傳播分為三個階段
第一階段是從window對象傳到到目標節(jié)點,是捕獲階段 capture phase
第二階段,在目標節(jié)點上觸發(fā),稱為目標階段,target phase
第三階段,從目標節(jié)點傳導到window對象,稱為冒泡階段 bubbling phase - phase是階段的意思
- bubbling是冒泡的意思
- capture是捕獲的意思
注意,瀏覽器總是假定click事件的目標節(jié)點,就是點擊位置嵌套最深的那個節(jié)點
也就是說,事件傳播順序,
在捕獲階段依次為window、document、html、body、div、p,
在冒泡階段依次為p、div、body、html、document、window。
事件的代理
由于事件會在冒泡階段向上傳播到父節(jié)點,因此可以把子節(jié)點的監(jiān)聽函數定義在父節(jié)點上,由父節(jié)點的監(jiān)聽函數統(tǒng)一處理多個子元素的事件。這種方法叫做事件的代理(delegation)。
- delegation 是委托,代理的意思
- 如果希望事件到某個節(jié)點為止,不再傳播,可以使用事件對象的stopPropagation方法。
- 但是,stopPropagation方法只會阻止事件的傳播,不會阻止該事件觸發(fā)<p>節(jié)點的其他click事件的監(jiān)聽函數。也就是說,不是徹底取消click事件。
// 事件傳播到 p 元素后,就不再向下傳播了
p.addEventListener('click', function (event) {
event.stopPropagation();
}, true);
// 事件冒泡到 p 元素后,就不再向上冒泡了
p.addEventListener('click', function (event) {
event.stopPropagation();
}, false);
- 如果想要徹底阻止這個事件的傳播,不再觸發(fā)后面所有click的監(jiān)聽函數,可以使用stopImmediatePropagation方法。
Event 對象概述
事件發(fā)生以后,會產生一個事件對象,作為參數傳給監(jiān)聽函數。瀏覽器原生提供一個Event對象,所有的事件都是這個對象的實例,或者說繼承了Event.prototype對象。
- Event對象本身就是一個構造函數,可以用來生成新的實例。
- event = new Event(type, options);
- Event構造函數接受兩個參數。
第一個參數type是字符串,表示事件的名稱;
第二個參數options是一個對象,表示事件對象的配置
bubbles:布爾值,可選,默認為false,表示事件對象是否冒泡。
cancelable:布爾值,可選,默認為false,表示事件是否可以被取消,
即能否用Event.preventDefault()取消這個事件。
一旦事件
- 被取消,就好像從來沒有發(fā)生過,不會觸發(fā)瀏覽器對該事件的默認行為。
- 注意,如果不是顯式指定bubbles屬性為true,生成的事件就只能在“捕獲階段”觸發(fā)監(jiān)聽函數。
// HTML 代碼為
// <div><p>Hello</p></div>
var div = document.querySelector('div');
var p = document.querySelector('p');
function callback(event) {
var tag = event.currentTarget.tagName;
console.log('Tag: ' + tag); // 沒有任何輸出
}
div.addEventListener('click', callback, false);
var click = new Event('click');
p.dispatchEvent(click);
上面代碼中,p元素發(fā)出一個click事件,該事件默認不會冒泡。
div.addEventListener方法指定在冒泡階段監(jiān)聽,因此監(jiān)聽函數不會觸發(fā)。
如果寫成div.addEventListener('click', callback, true),那么在“捕獲階段”可以監(jiān)聽到這個事件。
Event 對象的實例屬性
Event.bubbles,Event.eventPhase
- Event.bubbles屬性返回一個布爾值,表示當前事件是否會冒泡。屬性為只讀屬性,一般用來了解 Event 實例是否可以冒泡。
- Event.eventPhase屬性返回一個整數常量,表示事件目前所處的階段。該屬性只讀。
Event.eventPhase的返回值有四種可能。
0,事件目前沒有發(fā)生。
1,事件目前處于捕獲階段,即處于從祖先節(jié)點向目標節(jié)點的傳播過程中。
2,事件到達目標節(jié)點,即Event.target屬性指向的那個節(jié)點。
3,事件處于冒泡階段,即處于從目標節(jié)點向祖先節(jié)點的反向傳播過程中。
- 除非顯式聲明,Event構造函數生成的事件,默認是不冒泡的。
Event.cancelable,
Event.cancelBubble,
event.defaultPrevented
Event.cancelable屬性返回一個布爾值,表示事件是否可以取消。該屬性為只讀屬性,一般用來了解 Event 實例的特性。
大多數瀏覽器的原生事件是可以取消的。
Event.currentTarget,
Event.target
- Event.currentTarget屬性返回事件當前所在的節(jié)點,即正在執(zhí)行的監(jiān)聽函數所綁定的那個節(jié)點。
- Event.target屬性返回原始觸發(fā)事件的那個節(jié)點,即事件最初發(fā)生的節(jié)點。
-
事件傳播過程中,不同節(jié)點的監(jiān)聽函數內部的Event.target與Event.currentTarget屬性的值是不一樣的,前者總是不變的,后者則是指向監(jiān)聽函數所在的那個節(jié)點對象。
https://www.cnblogs.com/bo-haier/p/5644268.html
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
componentDidMount() {
const a = document.getElementById("one");
a.addEventListener('click', go, false);
function go(e) {
console.log(e.target, "e.target"); ----------------- 事件發(fā)出的節(jié)點,即點擊的那個節(jié)點
console.log(e.currentTarget, "e.currentTarget"); ---------------- 是監(jiān)聽函數綁定的元素節(jié)點
console.log(this, 'this'); ------------ 事件觸發(fā)所綁定的那個節(jié)點,即監(jiān)聽函數所在的節(jié)點
}
}
render() {
return <div className="App">
<div id="one" style={{ background: "yellow", padding: "20px" }}>
第一個節(jié)點
<div id="two" style={{ background: "silver", padding: "20px" }}>
第二個節(jié)點
<div id="three" style={{ background: "red", padding: "20px" }}>
第三個節(jié)點
</div>
</div>
</div>
</div>;
}
}
export default App;
總結:
1. e.currentTarget指向監(jiān)聽函數所在的元素節(jié)點 ------ 即id=one的節(jié)點
2. e.target 指向事件發(fā)出的節(jié)點 ----- 即點擊的那個節(jié)點
3. 監(jiān)聽函數中的this, 指向觸發(fā)事件的節(jié)點 ---- 始終等于e.currentTarget
Event.timeStamp
Event.detail
Event 對象的實例方法
Event.preventDefault()
- Event.preventDefault方法取消瀏覽器對當前事件的默認行為。比如點擊鏈接后,瀏覽器默認會跳轉到另一個頁面,使用這個方法以后,就不會跳轉了;再比如,按一下空格鍵,頁面向下滾動一段距離,使用這個方法以后也不會滾動了。該方法生效的前提是,事件對象的cancelable屬性為true,如果為false,調用該方法沒有任何效果。
- 注意,該方法只是取消事件對當前元素的默認影響,不會阻止事件的傳播。如果要阻止傳播,可以使用stopPropagation()或stopImmediatePropagation()方法。
Event.stopPropagation()
- stopPropagation方法阻止事件在 DOM 中繼續(xù)傳播,防止再觸發(fā)定義在別的節(jié)點上的監(jiān)聽函數,但是不包括在當前節(jié)點上其他的事件監(jiān)聽函數。
- propagation:是傳播的意思
Event.stopImmediatePropagation()
- Event.stopImmediatePropagation方法阻止同一個事件的其他監(jiān)聽函數被調用,不管監(jiān)聽函數定義在當前節(jié)點還是其他節(jié)點。也就是說,該方法阻止事件的傳播,比Event.stopPropagation()更徹底。
Event.composedPath()
- Event.composedPath()返回一個數組,成員是事件的最底層節(jié)點和依次冒泡經過的所有上層節(jié)點。
- compose: 組成,成員
CustomEvent 接口
- CustomEvent 接口用于生成自定義的事件實例。那些瀏覽器預定義的事件,雖然可以手動生成,但是往往不能在事件上綁定數據。如果需要在觸發(fā)事件的同時,傳入指定的數據,就可以使用 CustomEvent 接口生成的自定義事件對象。
document.documentElement
document.documentElement 以一個 ( 元素對象 ) 返回一個文檔的 ( 文檔元素 )
- ( html文檔 ) 返回對象為 ( html元素 )
- 如果html元素缺失,返回null
document.documentElement 返回整個html文檔元素

window.location.protocol
window.location.protocol 獲得當前網址的協(xié)議
- protocol是協(xié)議的意思
類似數組的對象轉成真正的數組
- Array.from()
- Array.prototype.slice.call(類似數組的對象)
Array.prototype.slice.call(nodeList類似數組的對象,傳入slice方法的參數)
- Array是實例數組的構造函數,
Array.prototype.slice就是實例數組的slice()方法。
實例數組的slice()方法繼承自Array.prototype屬性。
slice()方法沒有參數時,相當于原數組的拷貝。即從0截取到最后 - call方法
Function.prototype.call(this需要綁定的對象, 傳入function函數的參數)。
函數中this的指向,即this指向函數執(zhí)行時所在的對象。
Function.prototype.call的作用是,綁定this的指向為參數對象,并且執(zhí)行該函數。
call方法舉例:
var obj = {};
var f = function () {
return this;
};
f() === window // true
f.call(obj) === obj // true
-------------- 把f函數中this的指向obj對象,即在obj的作用域內運行f函數,第二個參數是傳給f函數的參數
- Array.prototype.slice.call(類似數組的對象,傳入slice的參數,如果沒有就是拷貝數組)
Array.prototype.slice.call({ 0: 'a', 1: 'b', length: 2 })
// ['a', 'b']
Array.prototype.slice.call(document.querySelectorAll("div"));--- 將nodeList對象轉成數組
Array.prototype.slice.call(arguments); --------------------------- 將arguments對象轉成數組
等于 [].slice.call(arguments) -------------- 因為[]是Array.prototype的實例,繼承了slice()方法
可以理解為:在特定的作用域中去執(zhí)行slice方法
https://www.cnblogs.com/happypayne/p/7739514.html
數組去重
1.
[ ...new Set([有重復值得數組]) ]
2.
let arr = [];
for(let i of new Set([有重復值得數組])) {
arr.push(i)
}
typeof NaN
typeof返回一個字符串,一共有6種類型:number, string, boolean,object,function,undefined
- typeof NaN 返回的是 ‘number’
- typeof Infinity 返回的是 ‘number’
- typeof Date 返回的是‘function’
- null , array , object 返回的都是‘object’
------- 如果要區(qū)分對象,可以使用 instanceof檢測某個對象是不是另一個對象的實例
------- [ ] instanceof Array// true
https://blog.csdn.net/GreyBearChao/article/details/77914261
instanceof
instanceof的原理是檢測右邊構造函數的原型是否在 左邊對象的原型鏈上
- instanceof返回一個布爾值,表示對象是否為某個構造函數的實例
- instance左邊是對象,右邊是構造函數
- 'aaa' instanceof String
false - [ ] instanceof Array
// true - 對于undefined和null,instanceOf運算符總是返回false
componentDidMount() {
let a = {};
let b = {x: 1};
Object.setPrototypeOf(a, b); // 把b對象設置成a對象的原型
console.log( Object.getPrototypeOf(a) === b );
// ---------------------------------------
const C = function(){};
const c = new C();
const d = c instanceof C;
console.log(d); // true
// ---------------------------------------
undefined instanceof Object // false
null instanceof Object // false
}
- instanceof的原理是檢測右邊構造函數的原型是否在 左邊對象的原型鏈上
v instanceof Vehicle
等同于
Vehicle.prototype.isPrototypeOf(v)
Object.create()
- 以參數對象為原型生成實例對象
Object.prototype.isPrototypeOf()
- isPrototype用來判斷該該對象是否是參數對象的原型對象
const a = {};
const b = Object.create(a); ------------------------- 以a對象為原型,生成實例對象b
const c = a.isPrototypeOf(b); ----------------------- a對象是不是b對象的原型
console.log(c) ------------------------------------- true
--
var o1 = {};
var o2 = Object.create(o1);
var o3 = Object.create(o2);
o2.isPrototypeOf(o3) // true
o1.isPrototypeOf(o3) // true
--
Object.prototype.isPrototypeOf({}) // true
Object.prototype.isPrototypeOf([]) // true
Object.prototype.isPrototypeOf(/xyz/) // true
Object.prototype.isPrototypeOf(Object.create(null)) // false
上面代碼中,由于Object.prototype處于原型鏈的最頂端,所以對各種實例都返回true,
只有直接繼承自null的對象除外。
Object.getPrototypeOf() ----------- 重要!?。。。?!
- 返回參數對象的原型對象
- Object.getPrototypeOf方法返回參數對象的原型。這是獲取原型對象的標準方法。
var F = function () {};
var f = new F();
Object.getPrototypeOf(f) === F.prototype -------- F.prototype會在生成實例時,成為實例對象的原型對象
// true
--
// 空對象的原型是 Object.prototype
Object.getPrototypeOf({}) === Object.prototype // true
// Object.prototype 的原型是 null
Object.getPrototypeOf(Object.prototype) === null // true --------------------重要重要?。?
// 函數的原型是 Function.prototype
function f() {}
Object.getPrototypeOf(f) === Function.prototype // true
Object.setPrototypeOf(對象,原型對象)
- Object.setPrototypeOf方法為參數對象設置原型,返回該參數對象。
- 它接受兩個參數,
第一個是現有對象,
第二個是原型對象。
var a = {};
var b = {x: 1};
Object.setPrototypeOf(a, b);
Object.getPrototypeOf(a) === b // true
a.x // 1
const a = {};
const b = {};
Object.setPrototypeOf(a,b); ----------------- 把b對象設置成a對象的原型對象
console.log( Object.getPrototypeOf(a) === b);
const c = Object.create(b); ---------------- 以b對象為原型對象,生成實例對象
console.log( Object.getPrototypeOf(c) === b );