React學習筆記-day01

1.let,const,var的區別:

var聲明的變量一般是屬於全局的變量。letconst是ES 6中新增的兩個關鍵字,用來聲明變量,let和const都是塊級作用域。let聲明的變量只在let命令所在的代碼塊內有效。const聲明一個只讀的常量,一旦聲明,常量的值就不能改變。

{
  let a = 100
 console.log(a);//100
}
 console.log(a);//Uncaught ReferenceError: a is not defined
​
{
   const a = 100
  console.log(a);//100
  a=1000;//Assignment to constant variable.
}
​
{
    var a = 100
 console.log(a);//100
}
console.log(a);//100
​

2.箭頭函數:

​ ES 6允許使用“箭頭”(=>)定義函數。這種方式創建的函數不需要function 關鍵字,並且還可以省略return關鍵字。同時,箭頭函數內的this指向函數定義時所在的上下文對象,而不是函數執行時的上下文對象。

​ 注意事項: 1.當我們的函數的參數爲空時我們可以寫成 var demo=()=>{}。 2.當我們函數處理的邏輯代碼只用一行時函數體的"{}"可以省略不寫。 3.函數的參數只有一個時我們可以寫成var demo =m=>{}

//原始定義的函數:
function add(num1,num2){
    return num1+num2;
}
add(111,222);
​
//箭頭函數的改寫:
var amount=(num1,num2)=>num1+num2;
amount(1001,1002);
​
//空參數的箭頭函數:
var demo =()=>{
console.log("hello");
}
demo();//hello
​
//函數的邏輯代碼只有一行時:
var f=(a,b)=>a+b;
f(100,200);
300
​
var f=()=>"Hello world!";
f();//Hello world!
​
//一個參數的箭頭函數:
var demo =m=>{
    console.log(m);
}
demo("hello world!");//hello world!

3.數據的結構賦值:

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

//對象的結構賦值1
let name = 'Lily';
let age = 4;
let person = {name, age};
person; // Object {name: "Lily", age: 4}
​
//對象解構賦值2
let person = {name: 'Lily', age: 4};
let {name, age} = person;
person;//
​
//數組的結構賦值:
let [a,b,c] = [1, 2, 3];
a //1
b //2
c //3
​
//對象參數解構
function sum ({x, y}) {
return x + y;
}
sum({x:1, y:2}); // 3

4.Rest參數:

ES 6引入rest參數(形式爲...變量名)用於獲取函數的多餘參數,以代替arguments對象的使用。rest參數是一個數組,數組中的元素是多餘的參數。注意,rest參數之後不能再有其他參數。

function languages(lang, ...types){
console.log(types);
}
languages('JavaScript', 'Java', 'Python'); //["Java",
"Python"]

5.React組件:

有狀態組件,無狀態組件

​ 如果一個組件的內部狀態是不變的,當然就用不到state,這樣的組件稱之爲無狀態組件。反之,一個組件的內部狀態會發生變化,就需要使用state來保存變化,這樣的組件稱之爲有狀態組件。

