react 学习

/**
 * @author shj
 * @file react index
 */
import React from 'react';
import ReactDOM from 'react-dom';
// hello world 显示
const name = 'shj';
const element = <h2> react {name}</h2>;

ReactDOM.render(
    element,
    document.getElementById('root')
  );
// 对象引用
class Person {
     constructor(name, age) {
         this.name = name;
         this.age = age;
     }
}
let p1 = new Person('张三', 12);
let ele  = (
    <div>
        <h1> hello ,{p1.name}</h1>
    </div>
);
ReactDOM.render(ele, document.getElementById('root'));
// 调用定时任务 元素渲染只能通过覆盖来实现
let msg = '秒表';
function times() {
    ele = (
      <div>
    <h1>react {msg}</h1>
    <h2> time: {new Date().toLocaleTimeString()}</h2>
    </div>
    );
    ReactDOM.render(ele, document.getElementById('root'));
}
setInterval(times, 1000000);
// 组件与props
/**
 * 当 React 元素为用户自定义组件时,
 * 它会将 JSX 所接收的属性(attributes)转换为单个对象传递给组件,
 * 这个对象被称之为 “props”。
 * 注意: 组件名称必须以大写字母开头。

React 会将以小写字母开头的组件视为原生 DOM 标签。
例如,<div /> 代表 HTML 的 div 标签,而 <Welcome />
则代表一个组件,并且需在作用域内使用 Welcome。
 */
class Welcome extends React.Component {
    render() {
        return <h1>hello ,{this.props.name} </h1>;
    }
}
ele = <Welcome name = "baidu"/>;
ReactDOM.render(ele, document.getElementById('root'));
/**
 * 我们调用 ReactDOM.render() 函数,并传入 <Welcome name="baidu" /> 作为参数。
React 调用 Welcome 组件,并将 {name: 'baidu'} 作为 props 传入。
Welcome 组件将 <h1>Hello, baidu</h1> 元素作为返回值。
React DOM 将 DOM 高效地更新为 <h1>Hello, baidu</h1>。
 */
// 组合组件
class App extends React.Component {
    render() {
        return (
            <div>
                <Welcome name = '张1三'/>
                <Welcome name = '张四'/>
                <Welcome name = '张五'/>
            </div>
        );
    }
}
ReactDOM.render(<App/>, document.getElementById('root'));
// 提取组件 将比较复杂的组件,拆分为多个小组件
function Comment(props) {
    return (
      <div className="Comment">
        <div className="UserInfo">
          <img className="Avatar"
            src={props.author.avatarUrl}
            alt={props.author.name}
          />
          <div className="UserInfo-name">
            {props.author.name}
          </div>
        </div>
        <div className="Comment-text">
          {props.text}
        </div>
        <div className="Comment-date">
          {(props.date)}
        </div>
      </div>
    );
}
class Avatar extends React.Component {
    render() {
        return (
            <span className="Avatar">
                {this.props.user.avatarUrl}{this.props.user.name}
            </span>
        );
    }
}
class UserInfo extends React.Component {
    render() {
        return (
            <div className="UserInfo">
                <Avatar user={this.props.user} />
                <div className="UserInfo-name">
                    {this.props.user.name}
                </div>
    </div>
        );
    }
}
class MyComp extends React.Component {
    render() {
        return (
            <div className="Comment">
                <UserInfo user ={this.props.comp.user}/>
            <div className="Comment-text">
            {this.props.comp.text}
            </div>
            <div className="Comment-date">
            {(this.props.comp.date)}
            </div>
            </div>
        );
    }
}

let comp = {};
let user = {};
user.avatarUrl = 'aaa';
user.name = '无图';
comp.user = user;
comp.text = 'mytext';
comp.date = new Date().toLocaleTimeString();
ReactDOM.render(<MyComp comp ={comp}/>, document.getElementById('root'));
// 所有 React 组件都必须像纯函数一样保护它们的 props 不被更改。

