Day58 (React)

1.useContext 之演进

可接元件并分享资料
只有function元件可使用,class元件不能使用

(1)function阶层继承 缺点:中间改变就断掉了
(Lab_useContext > index_0.html)

      function Me(props) {
        return <h3>{props.secret}</h3>; // 3.在使用Father的方法取得资料
      }

      function Father(props) {
        return <Me secret={props.secret} />; // 2.把GrandFather的secret给Me  //4.回传给GrandFather
        // return (
        //   <h3>{props.secret}</h3>
        // )
      }

      function GrandFather(props) {
        let [secret, setSecret] = React.useState("work harder or work smarter"); // 1.secret设定为字串 setSecret=方法  //5.变更後显示
        return (
          <React.Fragment>
            <Father secret={secret} />
          </React.Fragment>
        );
      }

(2)虽然Father不用收,但还是很麻烦==
(Lab_useContext > index_1.html)

      function Me(props) {
        // 3.Provider搭配Consumer并使用=>接资料
        return (
          <heirloom.Consumer>
            {
              secret =>
                <h3>{secret}</h3>
            }
            
          </heirloom.Consumer>
        );
      }

      function Father(props) {
        return <Me />             // 2.回传Me,不用接GrandFather
        // return (
        //   <h3>{props.secret}</h3>
        // )
      }

      function GrandFather(props) {
        let [secret, setSecret] = React.useState("work harder or work smarter");
        return (
          // 1.GrandFather把传家宝跟<Father />绑在一起,所以Father不用接
          <React.Fragment>
          <heirloom.Provider value={secret}>  
            <Father />
          </heirloom.Provider>
          </React.Fragment>
        );
      }

(3)使用 useContext取得资料,createContext限制只有哪些元件可取得
(Lab_useContext > index_2.html)

      // useContext取得资料,createContext限制只有哪些元件可取得
      // 1. React.createContext()只有在这个范围内的元件,才能使用
      var heirloom = React.createContext();

      function Me(props) {
        let secret = React.useContext(heirloom); // 4.useContext可以取得资料
        return <h3>{secret}</h3>;
      }

      function Father(props) {
        // 3.Father包含<Me />
        return <Me />;
        // return (
        //   <h3>{props.secret}</h3>
        // )
      }

      function GrandFather(props) {

        //回传阵列 ; useState设定secret=字串,setSecret=ƒ()
        let [secret, setSecret] = React.useState("work harder or work smarter"); 

        let heirloomState = { secret, setSecret };
        console.log(heirloomState);
        return (
          // 2.设定范围 GrandFather包含<Father />
          <React.Fragment>
            <heirloom.Provider value={secret}>
              <Father />
            </heirloom.Provider>
          </React.Fragment>
        );
      }

(4)最终版本:设定好可以使用的元件范围,及可以使用的物件

      // 1. React.createContext()只有在这个范围内的元件,才能使用
      var heirloom = React.createContext();

      // 3.使用useContext就可取出传家宝,取得secret, setSecret
      function Me(props) {
        let { secret, setSecret } = React.useContext(heirloom);
        // 4.事件处理程序 拿secret, setSecret来用
        let doTest = () => {
          setSecret("Work smarter"); //把setSecret方法的仓库拿来,使用
          document.title = Date();
        };
        // 4.事件处理程序 拿secret, setSecret来用
        return (
          //把secret字串的仓库拿来,使用
          <div>
            <h3>{secret}</h3>
            <button onClick={doTest}>test</button>
          </div>
        );
      }

      function Father(props) {
        // 3. Father包含<Me />
        return <Me />;
        // return (
        //   <h3>{props.secret}</h3>
        // )
      }

      function GrandFather(props) {
        // 回传阵列 ; useState设定secret=字串,setSecret=ƒ()改变资料的方法
        let [secret, setSecret] = React.useState("work harder or work smarter");
        // heirloomState 建立成一个物件,让Provider(传家宝)的值={}
        let heirloomState = { secret, setSecret };

        return (
          // 2. 设定范围 GrandFather包含<Father /> 并设定传家宝Provider
          // heirloomState = { secret, setSecret }; 物件
          <React.Fragment>
            <heirloom.Provider value={heirloomState}>
              <Father />
            </heirloom.Provider>
          </React.Fragment>
        );
      }