//有狀態組件
import React, { Component } from "react";
class PostItem extends Component {
    //初始化數據的構造函數      
    //組件通過props接收外部傳入的數據(包括方法)
    //state是組件對內的接口,組件的內部的變化通過state來反映
    //state是可變的,props是隻讀的在組件的內部不能修改props的數據值
    constructor(props) {
        super(props);
        //初始化組件的狀態
        this.state = {
            vote: 0
        };
    }
    //處理點讚的業務邏輯
    handleClick() {
        let vote = this.state.vote;
        vote++;
        this.setState({
            vote: vote
        });
​
    }
    render() {
        const { title, author, date } = this.props;
        return (
            <li>
                <div>
                    {title}
                </div>
​
                <div>
                    創建人:<span>{author}</span>
                </div>
​
                <div>
                    創建時間:<span>{date}</span>
                </div>
​
                <div>
                    <button
                        onClick={() => {
                            this.handleClick();
                        }}
                    >
                        點贊
                    </button>
                    &nbsp;
                    <span>
                        {this.state.vote}
                    </span>
                </div>
            </li>
        );
    }
}
export default PostItem;
​
​
//無狀態組件
import React, { Component } from "react";
import PostItem from "./PostItem";
​
const data =[
    { title: "大家一起來討論React吧", author: "張三", date:
    "2017-09-01 10:00" },
    { title: "前端框架,你最愛哪一個", author: "李四", date:
    "2017-09-01 12:00" },
    { title: "Web App的時代已經到來", author: "王五", date:
    "2017-09-01 14:00" }
];
​
class PostList extends Component {
    render() {
        const {title,author,date} = this.props;
        return (
            <div>
                帖子列表:
                <ul>
                   {
                    data.map(item=>(
                            <PostItem
                            title={item.title}
                            author={item.author}
                            date={item.date}
                            />
                       )
                    )
                   }
                </ul>
            </div>
        );
    }
}
export default PostList;
​
​
​
​
​
使用函數對組件的狀態進行重構:
//有狀態組件
import React, { Component } from "react";
import PostItem from "./PostItem";
//getDefaultProps、getInitialState、componentWillMount、render 和 componentDidMount。
const data = [
    {
        title: "大家一起來討論React吧", author: "張三", date:
            "2017-09-01 10:00"
    },
    {
        title: "前端框架,你最愛哪一個", author: "李四", date:
            "2017-09-01 12:00"
    },
    {
        title: "Web App的時代已經到來", author: "王五", date:
            "2017-09-01 14:00"
    },
​
];
class PostList extends Component {
    constructor(props) {
        super(props);
        this.state = {
            posts: []
        };
        this.timer = null;//定時器
        this.handleVote = this.handleVote.bind(this);//ES 6class中,必須手動綁定方法this的指向
    }
    //生命週期的方法
    componentDidMount() {
        //// 用setTimeout模擬異步從服務器端獲取數據,然後調用setState更新組件狀態。
        this.timer = setTimeout(() => {
            this.setState({
                posts: [
                    { id: 1, title: "大家一起來討論React吧", author: "張三", date: "2017-09-01 10:00", vote: 0 },
                    { id: 2, title: "前端框架,你最愛哪一個", author: "李四", date: "2017-09-01 12:00", vote: 0 },
                    { id: 3, title: "Web App的時代已經到來", author: "王五", date: "2017-09-01 14:00", vote: 0 }
                ]
            });
        }, 1000);
    }
​
    componentWillUnmount() {
        if (this.timer) {
            clearTimeout(this.timer); // 清除定時器
        }
    }
​
    handleVote(id) {
        //根據帖子id進行過濾,找到待修改vote屬性的帖子,返回新的posts對象
        const posts = this.state.posts.map(item => {
            const newItem = item.id === id ? { ...item, vote: ++item.vote }:item;
            return newItem;
        });
        // 使用新的posts對象設置state
        this.setState({
            posts
        });
    }
​
​
    render() {
        return (
            <div>
                帖子列表:
                <ul>
                    {
                       this.state.posts.map(item => 
                            <PostItem
                              post = {item}
                              onVote = {this.handleVote}
                            />
                        )
                    }
                </ul>
            </div>
        );
    }
}
export default PostList;
​
​
//使用函數的無狀態組件
import React, { Component } from "react";
function PostItem(props) {
    const handleClick = () => {
        props.onVote(props.post.id);
    };
    const { post } = props;
    return (
        <li>
            <div>
                {post.title}
            </div>
            <div>
                創建人:<span>{post.author}</span>
            </div>
            <div>
                創建時間:<span>{post.date}</span>
            </div>
            <div>
                <button onClick={handleClick}>點贊</button>
                &nbsp;
            <span>{post.vote}</span>
            </div>
        </li>
    );
}
export default PostItem;

 

6.屬性的校驗:

​ React提供了PropTypes這個對象,用於校驗組件屬性的類型。PropTypes包含組件屬性所有可能的類型,我們通過定義一個對象(對象的key是組件的屬性名,value是對應屬性的類型)實現組件屬性類型的校驗。

PropTypes可以校驗的組件屬性類型。

類型 PropTypes對應屬性String PropTypes.stringNumber PropTypes.numberBoolean PropTypes.boolFunction PropTypes.funcObject PropTypes.objectArray PropTypes.arraySymbol PropTypes.symbolElement(React元素) PropTypes.elementNode(可被渲染的節點:數字、字符串、React元素或由這些類型的數據組成的數組) PropTypes.node

示例如下:class PostItem extends React.Component {}PostItem.propTypes = {post: PropTypes.object,onVote: PropTypes.func};

當使用PropTypes.object或PropTypes.array校驗屬性類型時,我們只知道這個屬性是一個對象或一個數組,至於對象的結構或數組元素的類型是什麼樣的,依然無從得知。這種情況下,更好的做法是使用PropTypes.shape PropTypes.arrayOf。