// state
class Clock extends React.Component {
    constructor(props) {
        super(props);
        this.state = {date: new Date()};
    }
    // 组件第一次被渲染时,挂载
    componentDidMount() {
        this.timerID = setInterval(
        () => this.tick(),
        1000
    );
    }
    // 组件被删除时,卸载
    componentWillUnmount() {
        clearInterval(this.timerID);
    }
    tick() {
        this.setState({
            date: new Date()
        });
    }
    render() {
        return (
            <div>
                <h1>Clock</h1>
                <h1> Time : {this.state.date.toLocaleTimeString()}</h1>
            </div>

        );
    }
}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);

/**
 * 构造方法是唯一直接设置state的入口
 * 只能通过setState() 改变state state ='' 并不能改变
 * state除了拥有并设置了它的组件,其他组件都无法访问
 * 这通常会被叫做“自上而下”或是“单向”的数据流。
 * 任何的 state 总是所属于特定的组件,
 * 而且从该 state 派生的任何数据或 UI 只能影响树中“低于”它们的组件
 */

class App1 extends React.Component {
    render() {
        return (
            <div>
            <Clock />
            <Clock />
            <Clock />
          </div>
        );
    }
  }
// 每个 Clock 组件都会单独设置它自己的计时器并且更新它。
ReactDOM.render(
    <App1 />,
    document.getElementById('root')
  );
// 事件处理
class Buttons extends React.Component {
    constructor(props) {
        super(props);
        this.state = {isOn: true};
// 为了在回调中使用 this ,必须绑定
        this.clicks = this.clicks.bind(this);
    }
    clicks() {
        this.setState(prevState => ({isOn: !prevState.isOn
        }));
    }
    render() {
        return (
            <button onClick={this.clicks}>
            {this.state.isOn ? 'ON' : 'OFF'}
        </button>
        );
    }
}
ReactDOM.render(
    <Buttons />,
    document.getElementById('root')
  );
  // <button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>

  // 条件渲染
class Comp1 extends React.Component {
    render() {
        return (
            <h1> comp1 </h1>
        );
    }
}
class Comp2 extends React.Component {
    render() {
        return (
            <h1> comp2 </h1>
        );
    }
}

class Show extends React.Component {
    render() {
        if (this.props.flag) {
            return <Comp1/>;
        }
        else {
            return <Comp2/>;
        }
    }
}
ReactDOM.render(
    <Show flag ={false}/>,
    document.getElementById('root')
);
// 元素变量
class Login extends React.Component {
    render() {
        return (
            <button onClick={this.props.onClick}>
                LOgin
            </button>
        );
    }
}
class Logout extends React.Component {
    render() {
        return (
            <button onClick={this.props.onClick}>
                Logout
            </button>
        );
    }
}
class LogController extends React.Component {
    constructor(props) {
        super(props);
        this.loginClock = this.loginClock.bind(this);
        this.logoutClock = this.logoutClock.bind(this);
        this.state = {flag: false};
    }
    loginClock() {
        this.setState({flag: true});
    }
    logoutClock() {
        this.setState({flag: false});
    }
    render() {
        const flag = this.state.flag;
        // let button;
        // if (flag) {
        //     button = <Login onClick ={this.logoutClock}/>;
        // }
        // else {
        //     button = <Logout onClick ={this.loginClock}/>;
        // }
        // return (
        //     <div>
        //         <Show flag ={flag}/>
        //         {button}
        //     </div>
        // );
        // 使用三目运算符
        return (
            <div>
                {flag ? (
                <Login onClick ={this.logoutClock}/>
                ) : (
                <Logout onClick ={this.loginClock}/>)
                }
            </div>
        );
    }
}
ReactDOM.render(
    <LogController/>,
    document.getElementById('root')
);
/**
 * 在 JavaScript 中,true && expression 总是会返回 expression, 而 false && expression 总是会返回 false。
    因此,如果条件是 true,&& 右侧的元素就会被渲染,如果是 false,React 会忽略并跳过它。
 * 在极少数情况下,你可能希望能隐藏组件,即使它已经被其他组件渲染。
 * 若要完成此操作,你可以让 render 方法直接返回 null,而不进行任何渲染。
 */

 // 列表
