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 bootstrap@4.1.1
counter-app资料夹内安装bootstrap@4.1.1
npm start
跑package.json "start": "react-scripts start",
http://localhost:3000/
(3)Lab_counters > src > index.js
import App from './App'; //引用有物件的.js 需fromimport '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
6.能否使用JQ在react?
可以,npm i jquery 要安装
import 'jquery/dist/jquery';