ES6與ReactJS學習筆記

1.ES6

ES6,是ECMAScript 6 的簡稱,是JavaScript語言的下一代標準,已於2015年6月正式發佈。

1.1. let於const

之前,我們在編寫js定義變量的時候,只有一個關鍵字 var。var有一個問題,就是定義的變量會成爲全局變量。

// var變量的作用域問題檢查
for(var i = 0;i<5;i++){
    console.log(i);
}
console.log("循環外:"+i);

可以看出,在循環外部也可以獲取到變量i的值。

  1. let關鍵字 :可以將i的作用域控制在循環內部。
//let 所聲明的變量,只在let命令所在的代碼塊內有效.
for(let i = 0;i<5;i++){
    console.log(i);
}
//index.html:21 Uncaught ReferenceError: i is not defined
//console.log("循環外:"+i);
  1. const關鍵字:聲明的變量是常量,不能被修改,類似於java中的final關鍵字。
//const 所聲明的變量是常量,不能被修改,類似於java中的final關鍵字
const a = 1;
console.log("a = ",a);
//給a重新賦值;Uncaught TypeError: Assignment to constant variable.
//a = 2;
console.log("a = ",a);

1.2.字符串擴展

ES6中,爲字符串擴展了幾個新的API

  • includes():返回布爾值,標識是否找到了參數字符串

  • startWith():返回布爾值,標識參數字符串是否在原字符串的尾部

  • endWith():返回布爾值,標識參數字符串是否在原字符串的尾部

let str = "hello fechin";
console.log(str,"中是否包含了fechin ==>",str.includes("fechin"));
console.log(str,"中是否包含了fuck ==>",str.includes("fuck"));

1.3.字符串模板

ES6中提供了" ` "來作爲字符串模板標記

 let str2 = `你好
 哈哈
 呵呵`;
 console.log("試一試",str2);   
 //在``之間的部分都會被認爲是字符串的值,可以任意換行;

1.4.解構表達式

ES6中允許按照一定模式從數組和對象中提取值,然後對變量進行賦值,這被稱爲解構。

  1. 數組解構
let arr = [1,2,3];
const [x,y,z] = arr; //x,y,z將與arr中的每個位置來對應
console.log(x,y,z);
//結果爲[1,2,3]

const a = arr;
console.log("+++++",a);
//結果爲[1,2,3]

const [b] = arr;
console.log("-----",b);
//結果爲1
  1. 對象解構
const person = {
    name : "fechin",
    age : "12",
    language : ["java","js","html"]
}

let {name,age,language} = person;
console.log(name,age,language);
//如果想要用其他變量接收,那麼需要額外指定別名
//{name:na}:name是person中的屬性名,冒號後面的n是解構後要賦值給的變量
let {name:na,age:ag,language:la} = person;
console.log("+-+-+-+-+-",na,ag,la);

1.5.函數優化

1.5.1.函數參數默認值

在ES6之前,我們無法給一個函數參數設置默認值,只能採用變通寫法

function add(a,b){
    //判斷b是否爲空,爲空就給默認值0
    if(!b){
        b = 0;
    }
    //判斷b是否爲空,爲空就給默認值0
    // b = b || 0;
    return a + b;
}
console.log(add(1));

ES6之後,可以這麼寫

function add(a,b = 0){
    return a + b;
}
console.log(add(1));

1.5.2.箭頭函數

//箭頭函數
//沒有參數
let sayHello = () => console.log("你好");
sayHello();

//一個參數
let print = a => console.log(a);
print("你好呀");

//多個參數
let sum = (a,b) => {return a+b;}
let result = sum(1,2);
console.log(result);

1.5.3.對象函數的屬性簡寫

		let person = {
        name : "fechin",
        eat : function(food){
            console.log(this.name+"在喫"+food);
        },
        //箭頭函數
        drink : food => {
            //不能從this.name中獲取到值,目前只能使用 person.name
            console.log(person.name+"在喝"+food);
        },
        //直接寫函數
        sleep(time) {
            console.log(person.name+" just slepp: " + time +" minutes");
        }
    }
    person.eat("象拔蚌");
    person.drink("香蕉油");
    person.sleep("60");