const arr = [7, 2, 3, 4, 5];
let arrItem = arr.map(number => <li >{number}</li>);
ReactDOM.render(
    <ul>{arrItem}</ul>,
    document.getElementById('root')
);
// key
class Numbers extends React.Component {
    constructor(props) {
        super(props);
        this.state = {item: props.items};
    }
    render() {
        let arrItem = this.state.item.map(number => <li key = {number.toString()}>{number}</li>);
        return (
            <ul >{arrItem}</ul>
        );
    }
}
ReactDOM.render(
    <Numbers items={arrItem}></Numbers>,
    document.getElementById('root')
);
/**
 * key 帮助 React 识别哪些元素改变了,比如被添加或删除。因此你应当给数组中的每一个元素赋予一个确定的标识
 * 一个元素的 key 最好是这个元素在列表中拥有的一个独一无二的字符串。通常,我们使用来自数据 id 来作为元素的 key
 * 当元素没有确定 id 的时候,万不得已你可以使用元素索引 index 作为 key
 * 元素的 key 只有放在就近的数组上下文中才有意义。
 * 一个好的经验法则是:在 map() 方法中的元素需要设置 key 属性。
 * 数组元素中使用的 key 在其兄弟节点之间应该是独一无二的。然而,它们不需要是全局唯一的
 */
// key 会传递信息给 React ,但不会传递给你的组件
/**
 * <Post
    key={post.id}
    id={post.id}
    title={post.title} />
    Post 组件可以读出 props.id,但是不能读出 props.key。
 */
// 在jsx 中使用 map()
class Number1 extends React.Component {
    render() {
        return (
            <ul>{this.props.items.map(number => <li key = {number.toString()}>{number}</li>)}</ul>
        );
    }
}
ReactDOM.render(
    <Number1 items={arrItem}/>,
    document.getElementById('root')
);
// 受控组件
/**
 * 在 HTML 中,表单元素(如<input>、 <textarea> 和 <select>)之类的表单元素通常自己维护 state,
 * 并根据用户输入进行更新。
 * 而在 React 中,可变状态(mutable state)通常保存在组件的 state 属性中,
 * 并且只能通过使用 setState()来更新。
 * 我们可以把两者结合起来,使 React 的 state 成为“唯一数据源”。
 * 渲染表单的 React 组件还控制着用户输入过程中表单发生的操作。
 * 被 React 以这种方式控制取值的表单输入元素就叫做“受控组件”。
 */
class FormComp extends React.Component {
    constructor(props) {
        super(props);
        // select的value在state中,控制默认选中的
        this.state = {value: 'apple'};
        this.handleChange = this.handleChange .bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }
    handleChange(event) {
        this.setState({value: event.target.value});
    }
    handleSubmit(event) {
        alert(this.state.value);
        event.preventDefault();
    }
    render() {
        return (
            <form onSubmit= {this.handleSubmit}>
                  <label>
                 Name:
                <input type= 'text' value= {this.state.value} onChange ={this.handleChange} />
                </label>
               <div>
                   水果:
                   <select value={this.state.value} onChange={this.handleChange} >
                      <option value='orange' >橘子</option>
                       <option value='apple' >苹果</option>
                       <option value='pear' >梨</option>
                       <option value='mango' >芒果</option>
                   </select>
                </div>
                <div>
                   水果2:
                   <select multiple={true} value={['apple', 'pear']}>
                      <option value='orange' >橘子</option>
                       <option value='apple' >苹果</option>
                       <option value='pear' >梨</option>
                       <option value='mango' >芒果</option>
                   </select>
                </div>
                <label>
                 描述:
                <textarea type= 'text' value= {this.state.value} onChange ={this.handleChange} />
                </label>
                <input type ='submit' value= '提交'/>;
            </form>
        );
    }
}
ReactDOM.render(
    <FormComp />,
    document.getElementById('root')
);
// 处理多个输入
class Inputs extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            value1: true,
            value2: 'value2'
        };
        this.handlechange = this.handlechange.bind(this);
    }
    handlechange(event) {
        const target = event.target;
        const name = target.name;
        const value = target.type === 'checkbox' ? target.checked : target.value;
        this.setState({
            [name]: value
        });
    }
    render() {
        return (
            <form>
                <input type='checkbox' name= 'value1' chedked ={this.state.value1} onChange ={this.handlechange}/>
                <input type ='text' name = 'value2' value={this.state.value2} onChange ={this.handlechange}></input>
            </form>
        );
    }
}
ReactDOM.render(
    <Inputs />,
    document.getElementById('root')
);
// 状态提升
function changeFtoC(f) {
    return (f - 32) * 5 / 9;
}
function changeCtoF(c) {
    return (c * 9 / 5) + 32;
}
function changeTemp(temp, cover) {
    const input = parseFloat(temp);
    if (Number.isNaN(input)) {
        return '';
    }
    const result = cover(input);
    const round = Math.round(result * 1000) / 1000;
    return round.toString();
}
const tenpType = {
    c: '摄氏',
    f: '华氏'
};