例如:
style: PropTypes.shape({
color: PropTypes.string,
fontSize: PropTypes.number
}),
sequence: PropTypes.arrayOf(PropTypes.number)
​
​
PostItem.propTypes = {
post: PropTypes.shape({
id: PropTypes.number,
title: PropTypes.string,
author: PropTypes.string,
date: PropTypes.string,
vote: PropTypes.number
}).isRequired,
onVote: PropTypes.func.isRequired
}
​

defaultProps:React還提供了爲組件屬性指定默認值的特性,這個特性通過組件的defaultProps實現。當組件屬性未被賦值時,組件會使用defaultProps定義的默認屬性。例如:function Welcome(props) {return <h1 className='foo'>Hello, {props.name}</h1>;}Welcome.defaultProps = {name: 'Stranger'};

 

7.組件的樣式:

我們爲組件添加樣式的方式有兩種:外部CSS樣式和內聯的樣式.

外部的CSS樣式:就是通過編寫想要的css文件,在需要的地方進行引入即可。(兩種引入的方式)1.<link rel="stylesheet" type="text/css" href="style.css">2.import './style.css'; //要保證相對路徑設置正確

內聯的樣式:直接將我們需要的樣式寫入相應需要的地方即可。

function Welcome(props) {
return (
<h1
style={{
width: "100%",
height: "50px",
backgroundColor: "blue",
fontSize: "20px"
}}
Hello, {props.name}
</h1>
);
}
​

8.組件的生命週期:

​ 組件從被創建到被銷燬的過程稱爲組件的生命週期。組件的生命週期可以分爲三個階段:掛載階段,更新階段,卸載階段。

注意:

​ 只有類組件才具有生命週期方法,函數組件是沒有生命週期方法的,因此永遠不要在函數組件中使用生命週期方法。

8.1掛載階段:

這個階段組件被創建,執行初始化,並被掛載到DOM中,完成組件的第一次渲染。依次調用的生命週期方法有:(1)constructor:創建組件時我們首先會調用構造函數去接收一個props參數,props一般是從父組件中傳入的屬性對象,如果父組件中沒有傳入屬性數據而自身定義了屬性的數據,則這個props值得就是組件的默認的屬性的數據。我們要在這個方法中調用super(props)才能保證props被傳入組件中。constructor通常用於初始化組件的state以及綁定事件處理方法等工作。(2)componentWillMount:這個方法在組件被掛載到DOM前調用,且只會被調用一次。。在這個方法中調this.setState不會引起組件的重新渲染。(3)render:這個是定義組件的唯一必要的方法(組件的其他的生命週期可以省略)。在這個方法中,根據組件的props和state返回一個React元素,用於描述組件的UI,通常React元素使用JSX語法定義。需要注意的是,render並不負責組件的實際渲染工作,它只是返回一個UI的描述,真正的渲染出頁面DOM的工作由React自身負責。render是一個純函數,在這個方法中不能執行任何有副作用的操作,所以不能在render中調用this.setState,這會改變組件的狀態。(4)componentDidMount:在組件被掛載到DOM後調用,且只會被調用一次。這時候已經可以獲取到DOM結構,因此依賴DOM節點的操作可以放到這個方法中。這個方法通常還會用於向服務器端請求數據。在這個方法中調用this.setState會引起組件的重新渲染。

8.2組件的更新:

組件的更新實質上是因爲組件的props或者state的數據變化引起的組更新,props引起的組件的更新實質上是由父組件引起的,就是父組件的Render方法被調用時組件會發生更新。state引起的組件的更新是通過調用this.setState修改組件的state來進行觸發的。組件更新調用的方法是:

(1)componentWillReceiveProps(nextProps);這個方法只在props引起的組件更新過程中,纔會被調用。State引起的組件更新並不會觸發該方法的執行。方法的參數nextProps是父組件傳遞給當前組件的新的props。但如上文所述,父組件render方法的調用並不能保證傳遞給子組件的props發生變化,也就是說nextProps的值可能和子組件當前props的值相等,因此往往需要比較nextProps和this.props來決定是否執行props發生變化後的邏輯,比如根據新的props調用this.setState觸發組件的重新渲染。(2)shouldComponentUpdate(nextProps,nextState):這個方法決定組件是否繼續執行更新過程。當方法返回true時(true也是這個方法的默認返回值),組件會繼續更新過程;當方法返回false時,組件的更新過程停止,後續的componentWillUpdate、render、componentDidUpdate也不會再被調用。一般通過比較nextProps、nextState和組件當前的props、state決定這個方法的返回結果。這個方法可以用來減少組件不必要的渲染,從而優化組件的性能。(3)componentWillUpdate(nextProps,nextState):這個方法在組件render調用前執行,可以作爲組件更新發生前執行某些工作的地方,一般也很少用到。(4)render(5)componentDidUpdate(prevProps,prevState);組件更新後被調用,可以作爲操作更新後的DOM的地方。這個方法的兩個參數prevProps、prevState代表組件更新前的props和state。