1.5.4.箭頭函數結合解構表達式

		//傳統方式
    function hello(person){
        console.log("hello"+person.name);
    }
    hello(person);

    //解構表達式與箭頭函數
    const hello = ({age}) => {
        console.log("++++"+age); //輸出爲 '++++21'
    }
    hello(person);

1.6.map和reduce

  1. map():接收一個函數,將原數組中的所有元素用這個函數處理後返回。
				let arr = ['1','20','30'];
        console.log(arr);

        let newArr = arr.map( s => parseInt(s));
        console.log(newArr);
  1. reduce():接收一個函數(必須)和一個初始值(可選),該函數接收兩個參數。

    • 第一個參數是上一次reduce處理的結果;
    • 第二個參數是數組中要處理的下一個元素;

    reduce():會從左到右依次把數組中的元素用reduce處理,並把處理的結果作爲下次reduce的第一個參數。如果是第一次,會把前兩個元素作爲計算參數,或者把用戶指定的初始值作爲起始參數。

				const arr = [1,20,-5,3];
        let result = arr.reduce((a,b) => {
            return a + b;
        });
        console.log(result);
        //19

        let result2 = arr.reduce((a,b) => {
            return a + b;
        }, 1);
        console.log(result2);
        //20

1.7.擴展運算符

擴展運算符是三個點...,將一個數組轉爲用逗號分隔的參數序列。

				console.log([1,2,3]) //[1,2,3]
        console.log(...[1,2,3]) //1,2,3
        
        let add = (x,y) => {
            return x+y;
        }
        let numbers = [1,2];
        console.log(add(...numbers)); //3

        //...可以用作數組的合併
        let arr = [...[1,2,3],...[4,5,6]];
        console.log(arr); //[1,2,3,4,5,6];

        //與結構表達式結合
        const [first,...rest] = [1,2,3,4,5];
        console.log(first,rest); //1,[2,3,4,5]

				//將字符串轉成數組
        console.log([...'hello']);//['h','e','l','l','o']

1.8.Promise

Promise,簡單說是一個容器,裏面保存着某個未來纔會結束的事件(通常是一個異步操作)的結果,從語法上來說Promise是一個對象,從它可以獲取異步操作的消息,Promise提供統一的API,各種異步操作都可以用同樣的方法進行處理。

我們可以通過Promise的構造函數來創建Promise對象,並在內部封裝一個異步執行的結果。

				const p = new Promise((resolve,reject) => {
            //編寫異步操作,通常寫ajax的操作,(模擬)
            setTimeout(()=>{
                let num = Math.random();
                if(num <0.5){
                    //認爲成功了
                    resolve("成功了"+num);//調用resolve,代表promise將返回成功的結果
                }else{
                    //認爲失敗了
                    reject("失敗了"+num);//調用reject,代表promise將返回失敗的結果
                }
            });
        });

        p.then(value => {
            console.log(value)
        }).catch(value =>{
            console.log(value);
        });

1.9.Set和Map

ES6中提供了Set和Map的數據結構

  1. Set本質上與數組類似,不同在於Set中只能保存不同的元素,如果元素相同會被忽略,和java中的Set集合非常相似。
				//set構造函數可以接受一個數組或空
        let set = new Set();
        set.add(1);//[1]添加
        set.clear();//清空
        set.delete(1);//刪除指定元素,並不是下標
        set.has(2);//判斷是否存儲
        set.forEach(s => console.log(s+1));//遍歷元素
        set.size;//元素個數

        let set2 = new Set([2,3,4,4]);//[2,3,4]
  1. Map本質上與Object類似的結構,不同的在於,Object強制規定key只能是字符串,而Map結構的key可以是任意對象,即:
    • Object是<String,Object>集合
    • map是<Object,Object>集合
        const map = new Map([
            ['key01','value01'],
            ['key02','value02']
        ]);

        map.set('key03','value03');//添加
        map.clear();//清空
        map.delete('key01');//刪除
        map.forEach((value,key)=>console.log(key,value));//遍歷元素,第一個拿到是value,第二個纔是key
        map.size;//元素個數

        map.values();//獲取value的迭代器
        map.keys();//獲取key的迭代器
        map.entries();//獲取entry的迭代器
    
        
        for(let key of map.keys()){
            console.log(key);
            
        }
        console.log(...map.values());
        for(let entry of map.entries()){
            console.log("+++++++++",entry);
        }
        

