2018年5月20日 星期日

History (React 16 七)

www.bootcdn.cn:https://cdn.bootcss.com/history/4.7.2/history.js
npm 官網連接
這是用來控制上一頁、下一頁的功能


※createBrowserHistory

<script src="./js/history_4.7.2.js"></script>
    
<script>
const history = History.createBrowserHistory();
    
function push(path) {
    history.push(path);
    return false;
}
    
function goBack() {
    history.goBack();
}
    
function goForword() {
    history.goForward();
}
    
function replace(path) {
    history.replace(path)
}
    
function go(n) {
    console.log(n);
    history.go(n);
}
    
history.listen(path => {
    console.log('path=', path);
})
</script>
    
<a onclick="return push('/reactPractice/historyPractice.htm#aaa')">超連結加入</a>
<button onClick="push('/reactPractice/historyPractice.htm#bbb')">按鈕加入</button>
<button onClick="goBack()">上一頁</button>
<button onClick="goForword()">下一頁</button>
<input type="number" onBlur="go(this.value)" />第?頁
<button onClick="replace('/reactPractice/historyPractice.htm#ccc')">取代</button>

※ aaa -> aaa -> aaa -> bbb -> bbb -> bbb,從左到右執行後,按上一頁、下一頁會有對應的效果

※push 就是從左到右一個一個排進去的

※假設按第五個 bbb 後,按取代鈕,那第五個會變成 ccc,然後上一頁、下一頁依此類推

※go 方法可以傳負數,就是上幾頁的意思,如果上一頁或下一頁沒有,就不執行



※createHashHistory

<script src="./js/history_4.7.2.js"></script>
    
const history = History.createHashHistory();
    
function push(path) {
    history.push(path);
    return false;
}
    
function goBack() {
    history.goBack();
}
    
function goForword() {
    history.goForward();
}
    
function replace(path) {
    history.replace(path)
}
    
function go(n) {
    console.log(n);
    history.go(n);
}
    
history.listen(path => {
    console.log('path=', path);
})
</script>
    
<a onclick="return push('/aaa')">超連結加入</a>
<button onClick="push('/bbb')">按鈕加入</button>
<button onClick="goBack()">上一頁</button>
<button onClick="goForword()">下一頁</button>
<input type="number" onBlur="go(this.value)" />第?頁
<button onClick="replace('/ccc')">取代</button>

※aaa -> aaa -> aaa -> bbb -> bbb -> bbb,使用 createHashHistory 後,必需將連續相同的看成一個,所以要看成 aaa -> bbb,所以按上一頁會直接變成 aaa

※又如果是 aaa -> aaa -> bbb -> bbb -> aaa -> bbb,那就看成 aaa -> bbb -> aaa -> bbb

2018年5月16日 星期三

axios、fetch (React 16 六)

因為 react 沒有 ajax 功能,所以使用第三方的 axios,或者用 javascript 內鍵的 fetch
axios,使用原始的 XmlHttpRequest (XHR)
fetch,ES6 加入的功能,所以舊的瀏覽器沒有這功能


※servlet

@WebServlet("*.do")
public class XxxAction extends HttpServlet {
    private static final long serialVersionUID = 1L;
    
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String acc = request.getParameter("acc");
        String pwd = request.getParameter("pwd");
        response.getWriter().append(acc + "-" + pwd);
    }
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("POST");
        this.doGet(request, response);
    }
}

※寫一支測試用的 servlet



※axios

class Test extends React.Component {
    handleAxios = _ => {
        // GET
        axios.get("abc.do?acc=aaa&pwd=pass")
        .then(res => {
            console.log(res)
        }).catch(err => console.error(err))
    
    
        // POST     
        const params = new URLSearchParams();
        params.append('acc', 'aaa');
        params.append('pwd', 'pass');
    
        axios.post('abc.do', params) // 也可學get在後面加
        .then(res => {
            console.log(res)
        }).catch(err => console.error(err))
    
    
        // AXIOS API - GET
        axios({
            method:'get',
            url:'abc.do?acc=aaa&pwd=pass',
        })
        .then(res => {
            console.log(res)
        });
    
    
        // AXIOS API - POST
        const params = new URLSearchParams();
        params.append('acc', 'aaa');
        params.append('pwd', 'pass');
    
        axios({
            method: 'post',
            url: 'abc.do', // 也可學get在後面加
            data: params
        }).then(res => {
            console.log(res)
        });
    }
    