2.物件{}收物件{},[]收[]

        //useState回传[],[]收下
        let [secret, setSecret] = React.useState("work harder or work smarter");

        //heirloomState是物件{} 
        let heirloomState = { secret, setSecret }; 

          <React.Fragment>
            <heirloom.Provider value={heirloomState}>  //{}收下
              <Father />
            </heirloom.Provider>
          </React.Fragment>

3.useMemo 改变该变数才跑此程序,为了节省效能,useMemo会记住该变数的原始值

(Lab_useMemo > index_OK.html)

      // 3.跑程序
      function App(props) {

        var [data1, setData1] = React.useState(1); //useState回传[],只能用[]装
        var [data2, setData2] = React.useState(1);

        var workResult = React.useMemo(() => {
          //useMemo会记忆原本data1是甚麽
          //此处只用data1
          return longTimeWork(data1); //参数
        }, [data1]); //资料 ; 4.判断:当[data1]改变我才跑这个 return longTimeWork(data1) function,如果[data1]没有改变就不会跑

        let changeData1 = () => {
          // 1.按按钮 data1 +1
          setData1(data1 + 1);
        };

        //按第二个按钮不会执行workResult 节省效能
        let changeData2 = () => {
          setData2(data2 + 1);
        }; C:\temp

        // 2.执行return
        return (
          <React.Fragment>
            <h3>
              workResult: {workResult}, data1: {data1}, data2: {data2}
            </h3>
            <button class="btn btn-outline-success" onClick={changeData1}>
              change data1
            </button>
            <button class="btn btn-outline-primary" onClick={changeData2}>
              change data2
            </button>
          </React.Fragment>
        );

4.介绍React + Node.js整体重跑一遍

(1)
Simple React Snippets 套件安装 => 元件产生器
Snippets 简写
https://marketplace.visualstudio.com/items?itemName=burkeholland.simple-react-snippets

(2)Lab_counters > counter-app

create-react-app counter-app
建立资料夹counter-app

npm install [email protected]
counter-app资料夹内安装[email protected]

npm start
跑package.json "start": "react-scripts start",
http://localhost:3000/

(3)Lab_counters > src > index.js

import App from './App'; //引用有物件的.js 需from
import 'bootstrap/dist/css/bootstrap.min.css'; //引用单纯没有物件的.js或.css 无须from

(4)Lab_counters > src > components > counter.jsx
imrc 快速建立引用
cc 快速建立类别
按tab跳行

     import React, { Component } from 'react';
     class Counter extends Component {
         state = {  }
         render() { 
             return ( <h1>hello</h1> );
         }
     }
 
     export default Counter;

(5)Lab_counters > src > index.js
改引用components/counter.jsx

import Counter from './components/counter.jsx';

     ReactDOM.render(
       // 测试看看有没有引用到BS
       <React.StrictMode>
         <Counter />
         <button className="btn btn-outline-success">OK</button>
       </React.StrictMode>,
       document.getElementById('root')
     );

此时会显示hello http://localhost:3000/

(6)Lab_counters > src > components > counter.jsx
使用方法formatCount()

    formatCount(){
        // 方法1.
        // return this.state.count === 0? "Zero" : this.state.count ; 
        // 方法2. this.state做成物件
        var {count} = this.state;
        return count === 0? "Zero" : count ;
    }
    render() { 
        return ( 
        <div>
            <span>{this.formatCount()}</span><hr />
            <button className="btn btn-outline-success">增加</button>
        </div> 
        );
    }

(7)增加图片、样式

    state = {  
        count:0,
        imgUrl: "https://dummyimage.com/200x200/000/fff"
    }

    //制作样式物件 大写必要font"W"eight(CSS内样式)
    styles = {
        fontWeight:"bold",
        fontSize:"3em",
        fontStyle:"italic"
    };

    render() { 
        return ( 
        <div> 
            //图片
            <img src= {this.state.imgUrl} /><hr />
            //新增样式
            <span style={this.styles} className="badge badge-primary m-2">{this.formatCount()}</span><hr /> 
        </div> 
        );
    }

(8)制作判别式 并 设定套用不同样式

    styles = {
        fontWeight:"bold",
        fontSize:"3em",
        fontStyle:"italic"
    };

    formatCount(){
        // 方法1.
        // return this.state.count === 0? "Zero" : this.state.count ; 
        // 方法2. this.state做成物件
        var {count} = this.state;
        return count === 0? "Zero" : count ;
    }

    //数值0=会变成黄色
    getBadgeClasses() {
        let myClassName = "badge m-2 ";
        myClassName += (this.state.count === 0) ? "badge-warning" : "badge-primary";
        return myClassName;
    }

    render() { 
        return ( 
        <div>
           

            {/* 设定蓝色 */}
            <span style={this.styles} className="badge badge-primary m-2">{this.formatCount()}</span><hr />

            {/* render内,设定红色 */}
            <span style={this.styles} className={myClassName}>{this.formatCount()}</span><hr />

            {/* getBadgeClasses(),设定黄色 */}
            {/* styles +  getBadgeClasses + formatCount 样式在遇到0的时候会变成黄色 */}
            <span style={this.styles} className={this.getBadgeClasses()}>{this.formatCount()}</span><hr />

        </div> 
        );
    }

(9)制作tage项目[]

    class Counter extends Component {
    state = {  
        imgUrl: "https://dummyimage.com/200x200/000/fff",  //制作图片物件
        count:0,
        tage : ["tage1","tage2","tage3"]
    }

    render() { 
        return ( 
            <ul>
                {/* tage有几个就跑几个 */}
                {/* index.js:1 Warning: Each child in a list should have a unique "key" prop. */}
                {/* 警告:要给tage唯一的key 所以帮li增加key */}
                {this.state.tage.map(x=> <li key={x}>000</li>)}
                {this.state.tage.map(x=> <li key={x}>{x}</li>)}
            </ul>
        </div> 
        );
    }

(10)把tage项目制作成function方法显示

    class Counter extends Component {
    state = {  
        imgUrl: "https://dummyimage.com/200x200/000/fff",  //制作图片物件
        count:0,
        tage : ["tage1","tage2","tage3"]
    }


    renderTags(){
        if(this.state.tage.length > 0 ){
            return <h3>我有东西唷!!请尝试改变我~</h3>
        }
        return(
            <ul>
                {this.state.tage.map(x=> <li key={x}>{x}</li>)}
            </ul>
        );
    }


        render() { 
          return ( 
           <div>
             <ul>
                {/* &&判断方式,前面true才会判断後面,并显示後面 */}
                {/* 实验:把tage : ["tage1","tage2","tage3"]清空 */}
                {this.state.tage.length == 0 && "请建立一个清单"} <br />
                {this.renderTags()}
             </ul>
           </div> 
          );
        }


5.方便小工具,剪贴簿WatchClipboard.exe

复制过的东西会贴在上面
截图会被放到 C:\temp

https://ithelp.ithome.com.tw/upload/images/20210830/20137684SlKIFo9VTG.png


6.能否使用JQ在react?

可以,npm i jquery 要安装

import 'jquery/dist/jquery';

<<:  RISC-V on Rust 从零开始(10) - 实作ELF loader

>>:  开赛前~怎麽会想不开来报名

中阶魔法 - 闭包 Closure (一)

前情提要 「艾草艾草,你在做什麽?」 艾草:「没特别做什麽呀!」 「艾草艾草,我问你喔!」 艾草:「...

Day 6 情报收集 - Information Gathering (Live Host Identification)

来到第六天Live host identificaction的环节,主轴在於活的主机,也就是在开机状...

Day 26-如何测试 terraform 之一:长 code 短 code,能过测试的 code 才是好 code

本篇翻译与讲解 terraform 官方 blog 对於 test terraform 的建议 课程...

第二十九日-MYSQL预存程序 STORED PROCEDURE:来写一个BMI小程序(2)

昨天已经认识分隔符号 DELIMITER和STORED PROCEDURE建立语法, 建立出BMI小...

Day7-Go回圈

前言 回圈基本上是每个程序语言必备的函式,藉以回圈来达成反覆或是循环的动作。而 Go 语言的回圈种类...