1.10.class(類)的基本語法

JavaScript語言的傳統方法是通過構造函數定義並生成新的對象,ES6中引入了class的概念,通過class關鍵字自定義類。

				class User {
            //構造函數
            constructor(name,age=20){
                this.name = name;
                this.age = age;
            }

            sayHello(){
                return "hello,"+this.name;
            }

            //靜態函數
            static isAdult(age){
                if(age>=18){
                    return "成年人";
                }
                return "未成年人";
            }
        }

        let user = new User("張三");
        console.log(user);
        console.log(user.sayHello());
        console.log(User.isAdult(20));

        class Somebody extends User{
            constructor(){
                super('李四');
            }
            test(){
                return "test ->" +this.name;         
            }
        }

        let somebody = new Somebody();
        console.log(somebody.test()); 
        console.log(somebody.sayHello());
        console.log(Somebody.isAdult(20));

1.11.Generator函數

Generator函數是ES6提供的一種異步編程解決方案,語法行爲與傳統函數完全不同;

Generator函數有兩個特徵:一是function命令與函數名之間有一個*號,二是函數內部使用yield定義不同的狀態。

				function* hello(){
            yield "hello";
            yield "world";
            yield "haha";
            return "hehe";
        }
        
        let h = hello();
        console.log(h); //類型是一個Generator對象
        console.log(h.next()); //{value: "hello", done: false} done爲false標識並未執行完成
        console.log(h.next()); //done:false
        console.log(h.next()); //done:false
        console.log(h.next()); //{value: "hehe", done: true}
        console.log(h.next()); //{value: undefined, done: true}

        for(let obj of h){
            console.log("++++",obj);
        }
        /*
        結果爲:
        ++++ hello
        ++++ world
        ++++ haha
        */

1.12.修飾器(Decorator)

修飾器是一個函數,用來修改類的行爲,ES2017引入了這項功能,目前Babel轉碼器已經支持。

				@T
        class User {
            constructor(name,age = 20){
                this.name = name;
                this.age = age;
            }
        }

        function T(target){ //定義一個普通方法
            console.log(targer); //target對象爲修飾的目標對象,這裏是User對象
            target.country = "中國"; //爲User類添加一個靜態屬性country(通過修飾器添加的屬性是靜態屬性)
        }
				
        console.log(User.country);

在這裏插入圖片描述運行報錯:在ES6中,並沒有支持該用法,在ES2017中才有,需要進行編碼後才能執行,轉碼的意思是將ES6或ES2017轉成ES5執行。

1.13.轉碼器

  • BabelBabel (babeljs.io)是一個廣爲使用的ES6轉碼器,可以將ES6代碼轉爲ES5代碼,從而在瀏覽器或其他環境執行。
  • Google公司的Traceur轉碼器(github.com/google/traceur-compiler),也可以將ES6代碼轉爲ES5的代碼。

我們使用的阿里的開源企業級react框架:UmiJS.

# 安裝完node之後,開始安裝yarn,其中tyarn使用的是npm.taobao.org的源,速度要快一些,可以把yarn看成優化後的npm
npm i yarn tyarn -g #-g是全局安裝
tyarn -v #進行測試
tyarn global add umi #開始安裝
umi #進行測試

在項目路徑下:

#通過初始化命令生成package.json文件,它是NodeJS約定的用來存放項目的信息和配置等信息的文件
tyarn init -y
#通過umi命令創建index.js文件
umi g pages index #可以看到在pages下創建好了index.js和index.css文件
#1.12修飾器的js代碼拷貝到index.js
#通過執行命令啓動umi的後臺服務,用於本地開發
umi dev

通過查看網頁源代碼可以看到轉碼之後的代碼在這裏插入圖片描述

1.14.模塊化

模塊化就是把代碼進行拆分,方便重複調用,類似java中的包,要使用一個包,必須先導包。而js中沒有包的概念,換來的是模塊的概念。模塊功能主要兩個命令構成 export import

  • export:命令用於規定模塊的對外接口;
class MyUtils{
    static sum =(a,b) => a + b;
}
export default MyUtils;
  • import:命令用於導入其他模塊提供的功能;
import MyUtils from './MyUtils';
console.log(MyUtils.sum(1,2));

2.ReactJS

2.1.前端開發的演變

到目前爲止,前端的開發經歷了四個階段,目前處在第四個階段

  1. 階段一:靜態頁面階段

在第一個階段中前端頁面都是靜態的,所有前端代碼和前端數據都是後端生成的。前端只是純粹的展示功能。js腳本的作用只是增加一些特殊效果,比如那時很流行用腳本控制頁面上飛來飛去的廣告。

那時候的網站開發,採用的是後端MVC模式,前端只是後端MVC的V

  1. 階段二:ajax階段

2004年,AJAX技術誕生,改變了前端開發,Gmail和Google地圖這樣革命性的產品出現,使得開發者發現,前端的作用不僅僅是展示技術,還可以管理數據並與用戶互動。

  1. 階段三:前端MVC階段

2010年,第一個前端MVC框架Backbone.js誕生,它基本上是把MVC模式搬到了前端,但是隻有M(讀寫數據)和V(展示數據),沒有C(處理數據)。有些框架提出了MVVM代替Controller。Model拿到數據後,VIew Model將數據處理成視圖層需要的格式,在視圖層展示出來。

  1. 階段四:SPA階段

前端可以做到讀寫數據,切換視圖,用戶交互,這意味着,網頁其實是一個應用程序,而不是信息的純展示,這種單張網頁應用被稱爲SPA(single-page-application)

目前最流行的前端框架 Vue ,Angular,React都屬於SPA開發框架。

2.2.ReactJS簡介

ReactJS就是一個用於構建用戶界面的JavaScript框架,是Facebook開發的一款JS框架。ReactJS把複雜的頁面拆分成一個個的組件,將這些組件一個個的拼裝起來,就會呈現多樣化的頁面

ReactJS圈內的一些框架簡稱:

  • Flux:Flux是Facebook用戶建立客戶端Web應用的前端架構,它通過利用一個單向的數據流補充了React的組合視圖組件,這更是一種模式而非框架。
  • Redux:Redux是JavaScript狀態容器,提供可預測化的狀態管理。Redux可以讓React組件狀態共享變得簡單。
  • Ant Design of React:阿里開源的基於React的企業級後臺產品,其中集成了多種框架,包含了上面提到的Flux,Redux。Ant Design提供了豐富的組件。

2.3.環境搭建

  1. 第一步:輸入命令進行初始化
tyarn init -y
  1. 第二步:項目中添加umi的依賴
tyarn add umi --dev

在umi中,約定的目錄結構如下:
在這裏插入圖片描述
3. 第三步,在工程的根目錄下創建config目錄,在config目錄下創建config.js文件。在UmiJS的約定中,config/config.js將作爲UmiJS的全局配置文件。在config.js文件中輸入以下內容,方便後面使用

//導出一個對象,暫時設置爲空對象,後面再填充內容
export default {};
  1. 第四步,創建HelloWorld.js頁面文件

在umi中,約定存放頁面代碼的文件夾是在src/pages,