8.3組件的卸載工作

組件的卸載的過程只會調用一個生命週期的方法componentWillUnmount,這個方法可以執行一些組件的清理工作,比如清除組件中的定時器避免內存泄漏。

9.列表和Keys

組件中的列表:組件中的列表我們可以將它理解爲數據的集合。

組件的keys: React使用key屬性來標記列表中的每個元素,當列表數據發生變化時,React就可以通過key知道哪些元素髮生了變化,從而只重新渲染髮生變化的元素,提高渲染效率。

10.事件的處理

注意的事項:1.事件的命名採用駝峯的命名方式:onclick要寫成onClick,onchange要寫成onChange等。2.處理事件的響應函數要以對象的形式賦值給事件的屬性。

//DOM中的事件綁定:
<button onclick="clickButton()">
Click
</button>
​
//而在React元素中綁定一個點擊事件變成這種形式:
<button onclick={clickButton}> //clickButton是一個函數
Click
</button>

1.在DOM事件中,可以通過處理函數返回false來阻止事件的默認行爲,但在React事件中,必須顯式地調用事件對象的preventDefault方法來阻止事件的默認行爲。除了這一點外,DOM事件和React事件在使用上並無差別。2.如果在某些場景下必須使用DOM提供的原生事件,可以通過React事件對象的nativeEvent屬性獲取。

//1.使用箭頭函數
//每次調用render方法時,都會重新的創建一個新的事件的處理函數,系統的性能降低
import React, { Component } from "react";
class MyContent extends React.Component {
    constructor(props) {
        super(props);
        this.state = { number: 0 }
    }
    // 每點擊一次Button,state中的number增加1
    handleClick(event) {
        const number = ++this.state.number;
        this.setState({
            number: number
        });
    }
    render() {
        return (
            <div>
                <div>{this.state.number}</div>
                <button onClick={(event) => { this.handleClick(event); }}>
                    Click
                </button>
            </div>
        );
    }
}
export default MyContent;
​
//使用組件的方法01
import React, { Component } from "react";
class MyContent extends React.Component {
    constructor(props) {
        super(props);
        this.state = { number: 0 }
        //將組件的方法賦值給元素的事件屬性,同時在類的構造函數中,將這個方法的this綁定到當前對象
        this.handleClick = this.handleClick.bind(this);
    }
    // 每點擊一次Button,state中的number增加1
    handleClick(event) {
        const number = ++this.state.number;
        this.setState({
            number: number
        });
    }
    render() {
        return (
            <div>
                <div>{this.state.number}</div>
                <button onClick={this.handleClick}>
                    Click
                </button>
            </div>
        );
    }
}
export default MyContent;
​
//使用組件的方法02
import React, { Component } from "react";
class MyContent extends React.Component {
    constructor(props) {
        super(props);
        this.state = { number: 0 }
    }
    // 每點擊一次Button,state中的number增加1
    handleClick(event) {
        const number = ++this.state.number;
        this.setState({
            number: number
        });
    }
    render() {
        return (
            <div>
                <div>{this.state.number}</div>
                {/* 事件屬性賦值和this同時綁定*/}
                <button onClick={this.handleClick.bind(this)}>
                    Click
                </button>
            </div>
        );
    }
}
export default MyContent;
​
​
//使用ES 7的property initializers會自動爲class中定義的方法綁定this。
//但是目前還處於實驗階段,默認是不支持的
import React, { Component } from "react";
class MyContent extends React.Component {
    constructor(props) {
        super(props);
        this.state = { number: 0 };
    }
    // ES7的屬性初始化語法,實際上也是使用了箭頭函數
    handleClick = (event) => {
        const number = ++this.state.number;
        this.setState({
            number: number
        });
    }
    render() {
        return (
            <div>
                <div>{this.state.number}</div>
                <button onClick={this.handleClick}>
                    Click
    </button>
            </div>
        );
    }
}
export default MyContent;

11.表單

受控組件:

​ 表單中元素的狀態變化是受到React控制的,狀態的修改是通過組件的state進行的。

文本框的受控原理:

​ 文本框包含類型爲text的input元素和textarea元素。它們受控的主要原理是,通過表單元素的value屬性設置表單元素的值,通過表單元素的onChange事件監聽值的變化,並將變化同步到React組件的state中

import React, { Component } from "react";
​
class LoginForm extends React.Component {
    constructor(props) {
        super(props);
        this.state = { name: '', password: '' };
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }
​
    //對用戶名和密碼兩個input進行監聽
    handleChange(event) {
        const target = event.target;
        this.setState({ [target.name]: target.value });
        console.log(this.state);
    }
    //表單提交的響應的函數
    handleSubmit(event) {
        console.log('login successfuly');
        event.preventDefault();
       console.log("handleSubmit觸發執行"+":"+this.state);
    }
​
    render() {
        return (
            <form onSubmit={this.handleSubmit}>
                <label>
                    用戶名:
                    <input type="text" name="name" value={this.state.name} onChange={this.handleChange}/>
                </label>
                <label>
                    密碼:
                    <input type="password" name="password" value={this.state.password} onChange={this.handleChange}/>
                </label>
              <input type="submit" value="登錄"/>
​
            </form>
        )
    }
}
 export default  LoginForm

列表:

import React, { Component } from "react";
class ReactStackForm extends React.Component {
    constructor(props) {
        super(props);
        this.state = { value: 'mobx' };
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }
    //監聽下列表的變化
    handleChange(event) {
        this.setState({ value: event.target.value });
    }
    //表單提交的響應的函數
    handleSubmit(event) {
        alert('You picked ' + this.state.value);
        event.preventDefault();
    }
    render() {
        return (
            <form onSubmit={this.handleSubmit}>
                <label>
                Pick one library:
                  {/* 
                    select的value屬性定義當前哪個option元素處於選中狀態
                    */}
                    <select value={this.state.value} onChange={this.handleChange}>
                        <option value="react">React</option>
                        <option value="redux">Redux</option>
                        <option value="mobx">MobX</option>
                    </select>
                </label>
                <input type="submit" value="Submit" />
​
            </form>
        )
    }
}
export default ReactStackForm;

複選和單選:

import React, { Component } from "react";
class ReactSelectForm extends React.Component {
    constructor(props) {
        super(props);
        this.state = { react: false, redux: false, mobx: false };
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }
​
    //監聽複選框變化,設置複選框的checked狀態
    handleChange(event) {
        this.setState({ [event.target.name]: event.target.checked });
        console.log(this.state);
        console.log(this.state.react);
    }
    //表單提交的響應的函數
    handleSubmit(event) {
        //顯式地調用事件對象的preventDefault方法來阻止事件的默認行爲
        event.preventDefault();
        console.log(this.state);
    }
​
    render() {
        return (
            <form onSubmit={this.handleSubmit}>
                {/* 設置3個複選框 */}
                <label>React
               <input
                        type="checkbox"
                        name="react"
                        value="react"
                        checked={this.state.react}
                        onChange={this.handleChange}
                    />
                </label>
                <label>Redux
                <input
                        type="checkbox"
                        name="redux"
                        value="redux"
                        checked={this.state.redux}
                        onChange={this.handleChange}
                    />
                </label>
                <label>MobX
                <input
                        type="checkbox"
                        name="mobx"
                        value="mobx"
                        checked={this.state.mobx}
                        onChange={this.handleChange}
                    />
                </label>
                <input type="submit" value="Submit" />
            </form>
        )
    }
}
export default ReactSelectForm;

非受控組件:

​ 其原理有悖於受控組件,其狀態的變化是不受組件的state控制的。非受控組件指表單元素的狀態依然由表單元素自己管理,而不是交給React組件管理。使用非受控組件需要有一種方式可以獲取到表單元素的值,React中提供了一個特殊的屬性ref,用來引用React組件或DOM元素的實例,因此我們可以通過爲表單元素定義ref屬性獲取元素的值。

​
import React, { Component } from "react";
class SimpleForm extends Component {
    constructor(props) {
        super(props);
        this.handleSubmit = this.handleSubmit.bind(this);
    }
    handleSubmit(event) {
        // 通過this.input 獲取到input元素的值
        alert('The title you submitted was ' +
            this.input.value);
        event.preventDefault();
    }
    render() {
        return (
            <form onSubmit={this.handleSubmit}>
                <label>
                    title:
    {/* this.input 指向當前input元素 */}
                    <input type="text" ref={(input) => this.input =
                        input} />
                </label>
                <input type="submit" value="Submit" />
            </form>
        );
    }
}
export default SimpleForm

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章