    render() {
        return (
            <button onClick={this.handleAxios}>按我</button>
        )
    }
}
    
ReactDOM.render(<Test />, document.querySelector("#xxx"));

※post 要使用 URLSearchParams 或第三方的 query-string,可參考npm官網,但我在 npm 環境不用 URLSearchParams 也可以成功,如下:

import React, { Component } from 'react';
import axios from 'axios';
    
class Test extends Component {
    handleAxios = _ => {
        axios.post('http://localhost:8888/TestServlet/abc.do?acc=aaa&pwd=pass', {
            acc:'aaa',
            pwd:'pass'
        })
        .then(res => {
            console.log(res)
        }).catch(err => console.error(err))
    }
    
    render() {
        return (
            <button onClick={this.handleAxios}>按我</button>
        )
    }
}

※如果出現「 No 'Access-Control-Allow-Origin' header is present on the requested resource.」表示不能跨域,可以用瀏覽器的跨域功能 (chrome 在這裡),或者 nginx 的跨域功能如下:


server {
    listen 8888;
    server_name localhost;
    charset UTF-8;
    
    location / {
        proxy_pass http://localhost:10080;
        if ($request_method = 'OPTIONS') {
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range,Token';
            add_header 'Access-Control-Max-Age' 1728000;
            add_header 'Content-Type' 'text/plain; charset=utf-8';
            add_header 'Content-Length' 0;
            return 204;
        }
    
        if ($request_method = 'POST') {
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range,Token';
            add_header 'Access-Control-Expose-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range,Token';
        }
    
        if ($request_method = 'GET') {
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range,Token';
            add_header 'Access-Control-Expose-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range,Token';
        }
    }
}

※收到 localhost:8888 請求後,會導到 localhost:10080,並使用跨域功能

※同源策略:如 http://localhost
1.http
2.localhost
3.port,沒寫就是 80
以上三個一樣才算是同源,如果不同源就不允許跨域
還可參考高手寫的

※還可以使用 query-string,尤於沒找到 browser 的下載點,所以使用 node.js
yarn add query-string