export default ()=>{
    //這是ReactJS自創的寫法,叫做JSX
    return <div>hello world</div>;
    //在umi中,可以使用約定式的路由,在pages下面的JS文件都會按照文件名映射到一個路由,比如上面的這個訪問 /HelloWorld 會對應到HelloWorld.js.
}
  1. 第五步:啓動服務查看效果
umi dev
  1. 第六步:添加 umi-plugin-react 插件
tyarn add umi-plugin-react --dev
  1. 第七步:在config.js中引入該插件
export default {
    plugins: [
        ['umi-plugin-react',{
            //暫時不開啓任何功能
        }]
    ]
};
  1. 第八步:構建與部署
umi build

2.4.ReactJS介紹

2.4.1.JSX語法

JSX語法就是,可以在js文件中插入html片段。JSX語法會被Babel轉碼工具進行轉碼,得到正常的js代碼再執行。

使用JSX語法,需要注意2點。

  1. 所有的html標籤必須是閉合的,如<div>hello world</div>
  2. 在JSX語法中只能有一個根標籤,不能有多個。
  3. 在JSX語法中,如果想要在html標籤中插入js腳本,需要{}插入JS腳本。
export default ()=>{
    //這是ReactJS自創的寫法,叫做JSX
    const t =() => "你好";
    return (<div>hello world {t()}</div>);
}

2.4.2.組件

  1. 自定義一個組件
import React from 'react';

class HelloWorld extends React.Component{
    //render渲染
    render(){
    return (<div>Hello World ,name = {this.props.name},content= {this.props.children}</div>);
    }
}

export default HelloWorld;
  1. 導入自定義組件
import React from 'react';
import HelloWorld from './HelloWorld';

class Show extends React.Component{
    render(){
        return <HelloWorld name="張三">你好呀</HelloWorld>;
    }

}
export default Show;

輸出結果:
在這裏插入圖片描述

2.4.3.組件狀態

每個組件都有一個狀態,其保存在this.state中,當狀態值發生改變時,React框架會自動調用render()方法,重新渲染頁面。

注意:

  • this.state值的設置要在構造函數參數中完成;
  • 要修改this.state的值,需要調用this.setState()完成,不能直接對this.state進行修改。
import React from 'react';

class List extends React.Component{

    constructor(props){
        super(props);
        this.state = {
            dataList : [1,2,3],
            maxNum : 3
        }
    }

    render(){
        return (
            <div>
                <ul>
                    {
                        this.state.dataList.map((value,index)=>{
                            return <li key ={index}>{value}</li>
                        })
                    }
                </ul>
                <button onClick={()=>{
                    let maxNum = this.state.maxNum + 1;
                    let newArr = [...this.state.dataList,maxNum];
                    this.setState({
                        dataList : newArr,
                        maxNum : maxNum
                    })
                }}>點我試試</button>
            </div>
        );
    }
}

export default List;

2.4.4.生命週期

在這裏插入圖片描述

import React from 'react'; //第一步,導入React
class LifeCycle extends React.Component {
    constructor(props) {
        super(props);
        //構造方法
        console.log("constructor()");
    }
    componentDidMount() {
        //組件掛載後調用
        console.log("componentDidMount()");
    }

    componentWillUnmount() {
        //在組件從 DOM 中移除之前立刻被調用。
        console.log("componentWillUnmount()");
    }

    componentDidUpdate() {
        //在組件完成更新後立即調用。在初始化時不會被調用。
        console.log("componentDidUpdate()");
    }
    
    shouldComponentUpdate(nextProps, nextState) {
        // 每當this.props或this.state有變化,在render方法執行之前,就會調用這個方法。
        // 該方法返回一個布爾值,表示是否應該繼續執行render方法,即如果返回false,UI 就不會更新, 默認返回true。
        // 組件掛載時,render方法的第一次執行,不會調用這個方法。
        console.log("shouldComponentUpdate()");
    }
    
    render() {
        return (
            <div>
                <h1>React Life Cycle!</h1>
            </div>
        );
    }
}
export default LifeCycle;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章