元件的設計原理

2020-09-30 17:00:01

1 案例結構

在這裡插入圖片描述

程式碼

app.js

//元件形式 function 函數形式 class類
// 01 react事件

import React, { Component } from 'react';
// 匯入react和react元件
// import ChildA from './components/ChildA'
// import ChildB from './components/ChilB'
// import Life from './components/Life'
import Todo from './pages/todo/index'
//定義一個App元件 繼承Component
class App extends Component {
  //建構函式
  constructor(props) {
    super(props);
    //呼叫父元件
    this.state = { num: 1 }
    //定義一個狀態 (data資料)
  }

 
  //渲染節點
  render() {
    return (
      <div >
       
          <Todo></Todo>


      </div>
    );
  }
}


export default App;

index.js

import React, { Component } from 'react'
import List from './List';
import Input from './Input'
class Todo extends Component {
    constructor(props) {
        super(props);
        this.state = { 
            list:[
                {done:false,title:"學習react",status:0},
                {done:true,title:"學習vue",status:0},
                {done:false,title:"小程式",status:0}
            ]
        }
        
    }
    // 新增item
    addItem = e=>{
        var list = this.state.list; //獲取到原list
        list.unshift({title:e.title,done:false,status:0}) //把新資料新增到list
        this.setState({list}) //更新list

    }
    // 刪除item
    delItem = item=>{
        var list = this.state.list;
        var ind = list.indexOf(item);
        list.splice(ind,1);
        this.setState({list})
    }
    // item被改變
    itemChange = (item,data)=>{
        var list = this.state.list; //獲取原來的list
        var ind = list.indexOf(item); //獲取是第幾個
        list[ind]={...item,...data} //用data 去覆蓋item的屬性
        this.setState({list}) //更新list
    }
    render() { 
        let listUndo = this.state.list.filter(item=>!item.done); //未完成
        let listDone = this.state.list.filter(item=>item.done); //已經完成
        return ( 
        <div>
            <h1>TodoList</h1>
            <Input  addItem={this.addItem}></Input>
            {/* addItem方法通過props addItem傳入給Input */}
            <h3>未完成({listUndo.length})</h3>
            <List 
            list={listUndo}
            delItem={this.delItem}
            itemChange={this.itemChange}
            ></List>

            <h3>已經完成({ listDone.length})</h3>
            <List 
            list={listDone}
            delItem={this.delItem}
            itemChange={this.itemChange}
            ></List>
        </div> );
    }
}
 
export default Todo;

List.js

import React from 'react'
import Item from './Item.js'
function List({list,delItem,itemChange}){
    return (
    <div className="list">
        {
            list.map(
                item=>{
                    return (
                        <Item 
                        key={item.title} 
                        item={item} 
                        delItem={delItem} 
                        itemChange={itemChange}>        
                        </Item>
                )}
            )
            // 把list通過map對映為有Item元件的陣列 並傳入item資料給Item元件
        }
       
    </div>)
}
export default List;

Item.js

import React, { Component } from 'react'
class Item extends Component {
    constructor(props) {
        super(props);
        this.state = {  }
    }
    render() { 
        let {item,delItem,itemChange} = this.props
        // 簡寫props.item
        return ( 
        <div>
            <span>
                <input type="checkbox" checked={item.done} onChange={e=>itemChange(item,{done:e.target.checked})}/>
                <span>{item.title}</span>
                <button onClick={()=>{delItem(item)}}>×</button>
            </span>
        </div> );
    }
}
 
export default Item;

Input.js

import React  from 'react';
function Input({addItem}){
    let inp = null; //定義inp  通過ref函數獲取到 input節點
    return (<div>
        <input 
        type="text" 
        placeholder="新增內容"
        ref={elem=>inp=elem}
        onKeyUp={e=>{
            if(e.keyCode!==13){return}
            addItem({title:inp.value,status:0})
            inp.value = "";
        }}
        />
        <button onClick={()=>{
            // 當單擊新增按鈕是 執行props 的addItem方法
            addItem({title:inp.value,status:0});
            inp.value = "";
        }}>新增</button>
    </div>)
}
export default Input;