使用時只要  import queryString from 'query-string';
然後 queryString.stringify({acc:'bbb', pwd:'ccc'} 放在 post 第二個參數就搞定了,但 post 不能在第一個參數的 ? 後面加參數,否則會以第一個參數為主


※fetch

// GET
fetch('abc.do?acc=aaa&pwd=pass', {
    method: 'GET'
}).then(res => { 
    console.log('res1=' + res);
})
.catch(err => console.error(err))
    
    
// POST
const params = new URLSearchParams();
params.append('acc', 'aaa');
params.append('pwd', 'pass');
    
fetch('abc.do', { // 也可學get在後面加
    method: 'POST',
    body: params
})
.then(res => res.json)
.then(data => {debugger;
    console.log(data.message)
})
.catch(err => console.error(err))

※參考mozilla 官網

2018年5月13日 星期日

生命週期 (React 16 五)

Component 除了 render 方法以外,還有其他的方法,以下列出一些常用的
render 方法是必要的,其他都是可選的


class Interval extends React.Component {
    constructor(p) {
        super(p)
        console.log("constructor")
        this.state = {
            opa:1
        }
    }
    
    handleCloseInternal() {
        console.log("按關閉了")
        ReactDOM.unmountComponentAtNode(document.querySelector("#div1"))
    }
    
    componentWillMount()  {
        console.log("componentWillMount")
    }
    
    componentDidMount() {
        console.log("componentDidMount")
    }
    
    componentWillUpdate() {
        console.log("componentWillUpdate")
    }
    
    componentDidUpdate() {
        console.log("componentDidUpdate")
    }
    
    componentWillUnmount() {
        console.log("componentWillUnmount")
    }
    
    render() {
        console.log("render")
        return (
            <div>
                <h1 style={{opacity:this.opa}}>{this.props.title}
關閉, document.querySelector("#div1"));
※覆寫的方法都是 component 開頭

※componentWillUnmount 要按關閉鈕才會執行

※componentWillMount  ->  render  ->  componentDidMoun,在 render 前後各有方法執行

※componentWillUpdate 和 componentDidUpdate 會在 setState 前後執行,但此例沒寫 setState,所以沒執行



※文字漸淡效果

class Interval extends React.Component {
    constructor(p) {
        super(p)
        console.log("constructor")
        this.state = {
            opa:1
        }
    }
    
    handleCloseInternal() {
        console.log("按關閉了")
        ReactDOM.unmountComponentAtNode(document.querySelector("#div1"))
    }
    
    componentWillMount()  {
        console.log("componentWillMount")
    }
    
    componentDidMount() {
        console.log("componentDidMount")
        /*
        this.intervalId = setInterval(() => {
            let {opa} = this.state
            opa -= 0.2
            if(opa <= 0) {
                opa = 1
            }
            this.setState({opa})
        }, 500)
        */
    
        this.intervalId = setInterval(function() {
            let {opa} = this.state
            opa -= 0.2
            if(opa <= 0) {
                opa = 1
            }
            this.setState({opa})
        }.bind(this), 500)
    }
    
    componentWillUpdate() {
        console.log("componentWillUpdate")
    }
    
    componentDidUpdate() {
        console.log("componentDidUpdate")
    }
    
    componentWillUnmount() {
        console.log("componentWillUnmount")
        clearInterval(this.intervalId)
    }
    
    render() {
        console.log("render")
        return (
            <div>
                <h1 style={{opacity:this.opa}}>{this.props.title}
關閉, document.querySelector("#div1"));

※注意 style 是用兩個花括號

※setInterval 使用箭頭函數可以不用 bind

※小數點會有誤差,所以用 <= 0

表單 (React 16 四)

受控組件:值會自動更新
非受控組件:值不會自動更新

※非受控組件



class FormPractice1 extends React.Component {
    constructor(p) {
        super(p)
        this.handleSubmit = this.handleSubmit.bind(this)
    }
    
    handleSubmit(e) {
        e.preventDefault() // 阻止提交
        alert(this.fname.value)
        alert(this.fpassword.value)
        // document.getElementsByTagName("form")[0].submit() // 提交
    }
    
    render() {
        return ( 
            <form action="xxx" onSubmit={this.handleSubmit}>
                <input name="name" ref={i => this.fname = i} /> 
                <input type="password" name="password" ref={i => this.fpassword = i} /><br />
                <input type="submit" value="提交" />
            </form>
        )
    }
}
    
ReactDOM.render(<FormPractice1 />, document.querySelector("#div1"));




※受控組件



class FormPractice1 extends React.Component {
    constructor(p) {
        super(p)
        this.state = {
            name:'',
            pwd:''
        }
        this.handleSubmit = this.handleSubmit.bind(this)
        this.handleChangeName = this.handleChangeName.bind(this)
        this.handleChangePwd = this.handleChangePwd.bind(this)
    }
    
    handleSubmit(e) {
        e.preventDefault() //阻止提交
        alert(`名稱:${this.state.name}  密碼:${this.state.pwd}`)
        // document.getElementsByTagName("form")[0].submit() // 提交
    }
    
    handleChangeName(e) {
        this.setState({
            name:e.target.value
        })
    }
    
    handleChangePwd(e) {
        this.setState({
            pwd: e.target.value
        })
    }
    
    render() {
        return ( 
            <form action="xxx" onSubmit={this.handleSubmit}>
                <input name="name" value={this.state.name} onChange={this.handleChangeName} /> 
                <input type="password" name="password" value={this.state.pwd} onChange={this.handleChangePwd} /><br />
                <input type="submit" value="提交" />
            </form>
        )
    }
}
    
ReactDOM.render(<FormPractice1 />, document.querySelector("#div1"));

※如果不寫事件,鍵盤打不進去

※onChange 在 React 裡,只要打完字就馬上更新了

組件組合、pubsub-js (React 16 三)

如上圖,分成三個組件,最外面的組件包括兩個組件
在文字輸入一些文字,然後按增加,就會到 radio button 的上面


※先寫靜態

class App extends React.Component {
    constructor(p) {
        super(p)
    }
    
    render() {
        return ( 
            <div>
                <h1>Component 組合練習</h1>
                <Add />
                <RadioList />
            </div>
        )
    }
}
    
class Add extends React.Component {
    constructor(p) {
        super(p)
        this.handleAdd = this.handleAdd.bind(this)
    }
    
    handleAdd() {
        const txt = this.txt.value.trim();
        if(!txt){
            return
        }
    }
    
    render() {
        return (
            <div>
                <input ref={i => this.txt = i}/> 
                <button onClick={this.handleAdd}>增加#5</button>
            </div>
        )
    }
}
    
const xxx = ["a", "b", "c"];
class RadioList extends React.Component {
    constructor(p) {
        super(p)
    }
    
    render() {
        return (
            <ul>
                {
                    xxx.map((data, i) => <li key={i}><input type="radio" name="x" />{data}</li>)
                }
            </ul>
        )
    }
}
    
ReactDOM.render(<App />, document.querySelector("#div1"));



※再寫動態

class App extends React.Component {
    constructor(p) {
        super(p)
        this.state = {
            data:["a", "b", "c"]
        }
    }
    
    render() {
        return ( 
            <div>
                <h1>Component 組合練習</h1>
                <Add count={this.state.data.length} />
                <RadioList data={this.state.data} />
            </div>
        )
    }
}
    
class Add extends React.Component {
    constructor(p) {
        super(p)
        this.handleAdd = this.handleAdd.bind(this)
    }
    
    handleAdd() {
        const txt = this.txt.value.trim()
        if(!txt) {
            return
        }
        console.log(txt)
    }
    
    render() {
        return (
            <div>
                <input ref={i => this.txt = i}/> 
                <button onClick={this.handleAdd}>增加#{this.props.count + 1}</button>
            </div>
        )
    }
}
    
Add.propTypes = {
    count : PropTypes.number.isRequired
}
    
// const xxx = ["a", "b", "c"];
class RadioList extends React.Component {
    constructor(p) {
        super(p)
    }
    
    render() {
        return (
            <ul>
                {
                    this.props.data.map((data, i) => {
                        return <li key={i}><input type="radio" name="x" />{data}</li>
                    })
                }
            </ul>
        )
    }
}
    
RadioList.propTypes = {
    data : PropTypes.array.isRequired
}
    
ReactDOM.render(<App />, document.querySelector("#div1"));



※互動

class App extends React.Component {
    constructor(p) {
        super(p)
        this.state = {
            data:["a", "b", "c"]
        }
        this.addNewData = this.addNewData.bind(this)
    }
    
    addNewData(newData) {
        this.state.data.unshift(newData)
        this.setState({data : this.state.data})
    }
    
    render() {
        return ( 
            <div>
                <h1>Component 組合練習</h1>
                <Add count={this.state.data.length} addNewData={this.addNewData} />
                <RadioList data={this.state.data} />
            </div>
        )
    }
}
    
class Add extends React.Component {
    constructor(p) {
        super(p)
        this.handleAdd = this.handleAdd.bind(this)
    }
    
    handleAdd() {
        const txt = this.txt.value.trim()
        if(!txt) {
            return
        }
        this.props.addNewData(txt)
        this.txt.value = ''
    }
    
    render() {
        return (
            <div>
                <input ref={i => this.txt = i}/> 
                <button onClick={this.handleAdd}>增加#{this.props.count + 1}</button>
            </div>
        )
    }
}
    
Add.propTypes = {
    count : PropTypes.number.isRequired,
    addNewData : PropTypes.func.isRequired
}
    
class RadioList extends React.Component {
    constructor(p) {
        super(p)
    }
    
    render() {
        return (
            <ul>
                {
                    this.props.data.map((data, i) => {
                        return <li key={i}><input type="radio" name="x" />{data}</li>
                    })
                }
            </ul>
        )
    }
}
    
RadioList.propTypes = {
    data : PropTypes.array.isRequired
}
    
ReactDOM.render(<App />, document.querySelector("#div1"));

※由於子組件不能使用 this.state 改變父組件的狀態
而狀態在哪一個組件,this.state 就寫在哪
所以傳一個 function 給子組件調用



※簡化並整理代碼

class App extends React.Component {
    state = {
        data:["a", "b", "c"]
    }
    
    addNewData = (newData) => {
        const {data} = this.state
        data.unshift(newData)
        this.setState({data})
    }
    
    render() {
        const {data} = this.state;
        return ( 
            <div>
                <h1>Component 組合練習</h1>
                <Add count={data.length} addNewData={this.addNewData} />
                <RadioList data={data} />
            </div>
        )
    }
}
    
class Add extends React.Component {
    static propTypes = {
        count : PropTypes.number.isRequired,
        addNewData : PropTypes.func.isRequired
    }
    
    handleAdd = _ => {
        const txt = this.txt.value.trim()
        if(!txt) {
            return
        }
        this.props.addNewData(txt)
        this.txt.value = ''
    }
    
    render() {
        return (
            <div>
                <input ref={i => this.txt = i}/> 
                <button onClick={this.handleAdd}>
                    增加#{this.props.count + 1}
                </button>
            </div>
        )
    }
}
    
class RadioList extends React.Component {
    static propTypes = {
        data : PropTypes.array.isRequired
    }
    
    render() {
        const {data} = this.props
        return (
            <ul>
                {
                    data.map((data, i) => {
                        return (
                            <li key={i}>
                                <input type="radio" name="x" />
                                {data}
                            </li>
                        )
                    })
                }
            </ul>
        )
    }
}
    
ReactDOM.render(<App />, document.querySelector("#div1"));

※使用箭頭函數不用 bind

※this.state 寫在外面,是因為繼承了 React.Component 才可以這麼做,ES6 不可以

※propTypes 寫在類別裡

※修改成解構賦值,以下是原理:
const {a} = {a:1}
console.log(a); // 1
    
const {b, c} = {b:2, c:3}
console.log(b, c); // 2, 3
    
    
const ooo = {d:4}
const {d} = ooo;
console.log(d); // 4
    
const xxx = {e:5, f:6}
const {e, f} = xxx;
console.log(e, f); // 5, 6

※ooo 和 xxx 就好比是 this.state



※pubsub-js

可以在全域宣告,可以解決上面的傳 func 的問題,父子間、兄弟間傳參都很麻煩,可以用這種辦法解決,官網連結
www.bootcdn.cn 的下載點:https://cdn.bootcss.com/pubsub-js/1.6.0/pubsub.js
使用 Node.js:到專案路徑下,執行 yarn add pubsub-js
執行完可下 npm list pubsub-js 查看是否成功
然後使用 import PubSub from 'pubsub-js'; 即可



<title>PubSub練習</title>
<script src="./js/development_16.3.2.js"></script>
<script src="./js/dom.development_16.3.2.js"></script>
<script src="./js/babel_7.0.0-beta.3.js"></script>
<script src="pubsub_1.6.0.js"></script>
    
    
    
<div id="div1"></div>
<script type="text/babel">
class App extends React.Component {
    declare = _ => {
        PubSub.subscribe('xxx', (p1, p2) => {
            console.log("p1=" + p1, "p2=" + p2) // p1=xxx p2=xxxxx
        });
    }
    
    trigger = _ => {
        PubSub.publish('xxx', 'xxxxx');
    }
    
    noTrigger = _ => {
        PubSub.unsubscribe('xxx');
    }
    
    render() {
        return (
            <div>
                <h1>PubSub 練習</h1>
                <button onClick={this.declare}>宣告</button>
                <button onClick={this.trigger}>觸發</button>
                <button onClick={this.noTrigger}>不想再觸發</button>
            </div>
        )
    }
}
    
ReactDOM.render(<App />, document.querySelector("#div1"));
</script>

※還有很多小技巧,自行參考官網


※再次將組件簡化後的代碼

<script src="./js/development_16.3.2.js"></script>
<script src="./js/dom.development_16.3.2.js"></script>
<script src="./js/babel_7.0.0-beta.3.js"></script>
<script src="prop-types.js"></script>
<script src="pubsub_1.6.0.js"></script>
    
    
    
<div id="div1"></div>
<script type="text/babel">
class App extends React.Component {
    state = {
        data:["a", "b", "c"],
        declareXxx: _ => {
            PubSub.subscribe('xxx', (p1, newData) => {
                const {data} = this.state
                data.unshift(newData)
                this.setState({data})
            });
        }
    }
    
    render() {
        this.state.declareXxx();
        const {data} = this.state;
        return (
            <div>
                <h1>Component 組合練習</h1>
                <Add count={data.length} />
                <RadioList data={data} />
            </div>
        )
    }
}
    
class Add extends React.Component {
    static propTypes = {
        count : PropTypes.number.isRequired,
    }
    
    handleAdd = _ => {
        const txt = this.txt.value.trim()
        if(!txt) {
            return
        }
        console.log(txt)
        PubSub.publish('xxx', txt);
        this.txt.value = ''
    }
    
    render() {
        return (
            <div>
                <input ref={i => this.txt = i}/> 
                <button onClick={this.handleAdd}>
                    增加#{this.props.count + 1}
                </button>
            </div>
        )
    }
}
    
class RadioList extends React.Component {
    static propTypes = {
        data : PropTypes.array.isRequired
    }
    
    render() {
        const {data} = this.props
        return (
            <ul>
                {
                    data.map((data, i) => {
                        return (
                            <li key={i}>
                                <input type="radio" name="x" />
                                {data}
                            </li>
                        )
                    })
                }
            </ul>
        )
    }
}
    
ReactDOM.render(<App />, document.querySelector("#div1"));
</script>



2018年5月12日 星期六

li、state、props、refs (React 16 二)

※li

li 有個 index 屬性,不寫在 console 會有警告
const array = ["aaa", "bbb", "ccc"];
const arr = [];
array.forEach((data, i) => arr.push(<li key={i}>{data}</li>));
    
ReactDOM.render(arr ,document.querySelector("#div1"));

※此種方式還要再宣告一個陣列,如不想宣告,還可以用如下的方式


const array = ["aaa", "bbb", "ccc"];
ReactDOM.render(
    <ul>
        {
            array.map((data, i) => {
                return <li key={i}>{data}</li>
            })
        }
    </ul>,
    document.querySelector("#div1")
);





※state

setState 為關鍵的方法,不能改
在 this.state 裡宣告,不一定要叫 state
組件內部使用

class Btn extends React.Component {
    constructor(p) {
        super(p)
        console.log(this);
        this.state = {bln:true}
        this.changeText = this.changeText.bind(this)
    }
    
    changeText() {
        this.setState({bln:!this.state.bln})
    }
    
    render() {
        return <button onClick={this.changeText}>{this.state.bln?'XXX':'OOO'}</button>
    }
}
    
ReactDOM.render(<Btn />, document.querySelector("#d1"))

※可看到 this 印出來,有 state、props、refs…等,這些關鍵字是不能改的

※要改變狀態一定要用 setState 方法,不能使用 this.setState.id = !this.state.id,雖然不會報錯,但沒有作用

※render 是覆寫 React.Componet 裡的方法;而 changeText 是自定義的方法,所以自定義的還得在 constructor 加上 bind 才可以使用,也可以寫在 onClick 裡,如 onClick={this.changeText.bind(this)}



※props

ReactDOM.render 的第一個參數傳進來的,可以用 props 取得

class Animal extends React.Component {
    constructor(p) {
        super(p)
    }
    
    render() {
        console.log(this)
        return (
            <ul>
                <li>{this.props.name}</li>
                <li>{this.props.price}</li>
            </ul>
        )
    }
}
    
Animal.defaultProps = { // 給預設值
    name: '動物名',
    price:500
}
    
Animal.propTypes = { // 給型態,如果不是必要,最後就不需要 isRequired
    name:PropTypes.string.isRequired,
    price:PropTypes.number.isRequired
}
    
const animal1 = {
    name:'老虎',
    price:200
}
    
const animal2 = {
    name:'老鼠',
    price:50
}
    
ReactDOM.render(<Animal {...animal1} />, document.querySelector("#d1"))
ReactDOM.render(<Animal name={animal2.name} />, document.querySelector("#d2"))

※想使用 propTypes,必需得有 prop-types.js



※refs

類似以前的 id
在 ref = 宣告


class Reference extends React.Component {
    constructor(p) {
        super(p)
        this.handleBlure = this.handleBlure.bind(this)
        this.handleClick = this.handleClick.bind(this)
    }
    
    handleClick() {
        console.log(this.msgVue.value)
    }
    
    handleBlure(e) {
        alert(e.target.value)
    }
    
    render() {
        return (
            <div>
                <input ref={i => this.msgVue=i} />
                <button onClick={this.handleClick}>按我</button>
                <input placeholder="預設值" onBlur={this.handleBlur} />
            </div>
        )
    }
}
    
ReactDOM.render(<Reference />, document.querySelector("#d1"))

※也可以使 ref="xxx",取值就用 this.refs.xxx.value 即可

2018年5月3日 星期四

Visual Studio Code 設定


※紅框可以設定顯視相關;綠框設定快速鍵



※文字字型大小


左邊是預設值,不能改,只能覆蓋,使用右邊來覆蓋



※快速鍵


由於本人使用 Eclipse 已經習慣了,所以列出幾個常用的快速鍵
Move Line Up:Alt+Up
Move Line Down:Alt+Down
以上兩個內鍵就已經是這樣子了

Copy Line Up:Ctrl+Alt+Up
Copy Line Down:Ctrl+Alt+Down
Delete Line:Ctrl+d
Format Document:Ctrl+Shift+f
Transform to Uppercase:Ctrl+Shift+x
Transform to Lowercase:Ctrl+Shift+y