安裝
cnpm install typescripy -g
使用
在命令行上码撰,運(yùn)行TypeScript編譯器:
輸出結(jié)果為一個(gè)a.js文件慧脱,它包含了和輸入文件中相同的JavsScript代碼拍皮。
tsc a.ts ---------------- 把a(bǔ).ts文件編譯成a.js文件
在vscode中自動(dòng)編譯
- 運(yùn)行命令:
tsc --init
-------> 生成tsconfig.json文件 - 點(diǎn)擊
任務(wù)---->運(yùn)行任務(wù)--------->tsc:監(jiān)視 - tsconfig.json
在tsconfig.json文件中:
outDir
: 表示js文件的生成目錄
比如:生成在根目錄的js文件夾中 ------------> outDir: './js'
數(shù)據(jù)類型
- string
- number
- boolean
- 數(shù)組
有兩種方法可以定義數(shù)組:
(1)第一種隧膏,可以在元素類型后面接上 []奠宜,表示由此類型元素組成的一個(gè)數(shù)組
let list: number[] = [1, 2, 3]; -------------- 由number類型元素組成的數(shù)組
(2)第二種方式是使用數(shù)組泛型包颁,Array<元素類型>:
let list: Array<number> = [1, 2, 3];
- 元組Tuple
tuple:是元組的意思
元組類型允許表示一個(gè)已知元素?cái)?shù)量和類型的數(shù)組瞻想,各元素的類型不必相同。
// Declare a tuple type
let x: [string, number];
// Initialize it
x = ['hello', 10]; // OK
// Initialize it incorrectly
x = [10, 'hello']; // Error ------------------- 不能交換位置娩嚼,只能按順序
6.枚舉enum
enum類型是對(duì)JavaScript標(biāo)準(zhǔn)數(shù)據(jù)類型的一個(gè)補(bǔ)充蘑险。 像C#等其它語言一樣,使用枚舉類型可以為一組數(shù)值賦予友好的名字岳悟。
enum Color {Red = 1, Green, Blue} ---- 默認(rèn)情況下佃迄,從0開始為元素編號(hào)。 你也可以手動(dòng)的指定成員的數(shù)值贵少。
let c: Color = Color.Green; ---------- 結(jié)果是2
- 枚舉類型提供的一個(gè)便利是你可以由枚舉的值得到它的名字
enum Color {Red = 1, Green, Blue}
let colorName: string = Color[2];
alert(colorName); // 顯示'Green'因?yàn)樯厦娲a里它的值是
7.Any
有時(shí)候呵俏,我們會(huì)想要為那些在編程階段還不清楚類型的變量指定一個(gè)類型。 這些值可能來自于動(dòng)態(tài)的內(nèi)容滔灶,比如來自用戶輸入或第三方代碼庫普碎。 這種情況下,我們不希望類型檢查器對(duì)這些值進(jìn)行檢查而是直接讓它們通過編譯階段的檢查录平。 那么我們可以使用 any類型來標(biāo)記這些變量:
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類型相反,它表示沒有任何類型斗这。 當(dāng)一個(gè)函數(shù)沒有返回值時(shí)动猬,你通常會(huì)見到其返回值類型是 void:
function warnUser(): void { ------------------------------- 正確
alert("This is my warning message");
}
function warnUser(): undefined { -------------------------- 錯(cuò)誤
alert("This is my warning message");
}
function a(): number { ------------------------------- 正確
return 123;
}
- 聲明一個(gè)void類型的變量沒有什么大用,因?yàn)槟阒荒転樗x予undefined和null:
let unusable: void = undefined; ----------- viod類型的變量只能賦予 undefined和null
9.Null 和 Undefined
TypeScript里表箭,undefined和null兩者各自有自己的類型分別叫做undefined和null赁咙。 和 void相似,它們的本身的類型用處不是很大:
- 默認(rèn)情況下null和undefined是所有類型的子類型免钻。 就是說你可以把 null和undefined賦值給number類型等任意類型的變量彼水。
然而,當(dāng)你指定了--strictNullChecks標(biāo)記伯襟,null和undefined只能賦值給void和它們各自。
10.Never -----------------------------------------包含null和undefined
never類型表示的是那些永不存在的值的類型握童。 例如姆怪, never類型是那些總是會(huì)拋出異常或根本就不會(huì)有返回值的函數(shù)表達(dá)式或箭頭函數(shù)表達(dá)式的返回值類型澡绩; 變量也可能是 never類型稽揭,當(dāng)它們被永不為真的類型保護(hù)所約束時(shí)。
never類型是任何類型的子類型肥卡,也可以賦值給任何類型溪掀;然而,沒有類型是never的子類型或可以賦值給never類型(除了never本身之外)步鉴。 即使 any也不可以賦值給never揪胃。
類型斷言
有時(shí)候你會(huì)遇到這樣的情況璃哟,你會(huì)比TypeScript更了解某個(gè)值的詳細(xì)信息。 通常這會(huì)發(fā)生在你清楚地知道一個(gè)實(shí)體具有比它現(xiàn)有類型更確切的類型喊递。
通過類型斷言這種方式可以告訴編譯器随闪,“相信我,我知道自己在干什么”骚勘。 類型斷言好比其它語言里的類型轉(zhuǎn)換铐伴,但是不進(jìn)行特殊的數(shù)據(jù)檢查和解構(gòu)。 它沒有運(yùn)行時(shí)的影響俏讹,只是在編譯階段起作用当宴。 TypeScript會(huì)假設(shè)你,程序員泽疆,已經(jīng)進(jìn)行了必須的檢查户矢。
類型斷言有兩種形式。
- 其一是“尖括號(hào)”語法:
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length; ---------------- someValue一定是一個(gè)字符串
- 另一個(gè)為as語法:
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;
接口:
關(guān)鍵詞: interface
interface LabelledValue { ----------------- interface聲明接口
label: string; ------------------------------- 注意這里是分號(hào)于微,但LabelledValue是個(gè)對(duì)象
}
function printLabel(labelledObj: LabelledValue) { --- 參數(shù)是一個(gè)對(duì)象逗嫡,必須有l(wèi)abel屬性,并且是個(gè)字符串
console.log(labelledObj.label);
}
let myObj = {size: 10, label: "Size 10 Object"}; ---- 雖然可以傳入size,但是在函數(shù)中調(diào)用時(shí)還是會(huì)報(bào)錯(cuò)
printLabel(myObj);
注意:
參數(shù)定義在外部株依,只要包含接口中的屬性就可以驱证,而直接寫在調(diào)用函數(shù)的內(nèi)部,則只能是接口中的屬性個(gè)數(shù)
如果是printLabel({size: 10, label: "Size 10 Object"}); 報(bào)錯(cuò) -------- 錯(cuò)
如果是printLabel({ label: "Size 10 Object"}); --------------------- 對(duì)
可選屬性 恋腕?
可選屬性就是在接口對(duì)象中的屬性后面加上抹锄?
- 可選屬性的好處之一是可以對(duì)可能存在的屬性進(jìn)行預(yù)定義,
- 好處之二是可以捕獲引用了不存在的屬性時(shí)的錯(cuò)誤荠藤。
比如伙单,我們故意將 createSquare里的color屬性名拼錯(cuò),就會(huì)得到一個(gè)錯(cuò)誤提示:
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表示私有哈肖,私有屬性和方法只能在該類中使用吻育,在 子類和實(shí)例對(duì)象中都不能使用
- public
- private
派生類
關(guān)鍵字:extends
- 基類,派生類
- ( 基類 ) 通常叫做 ( 超類 )
- ( 派生類 ) 通常叫做 ( 子類 )
(一) 在Table中淤井,編輯每一行的值布疼,當(dāng)Antd-Modal-Form-FormItem-initialValue 表單的每項(xiàng)獲得初始值后,改變其中某個(gè)input框的值币狠,影響其他行的table-modal-form的input值
( Modal中內(nèi)嵌Form表單的initialValue值不動(dòng)態(tài)更新問題 )
( 編輯第一行的input游两,影響第二行的input )
- 原因分析:當(dāng)?shù)谝粋€(gè)打開modal時(shí),modal被掛載漩绵,form獲得initialValue值贱案,再次打開modal時(shí),modal并沒有被重新掛載(只是被css隱藏了)止吐, 所以form中是上一次改變后input的值宝踪。
- 解決方案: Modal窗口我們都有應(yīng)用一個(gè)Visible來控制是否顯示侨糟, 我們只要利用這個(gè)值得變化就可以實(shí)現(xiàn)Modal組件的重新掛載了。
{
this.state.showModal ? <Modal></Modal> : null
}
false的時(shí)候肴沫,不掛載Modal
true的時(shí)候粟害,掛載
https://blog.csdn.net/u013558749/article/details/79105531/
(二) react-intl 國際化
- 安裝
cnpm install react-intl --save
- 包含的組件
(1) addLocaleData
(2) IntlProvider ----- 包裹需要國際化的根組件 ( local屬性,message屬性 )
- 使用<IntlProvider>組件包裹需要實(shí)現(xiàn)國際化的根組件
- intlProvider --- 組件包含兩個(gè)屬性 :
local
颤芬,message
index.js根組件:
import{ addLocaleData, IntlProvider } from 'react-intl'; --- 引入 addLocaleData 和 IntlProvider
添加多種語言對(duì)應(yīng)的文本悲幅,自己新建兩個(gè)js文件或者json文件
import enus from './locales/en-us';
import zhcn from './locales/zh-cn';
載入語言環(huán)境數(shù)據(jù)
import enLocaleData from 'react-intl/locale-data/en'
import zhLocaleData from 'react-intl/locale-data/zh'
// addLocaleData(enLocaleData) //注冊(cè)區(qū)域設(shè)置數(shù)據(jù)
// addLocaleData(zhLocaleData) //注冊(cè)區(qū)域設(shè)置數(shù)據(jù)
addLocaleData([...enLocaleData, ...zhLocaleData]) ------------ 使用addLocalData載入語言環(huán)境數(shù)據(jù)
<Provider store={store}>
<IntlProvider locale={'zh'} messages={zhcn} > ------------- interProvider組件
<BrowserRouter>
...
</BrowserRouter>
</IntlProvider>
</Provider>
, document.getElementById('root'));
(3) injectIntl 和 FormattedMesssage
React Intl 提供一個(gè)API,injectIntl站蝠,可以把命令式格式化的 API 注入到任意組件的props中汰具。然后可以在那個(gè)組件中通過this.props.intl直接去調(diào)用一些API和屬性,
比如this.props.intl.locale的值就是當(dāng)前語言了菱魔。
- FormattedMesssage組件
- injectIntl包裹子組件后留荔,通過this.props.intl.formatMessage({.....})來國際化
<FormattedMessage id="table.edit"/>
---------------
定義:
formatMessage = (...args) => {
const {intl: {formatMessage}} = this.props;
return formatMessage(...args)
};
調(diào)用:
this.formatMessage({id: "modal.saveError"})
FormattedMessage
FormattedDate
FormattedTime
- 使用:
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: '學(xué)生啊'}}
/>
<FormattedDate
value={ new Date() }
/>
運(yùn)算符優(yōu)先級(jí)
- 最高優(yōu)先級(jí):
----------> 屬性訪問.
()
[]
- 一元操作符是除了屬性訪問操作符外,具有最高的優(yōu)先級(jí)
-----------> 一元+澜倦,一元-聚蝶,遞增,遞減藻治,typeof碘勉,delete,void等 - 除逗號(hào)外桩卵,最低優(yōu)先級(jí):
----------> 賦值運(yùn)算符=
結(jié)合性--------------優(yōu)先級(jí)相同時(shí)的順序
- 左結(jié)合:除了一元验靡,三元,賦值以外的雏节,都是左結(jié)合
- 右結(jié)合:一元運(yùn)算符胜嗓,三元運(yùn)算符,賦值運(yùn)算符 (從右往左算)
https://www.cnblogs.com/liushui-sky/p/7993122.html
只有一元運(yùn)算符钩乍,三元運(yùn)算符辞州,賦值運(yùn)算符是右結(jié)合,其他的都是左結(jié)合
列子
const a = 2 < 1 ? 20 : 3 > 1 ? 200 : 2000 // 200
因?yàn)槿\(yùn)算符是右結(jié)合寥粹,所以上面的代碼相當(dāng)于
const a = 2 < 1 ? 20 : ( 3 > 1 ? 200 : 2000 ) ------------------------- 先算右邊的
事件模型
事件的本質(zhì)是程序各個(gè)組成部分之間的一種通信方式变过,也是異步編程的一種實(shí)現(xiàn)
EventTarget 接口
dom的事件操作,監(jiān)聽和觸發(fā)排作,都定義在eventTarget接口牵啦,所有節(jié)點(diǎn)對(duì)象都部署了這個(gè)接口
EventTarget 接口提供三個(gè)實(shí)例方法 :
- addEventListener:綁定事件的監(jiān)聽函數(shù)
- removeEventListener:移除事件的監(jiān)聽函數(shù)
- dispatchEvent:觸發(fā)事件
EventTarget.addEventListener()
EventTarget.addEventListener()綁定事件的監(jiān)聽函數(shù)亚情,一旦該事件發(fā)生妄痪,就會(huì)觸發(fā)執(zhí)行綁定的監(jiān)聽函數(shù),沒有返回值
EventTarget.addEventListener()用于在當(dāng)前節(jié)點(diǎn)或?qū)ο笊侠慵x一個(gè)特定事件的監(jiān)聽函數(shù)衫生。一旦這個(gè)事件發(fā)生裳瘪,就會(huì)執(zhí)行監(jiān)聽函數(shù)。
該方法沒有返回值罪针。
target.addEventListener(type, listener, useCapture);
type: 事件名稱彭羹,大小寫敏感
listener: 監(jiān)聽函數(shù),事件發(fā)生時(shí)泪酱,觸發(fā)該事件
useCapture: 監(jiān)聽函數(shù)是否在捕獲階段觸發(fā)派殷,默認(rèn)是false,即只在冒泡階段觸發(fā)
關(guān)于 ( 參數(shù) ) 需要注意兩個(gè)地方:
- 第二個(gè)參數(shù)除了是
監(jiān)聽函數(shù)
以外墓阀,還可以是一個(gè)具有handleEvent 方法的對(duì)象
handleEvent詳細(xì)介紹: http://www.reibang.com/p/13a0e7f4c335
componentDidMount() {
const a = document.getElementById('test');
a.addEventListener('click', {
handleEvent: function(e) {console.log(e)},
},false)
}
- 第三個(gè)參數(shù)除了是
useCapture布爾值
以外毡惜,還可以是一個(gè)屬性配置對(duì)象
capture:布爾值,表示該事件是否在捕獲階段觸發(fā)監(jiān)聽函數(shù)斯撮。
once:布爾值经伙,表示監(jiān)聽函數(shù)是否只觸發(fā)一次,然后就自動(dòng)移除勿锅。
passive:布爾值帕膜,表示監(jiān)聽函數(shù)不會(huì)調(diào)用事件的preventDefault方法。
如果監(jiān)聽函數(shù)調(diào)用了溢十,瀏覽器將忽略這個(gè)要求垮刹,并在監(jiān)控臺(tái)輸出一行警告。
-
addEventListener可以為當(dāng)前對(duì)象的同一事件茶宵,添加不同的監(jiān)聽函數(shù)危纫,這些函數(shù)按照添加順序觸發(fā),即先添加先觸發(fā)乌庶。
- 如果為同一個(gè)事件多次添加同一個(gè)監(jiān)聽函數(shù)种蝶,該函數(shù)只會(huì)執(zhí)行一次,多余的添加將自動(dòng)被去除(不必使用removeEventListener方法手動(dòng)去除)瞒大。
function hello() {
console.log('Hello world');
}
document.addEventListener('click', hello, false);
document.addEventListener('click', hello, false);
執(zhí)行上面代碼螃征,點(diǎn)擊文檔只會(huì)輸出一行Hello world。
- 如果希望向監(jiān)聽函數(shù)傳遞參數(shù)透敌,可以用 匿名函數(shù) 包裝 監(jiān)聽函數(shù)
function print(x) {
console.log(x);
}
var el = document.getElementById('div1');
el.addEventListener('click', function () { print('Hello'); }, false);
addEventListener(type, listener, useCapture)
-
監(jiān)聽函數(shù)內(nèi)部中的this盯滚,指向 ( 當(dāng)前事件 ) 所在的那個(gè) ( 對(duì)象 )
class App extends Component {
componentDidMount() {
const a = document.getElementById('test');
a.addEventListener('click', function(e) {console.log(this.nodeName)}, false)
} ------------------------------ 監(jiān)聽函數(shù)中的this,指向當(dāng)前事件所在的對(duì)象 // 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 + '可以為同一個(gè)對(duì)象的同一個(gè)事件綁定不同的監(jiān)聽函數(shù)')},
false);
a.addEventListener('click', function(){ go('重慶') }, false);
----- 如果要向監(jiān)聽函數(shù)傳遞參數(shù)酗电,可以用匿名函數(shù)來包裝一下監(jiān)聽函數(shù)
const b = document.getElementById('test-wrapper');
b.addEventListener('click', {
handleEvent: function(e) {
console.log('第二個(gè)參數(shù)可以是一個(gè)具有 handleEvent方法的對(duì)象')
}
}, {
capture: false, ------- 是否在捕獲階段觸發(fā)監(jiān)聽函數(shù)
once: false, --------- 是否只觸發(fā)一次監(jiān)聽函數(shù)魄藕,然后自動(dòng)移除
passive: true --------- 表示監(jiān)聽函數(shù)不會(huì)調(diào)用事件的preventDefault方法
});
----- 第二個(gè)參數(shù)可以是具有handleEvent方法的對(duì)象赏枚,
----- 第三個(gè)參數(shù)可以省略敬矩,默認(rèn)是false,在冒泡階段觸發(fā)羡铲,第三個(gè)參數(shù)也可以是配置對(duì)象
function go(params) {
console.log(params)
}
}
EventTarget.removeEventListener()
EventTarget.removeEventListener方法用來移除addEventListener方法添加的事件監(jiān)聽函數(shù)。該方法沒有返回值寝姿。
- removeEventListener方法的參數(shù)交排,與addEventListener方法完全一致。
- 注意:
removeEventListener()方法移除的監(jiān)聽函數(shù)饵筑,必須是addEventListener()方法添加的監(jiān)聽函數(shù)埃篓,并且必須在同一個(gè)元素節(jié)點(diǎn),否則無效根资。
div.addEventListener('click', function (e) {}, false);
div.removeEventListener('click', function (e) {}, false);
上面代碼中架专,removeEventListener方法無效,因?yàn)楸O(jiān)聽函數(shù)不是同一個(gè)匿名函數(shù)玄帕。
element.addEventListener('mousedown', handleMouseDown, true);
element.removeEventListener("mousedown", handleMouseDown, false);
上面代碼中胶征,removeEventListener方法也是無效的,因?yàn)榈谌齻€(gè)參數(shù)不一樣桨仿。
EventTarget.dispatchEvent()
EventTarget.dispatchEvent方法在當(dāng)前節(jié)點(diǎn)上觸發(fā)指定事件睛低,從而觸發(fā)監(jiān)聽函數(shù)的執(zhí)行。該方法返回一個(gè)布爾值服傍,只要有一個(gè)監(jiān)聽函數(shù)調(diào)用了Event.preventDefault()钱雷,則返回值為false,否則為true吹零。
- dispatchEvent() 在當(dāng)前節(jié)點(diǎn)上觸發(fā)指定事件-----------> 從而觸發(fā)監(jiān)聽函數(shù)執(zhí)行
dispatchEvent() 方法的參數(shù)是一個(gè)Event對(duì)象的實(shí)例
- 有返回值罩抗,只有有一個(gè)監(jiān)聽函數(shù)設(shè)置了 preventDefault() 就返回 false
para.addEventListener('click', hello, false); ----------- 觸發(fā)event事件后,會(huì)觸發(fā)事件監(jiān)聽函數(shù)hello
var event = new Event('click'); ----------- Event構(gòu)造函數(shù)灿椅,生成'click'事件實(shí)例
para.dispatchEvent(event); ----------------- 在para節(jié)點(diǎn)上套蒂,觸發(fā) event 事件
總結(jié):
1. EventTarget.dispatchEvent()觸發(fā)當(dāng)前節(jié)點(diǎn)指定的事件,參數(shù)是Event對(duì)象的實(shí)例茫蛹。
2. EventTarget.dispatchEvent()返回boolean值操刀,只要有一個(gè)監(jiān)聽函數(shù)調(diào)用了 preventDefault函數(shù),就返回false
3. EventTarget.dispatchEvent()參數(shù)為空婴洼,或者不是一個(gè)有效的事件對(duì)象骨坑,就會(huì)報(bào)錯(cuò)
- 如果dispatchEvent方法的參數(shù)為空,或者不是一個(gè)有效的事件對(duì)象柬采,將報(bào)錯(cuò)欢唾。
監(jiān)聽函數(shù)
瀏覽器的事件模型,就是通過監(jiān)聽函數(shù)(listener)對(duì)事件做出反應(yīng)粉捻。事件發(fā)生后礁遣,瀏覽器監(jiān)聽到了這個(gè)事件,就會(huì)執(zhí)行對(duì)應(yīng)的監(jiān)聽函數(shù)肩刃。這是事件驅(qū)動(dòng)編程模式(event-driven)的主要編程方式祟霍。
JavaScript 有三種方法押搪,可以為事件綁定監(jiān)聽函數(shù)。
HTML 的 on- 屬性 ------- 只會(huì)在冒泡階段觸發(fā)監(jiān)聽函數(shù)
- 元素的事件監(jiān)聽屬性浅碾,都是on加上事件名,比如onload就是on + load续语,表示load事件的監(jiān)聽代碼垂谢。
- 注意,
這些屬性的值是將會(huì)執(zhí)行的代碼疮茄,而不是一個(gè)函數(shù)滥朱。
- 使用這個(gè)方法指定的監(jiān)聽代碼,只會(huì)在冒泡階段觸發(fā)力试。
- 直接設(shè)置on-屬性徙邻,與通過元素節(jié)點(diǎn)的setAttribute方法設(shè)置on-屬性,效果是一樣的畸裳。
<!-- 正確 -->
<body onload="doSomething()"> ----------- 值是將要執(zhí)行的代碼缰犁,而不是函數(shù),即必須調(diào)用
<!-- 錯(cuò)誤 -->
<body onload="doSomething">
<div onClick="console.log(2)">
<button onClick="console.log(1)">點(diǎn)擊</button>
</div>
由于on-屬性的監(jiān)聽代碼怖糊,只在冒泡階段觸發(fā)帅容,所以點(diǎn)擊結(jié)果是先輸出1,再輸出2伍伤,
即事件從子元素開始冒泡到父元素并徘。
- 直接設(shè)置on-屬性,與通過元素節(jié)點(diǎn)的setAttribute方法設(shè)置on-屬性扰魂,效果是一樣的麦乞。
el.setAttribute('onclick', 'doSomething()');
// 等同于
// <Element onclick="doSomething()">
元素節(jié)點(diǎn)的事件屬性
- 元素節(jié)點(diǎn)對(duì)象 的事件屬性,同樣可以指定監(jiān)聽函數(shù)劝评。
- 使用這個(gè)方法指定的監(jiān)聽函數(shù)姐直,也是只會(huì)在冒泡階段觸發(fā)。
- 缺點(diǎn): 同一個(gè)事件只能定義一個(gè)監(jiān)聽函數(shù)
- 注意蒋畜,
(元素節(jié)點(diǎn)對(duì)象的 事件屬性 )
這種方法與 HTML 的on-屬性的差異是:
- 元素節(jié)點(diǎn)對(duì)象的 事件屬性: ------它的值是函數(shù)名(doSomething)简肴,
- HTML 的on-屬性: ------必須給出完整的監(jiān)聽代碼(doSomething())。
window.onload = doSomething;
div.onclick = function (event) { ----------------- 注意這種寫法不是駝峰寫法
console.log('觸發(fā)事件');
};
小結(jié)
上面三種方法百侧,
第一種“HTML 的 on- 屬性”砰识,違反了 HTML 與 JavaScript 代碼相分離的原則,將兩者寫在一起佣渴,不利于代碼分工辫狼,因此不推薦使用。
第二種“元素節(jié)點(diǎn)的事件屬性”的缺點(diǎn)在于辛润,同一個(gè)事件只能定義一個(gè)監(jiān)聽函數(shù)膨处,也就是說,如果定義兩次onclick屬性,后一次定義會(huì)覆蓋前一次真椿。因此鹃答,也不推薦使用。
第三種EventTarget.addEventListener是推薦的指定監(jiān)聽函數(shù)的方法突硝。它有如下優(yōu)點(diǎn):
EventTarget.addEventListener() 優(yōu)點(diǎn)
- 同一個(gè)事件可以添加多個(gè)監(jiān)聽函數(shù)测摔。
- 能夠指定在哪個(gè)階段(捕獲階段還是冒泡階段)觸發(fā)監(jiān)聽函數(shù)。
- 除了 DOM 節(jié)點(diǎn)解恰,其他對(duì)象(比如window锋八、XMLHttpRequest等)也有這個(gè)接口,它等于是整個(gè) JavaScript 統(tǒng)一的監(jiān)聽函數(shù)接口护盈。
EventTarget.addEventListener()的優(yōu)點(diǎn):
1. 可以為同一個(gè)事件挟纱,指定不同的監(jiān)聽函數(shù)
2. 可以指定監(jiān)聽函數(shù)觸發(fā)的階段,默認(rèn)是在useCapture捕獲階段觸發(fā)腐宋。第三個(gè)參數(shù)
3. 除了dom節(jié)點(diǎn)紊服,其他對(duì)象也有這個(gè)接口。 window, XMLHttpRequest等
this 的指向
- 監(jiān)聽函數(shù)內(nèi)部的this, 指向觸發(fā)事件的元素節(jié)點(diǎn)
監(jiān)聽函數(shù)中的this, 指向觸發(fā)事件的那個(gè)元素節(jié)點(diǎn)
事件的傳播
一個(gè)事件發(fā)生后胸竞,會(huì)在子元素和父元素之間傳播(propagation)围苫。這種傳播分成三個(gè)階段。
- 第一階段:從window對(duì)象傳導(dǎo)到目標(biāo)節(jié)點(diǎn)(上層傳到底層)撤师,稱為“捕獲階段”(capture phase)剂府。
- 第二階段:在目標(biāo)節(jié)點(diǎn)上觸發(fā),稱為“目標(biāo)階段”(target phase)剃盾。
- 第三階段:從目標(biāo)節(jié)點(diǎn)傳導(dǎo)回window對(duì)象(從底層傳回上層)腺占,稱為“冒泡階段”(bubbling phase)。
事件的傳播分為三個(gè)階段
第一階段是從window對(duì)象傳到到目標(biāo)節(jié)點(diǎn)痒谴,是捕獲階段 capture phase
第二階段衰伯,在目標(biāo)節(jié)點(diǎn)上觸發(fā),稱為目標(biāo)階段积蔚,target phase
第三階段意鲸,從目標(biāo)節(jié)點(diǎn)傳導(dǎo)到window對(duì)象,稱為冒泡階段 bubbling phase
- phase是階段的意思
- bubbling是冒泡的意思
- capture是捕獲的意思
注意尽爆,瀏覽器總是假定click事件的目標(biāo)節(jié)點(diǎn)怎顾,就是點(diǎn)擊位置嵌套最深的那個(gè)節(jié)點(diǎn)
也就是說,事件傳播順序漱贱,
在捕獲階段依次為window槐雾、document、html幅狮、body募强、div株灸、p,
在冒泡階段依次為p擎值、div慌烧、body、html鸠儿、document屹蚊、window。
事件的代理
由于事件會(huì)在冒泡階段向上傳播到父節(jié)點(diǎn)捆交,因此可以把子節(jié)點(diǎn)的監(jiān)聽函數(shù)定義在父節(jié)點(diǎn)上,由父節(jié)點(diǎn)的監(jiān)聽函數(shù)統(tǒng)一處理多個(gè)子元素的事件腐巢。這種方法叫做事件的代理(delegation)品追。
- delegation 是委托冯丙,代理的意思
- 如果希望事件到某個(gè)節(jié)點(diǎn)為止,不再傳播胃惜,可以使用事件對(duì)象的stopPropagation方法。
- 但是船殉,stopPropagation方法只會(huì)阻止事件的傳播鲫趁,不會(huì)阻止該事件觸發(fā)<p>節(jié)點(diǎn)的其他click事件的監(jiān)聽函數(shù)利虫。也就是說,不是徹底取消click事件糠惫。
// 事件傳播到 p 元素后疫剃,就不再向下傳播了
p.addEventListener('click', function (event) {
event.stopPropagation();
}, true);
// 事件冒泡到 p 元素后硼讽,就不再向上冒泡了
p.addEventListener('click', function (event) {
event.stopPropagation();
}, false);
- 如果想要徹底阻止這個(gè)事件的傳播,不再觸發(fā)后面所有click的監(jiān)聽函數(shù)固阁,可以使用stopImmediatePropagation方法。
Event 對(duì)象概述
事件發(fā)生以后柒爵,會(huì)產(chǎn)生一個(gè)事件對(duì)象赚爵,作為參數(shù)傳給監(jiān)聽函數(shù)法瑟。瀏覽器原生提供一個(gè)Event對(duì)象唁奢,所有的事件都是這個(gè)對(duì)象的實(shí)例,或者說繼承了Event.prototype對(duì)象麻掸。
- Event對(duì)象本身就是一個(gè)構(gòu)造函數(shù),可以用來生成新的實(shí)例熬北。
- event = new Event(type, options);
- Event構(gòu)造函數(shù)接受兩個(gè)參數(shù)诚隙。
第一個(gè)參數(shù)type是字符串,表示事件的名稱巫延;
第二個(gè)參數(shù)options是一個(gè)對(duì)象地消,表示事件對(duì)象的配置
bubbles:布爾值,可選脉执,默認(rèn)為false,表示事件對(duì)象是否冒泡竿开。
cancelable:布爾值玻熙,可選,默認(rèn)為false嗦随,表示事件是否可以被取消,
即能否用Event.preventDefault()取消這個(gè)事件枚尼。
一旦事件
- 被取消,就好像從來沒有發(fā)生過崎溃,不會(huì)觸發(fā)瀏覽器對(duì)該事件的默認(rèn)行為盯质。
- 注意概而,如果不是顯式指定bubbles屬性為true囱修,生成的事件就只能在“捕獲階段”觸發(fā)監(jiān)聽函數(shù)。
// 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ā)出一個(gè)click事件鲜漩,該事件默認(rèn)不會(huì)冒泡。
div.addEventListener方法指定在冒泡階段監(jiān)聽孕似,因此監(jiān)聽函數(shù)不會(huì)觸發(fā)。
如果寫成div.addEventListener('click', callback, true)霸饲,那么在“捕獲階段”可以監(jiān)聽到這個(gè)事件臂拓。
Event 對(duì)象的實(shí)例屬性
Event.bubbles习寸,Event.eventPhase
- Event.bubbles屬性返回一個(gè)布爾值,表示當(dāng)前事件是否會(huì)冒泡孵滞。屬性為只讀屬性鸯匹,一般用來了解 Event 實(shí)例是否可以冒泡。
- Event.eventPhase屬性返回一個(gè)整數(shù)常量匿级,表示事件目前所處的階段染厅。該屬性只讀。
Event.eventPhase的返回值有四種可能肖粮。
0,事件目前沒有發(fā)生行施。
1,事件目前處于捕獲階段悲龟,即處于從祖先節(jié)點(diǎn)向目標(biāo)節(jié)點(diǎn)的傳播過程中须教。
2,事件到達(dá)目標(biāo)節(jié)點(diǎn)轻腺,即Event.target屬性指向的那個(gè)節(jié)點(diǎn)。
3挤土,事件處于冒泡階段误算,即處于從目標(biāo)節(jié)點(diǎn)向祖先節(jié)點(diǎn)的反向傳播過程中。
- 除非顯式聲明咖杂,Event構(gòu)造函數(shù)生成的事件蚊夫,默認(rèn)是不冒泡的。
Event.cancelable知纷,
Event.cancelBubble,
event.defaultPrevented
Event.cancelable屬性返回一個(gè)布爾值伍绳,表示事件是否可以取消乍桂。該屬性為只讀屬性,一般用來了解 Event 實(shí)例的特性漠趁。
大多數(shù)瀏覽器的原生事件是可以取消的忍疾。
Event.currentTarget,
Event.target
- Event.currentTarget屬性返回事件當(dāng)前所在的節(jié)點(diǎn)甥绿,即正在執(zhí)行的監(jiān)聽函數(shù)所綁定的那個(gè)節(jié)點(diǎn)。
- Event.target屬性返回原始觸發(fā)事件的那個(gè)節(jié)點(diǎn)共缕,即事件最初發(fā)生的節(jié)點(diǎn)。
-
事件傳播過程中翩活,不同節(jié)點(diǎn)的監(jiān)聽函數(shù)內(nèi)部的Event.target與Event.currentTarget屬性的值是不一樣的便贵,前者總是不變的,后者則是指向監(jiān)聽函數(shù)所在的那個(gè)節(jié)點(diǎn)對(duì)象利耍。
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é)點(diǎn)盔粹,即點(diǎn)擊的那個(gè)節(jié)點(diǎn)
console.log(e.currentTarget, "e.currentTarget"); ---------------- 是監(jiān)聽函數(shù)綁定的元素節(jié)點(diǎn)
console.log(this, 'this'); ------------ 事件觸發(fā)所綁定的那個(gè)節(jié)點(diǎn),即監(jiān)聽函數(shù)所在的節(jié)點(diǎn)
}
}
render() {
return <div className="App">
<div id="one" style={{ background: "yellow", padding: "20px" }}>
第一個(gè)節(jié)點(diǎn)
<div id="two" style={{ background: "silver", padding: "20px" }}>
第二個(gè)節(jié)點(diǎn)
<div id="three" style={{ background: "red", padding: "20px" }}>
第三個(gè)節(jié)點(diǎn)
</div>
</div>
</div>
</div>;
}
}
export default App;
總結(jié):
1. e.currentTarget指向監(jiān)聽函數(shù)所在的元素節(jié)點(diǎn) ------ 即id=one的節(jié)點(diǎn)
2. e.target 指向事件發(fā)出的節(jié)點(diǎn) ----- 即點(diǎn)擊的那個(gè)節(jié)點(diǎn)
3. 監(jiān)聽函數(shù)中的this, 指向觸發(fā)事件的節(jié)點(diǎn) ---- 始終等于e.currentTarget
Event.timeStamp
Event.detail
Event 對(duì)象的實(shí)例方法
Event.preventDefault()
- Event.preventDefault方法取消瀏覽器對(duì)當(dāng)前事件的默認(rèn)行為轴猎。比如點(diǎn)擊鏈接后咬崔,瀏覽器默認(rèn)會(huì)跳轉(zhuǎn)到另一個(gè)頁面烦秩,使用這個(gè)方法以后,就不會(huì)跳轉(zhuǎn)了兜蠕;再比如抛寝,按一下空格鍵,頁面向下滾動(dòng)一段距離晶府,使用這個(gè)方法以后也不會(huì)滾動(dòng)了钻趋。該方法生效的前提是,事件對(duì)象的cancelable屬性為true蛮位,如果為false鳞绕,調(diào)用該方法沒有任何效果们何。
- 注意控轿,該方法只是取消事件對(duì)當(dāng)前元素的默認(rèn)影響,不會(huì)阻止事件的傳播茬射。如果要阻止傳播,可以使用stopPropagation()或stopImmediatePropagation()方法片部。
Event.stopPropagation()
- stopPropagation方法阻止事件在 DOM 中繼續(xù)傳播霜定,防止再觸發(fā)定義在別的節(jié)點(diǎn)上的監(jiān)聽函數(shù),但是不包括在當(dāng)前節(jié)點(diǎn)上其他的事件監(jiān)聽函數(shù)辖所。
- propagation:是傳播的意思
Event.stopImmediatePropagation()
- Event.stopImmediatePropagation方法阻止同一個(gè)事件的其他監(jiān)聽函數(shù)被調(diào)用磨德,不管監(jiān)聽函數(shù)定義在當(dāng)前節(jié)點(diǎn)還是其他節(jié)點(diǎn)。也就是說酥宴,該方法阻止事件的傳播您觉,比Event.stopPropagation()更徹底。
Event.composedPath()
- Event.composedPath()返回一個(gè)數(shù)組琳水,成員是事件的最底層節(jié)點(diǎn)和依次冒泡經(jīng)過的所有上層節(jié)點(diǎn)在孝。
- compose: 組成,成員
CustomEvent 接口
- CustomEvent 接口用于生成自定義的事件實(shí)例私沮。那些瀏覽器預(yù)定義的事件,雖然可以手動(dòng)生成极阅,但是往往不能在事件上綁定數(shù)據(jù)。如果需要在觸發(fā)事件的同時(shí)仆百,傳入指定的數(shù)據(jù)奔脐,就可以使用 CustomEvent 接口生成的自定義事件對(duì)象。
document.documentElement
document.documentElement 以一個(gè) ( 元素對(duì)象 ) 返回一個(gè)文檔的 ( 文檔元素 )
- ( html文檔 ) 返回對(duì)象為 ( html元素 )
- 如果html元素缺失髓迎,返回null
document.documentElement 返回整個(gè)html文檔元素
window.location.protocol
window.location.protocol 獲得當(dāng)前網(wǎng)址的協(xié)議
- protocol是協(xié)議的意思
類似數(shù)組的對(duì)象轉(zhuǎn)成真正的數(shù)組
- Array.from()
- Array.prototype.slice.call(類似數(shù)組的對(duì)象)
Array.prototype.slice.call(nodeList類似數(shù)組的對(duì)象,傳入slice方法的參數(shù))
- Array是實(shí)例數(shù)組的構(gòu)造函數(shù)尺铣,
Array.prototype.slice就是實(shí)例數(shù)組的slice()方法争舞。
實(shí)例數(shù)組的slice()方法繼承自Array.prototype屬性。
slice()方法沒有參數(shù)時(shí)竞川,相當(dāng)于原數(shù)組的拷貝。即從0截取到最后 - call方法
Function.prototype.call(this需要綁定的對(duì)象, 傳入function函數(shù)的參數(shù))床牧。
函數(shù)中this的指向福澡,即this指向函數(shù)執(zhí)行時(shí)所在的對(duì)象驹马。
Function.prototype.call的作用是,綁定this的指向?yàn)閰?shù)對(duì)象算利,并且執(zhí)行該函數(shù)泳姐。
call方法舉例:
var obj = {};
var f = function () {
return this;
};
f() === window // true
f.call(obj) === obj // true
-------------- 把f函數(shù)中this的指向obj對(duì)象,即在obj的作用域內(nèi)運(yùn)行f函數(shù)缎患,第二個(gè)參數(shù)是傳給f函數(shù)的參數(shù)
- Array.prototype.slice.call(類似數(shù)組的對(duì)象,傳入slice的參數(shù)肮街,如果沒有就是拷貝數(shù)組)
Array.prototype.slice.call({ 0: 'a', 1: 'b', length: 2 })
// ['a', 'b']
Array.prototype.slice.call(document.querySelectorAll("div"));--- 將nodeList對(duì)象轉(zhuǎn)成數(shù)組
Array.prototype.slice.call(arguments); --------------------------- 將arguments對(duì)象轉(zhuǎn)成數(shù)組
等于 [].slice.call(arguments) -------------- 因?yàn)閇]是Array.prototype的實(shí)例判导,繼承了slice()方法
可以理解為:在特定的作用域中去執(zhí)行slice方法
https://www.cnblogs.com/happypayne/p/7739514.html
數(shù)組去重
1.
[ ...new Set([有重復(fù)值得數(shù)組]) ]
2.
let arr = [];
for(let i of new Set([有重復(fù)值得數(shù)組])) {
arr.push(i)
}
typeof NaN
typeof返回一個(gè)字符串,一共有6種類型:number
, string
, boolean
,object
,function
,undefined
- typeof NaN 返回的是 ‘number’
- typeof Infinity 返回的是 ‘number’
- typeof Date 返回的是‘function’
- null , array , object 返回的都是‘object’
------- 如果要區(qū)分對(duì)象绕辖,可以使用 instanceof檢測某個(gè)對(duì)象是不是另一個(gè)對(duì)象的實(shí)例
------- [ ] instanceof Array// true
https://blog.csdn.net/GreyBearChao/article/details/77914261
instanceof
instanceof的原理是檢測右邊構(gòu)造函數(shù)的原型
是否在 左邊對(duì)象的原型鏈上
- instanceof返回一個(gè)布爾值擂红,表示對(duì)象是否為某個(gè)構(gòu)造函數(shù)的實(shí)例
- instance左邊是對(duì)象,右邊是構(gòu)造函數(shù)
- 'aaa' instanceof String
false
- [ ] instanceof Array
// true
- 對(duì)于undefined和null弟头,instanceOf運(yùn)算符總是返回false
componentDidMount() {
let a = {};
let b = {x: 1};
Object.setPrototypeOf(a, b); // 把b對(duì)象設(shè)置成a對(duì)象的原型
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的原理是檢測右邊構(gòu)造函數(shù)的原型是否在 左邊對(duì)象的原型鏈上
v instanceof Vehicle
等同于
Vehicle.prototype.isPrototypeOf(v)
Object.create()
- 以參數(shù)對(duì)象為原型生成實(shí)例對(duì)象
Object.prototype.isPrototypeOf()
- isPrototype用來判斷該該對(duì)象是否是參數(shù)對(duì)象的原型對(duì)象
const a = {};
const b = Object.create(a); ------------------------- 以a對(duì)象為原型涉茧,生成實(shí)例對(duì)象b
const c = a.isPrototypeOf(b); ----------------------- a對(duì)象是不是b對(duì)象的原型
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處于原型鏈的最頂端,所以對(duì)各種實(shí)例都返回true钳垮,
只有直接繼承自null的對(duì)象除外。
Object.getPrototypeOf() ----------- 重要F缃埂6且健!3μ住D阒伞朱躺!
- 返回參數(shù)對(duì)象的原型對(duì)象
- Object.getPrototypeOf方法返回參數(shù)對(duì)象的原型搁痛。這是獲取原型對(duì)象的標(biāo)準(zhǔn)方法。
var F = function () {};
var f = new F();
Object.getPrototypeOf(f) === F.prototype -------- F.prototype會(huì)在生成實(shí)例時(shí)鸡典,成為實(shí)例對(duì)象的原型對(duì)象
// true
--
// 空對(duì)象的原型是 Object.prototype
Object.getPrototypeOf({}) === Object.prototype // true
// Object.prototype 的原型是 null
Object.getPrototypeOf(Object.prototype) === null // true --------------------重要重要=文啤!
// 函數(shù)的原型是 Function.prototype
function f() {}
Object.getPrototypeOf(f) === Function.prototype // true
Object.setPrototypeOf(對(duì)象疗垛,原型對(duì)象)
- Object.setPrototypeOf方法為參數(shù)對(duì)象設(shè)置原型,返回該參數(shù)對(duì)象背镇。
- 它接受兩個(gè)參數(shù)泽裳,
第一個(gè)是現(xiàn)有對(duì)象,
第二個(gè)是原型對(duì)象胸囱。
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對(duì)象設(shè)置成a對(duì)象的原型對(duì)象
console.log( Object.getPrototypeOf(a) === b);
const c = Object.create(b); ---------------- 以b對(duì)象為原型對(duì)象瀑梗,生成實(shí)例對(duì)象
console.log( Object.getPrototypeOf(c) === b );