class TempF extends React.Component {
    constructor(props) {
        super(props);
        this.handleChange = this.handleChange.bind(this);
    }
    handleChange(e) {
        this.props.tempChange(e.target.value);
        // this.setState({temp: e.target.value});
    }
    render() {
        const temp = this.props.temp;
        const scale = this.props.scale;
        return (
            <fieldset>
                <legend>输入{tenpType[scale]} 温度:</legend>
                <input type ='text' value = {temp} onChange = {this.handleChange}/>
            </fieldset>
        );
    }
}
class Boilling extends React.Component {
    render() {
        if (this.props.cTemp > 100) {
            return <p> 开水</p>;
        }
        return <p>没有开水</p>;
    }
}
class Temp extends React.Component {
    constructor(props) {
        super(props);
        this.state = {temp: '', scale: 'c'};
        this.changeC = this.changeC.bind(this);
        this.changeF = this.changeF.bind(this);
    }
    changeC(temp) {
        this.setState({scale: 'c', temp});
    }
    changeF(temp) {
        this.setState({scale: 'f', temp});
    }
    render() {
        const temp = this.state.temp;
        const scale = this.state.scale;
        const cel = scale === 'f' ? changeTemp(temp, changeFtoC) : temp;
        const fah = scale === 'c' ? changeTemp(temp, changeCtoF) : temp;

        return (
            <div>
                <TempF
                scale='c'
                temp ={cel}
                tempChange ={this.changeC} />

                <TempF
                scale='f'
                temp ={fah}
                tempChange ={this.changeF} />

                <Boilling
                cTemp ={parseFloat(cel)}/>
            </div>
        );
    }
}

ReactDOM.render(
    <Temp />,
    document.getElementById('root')
);

// 组合
/**
 * <FancyBorder> JSX 标签中的所有内容都会作为一个 children prop 传递给 FancyBorder 组件。
 * 因为 FancyBorder 将 {props.children} 渲染在一个 <div> 中,被传递的这些子组件最终都会出现在输出结果中。
 每个组件都可以获取到 props.children。它包含组件的开始标签和结束标签之间的内容
 */

// 需要引入css
class FancyBorder extends React.Component {
    render() {
        return (
            <div className={'FancyBorder FancyBorder-' + this.props.color}>
            {this.props.children}
             </div>
        );
    }
}

class Welcome2 extends React.Component {
    render() {
        return (
        <FancyBorder color ='red'>
            <h1 className = 'Dialog-title'>Welcome</h1>
            <p className ='Dialog-mssage'> Thankn you</p>
        </FancyBorder>
        );
    }
}

ReactDOM.render(
    <Welcome2 />,
    document.getElementById('root')
);

function Contacts() {
    return <div className="Contacts" />;
}

function Chat() {
    return <div className="Chat" />;
}

class SplitComp extends React.Component {
    render() {
        return (
            <div className = 'SplitComp'>
                <div className = 'SplitComp-left'>
                    {this.props.left}
                </div>
                <div className ='SplitComp-right'>
                    {this.props.right}
                </div>
            </div>
        );
    }
}

class SHowSplit extends React.Component {
    render() {
        return (
            <SplitComp
            left= {
                <Chat />
            }
            right= {
                <Contacts />
            } />
        );
    }
}
ReactDOM.render(
    <SHowSplit />,
    document.getElementById('root')
);

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hero_孙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值