import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import './App.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
//定义 元素
const ele = <h1 className="tes" >hello world</h1>; //style = {{textAlign:"center"}}
const el = React.createElement(
'h1',
{className:'tes'},
'hello red'
)
ReactDOM.render(ele,
document.getElementById('root')
);
//update dom
//props: 传入function的任意参数
// function Clock(prop){
// return (
// <div>
// <h1>hello</h1>
// <h2>now:{prop.date.toLocaleTimeString()}</h2>
// </div>
// )
// }
//es6 语法 推荐 定义组件必须 以大写名字开头
class Clock extends React.Component{
render(){
return(
<div>hello</div>,
<h2>now: {this.props.date.toLocaleTimeString()}</h2>
);
}
}
//使用组件
// function tick(){
// ReactDOM.render(
// <Clock date={new Date()}/>,
// document.getElementById('interval')
// )
// }
// setInterval(tick,3000);
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
//多次使用
class Ticks extends React.Component{
render(){
return (
<div> /*没有div框起来 默认只显示一个组件, 不知道为什么*/
<Welcome name="ssssssssssssssssssssssssssssssssssssssssss"></Welcome>,
<Clock date={new Date()}/>
</div>
// "aa" 不放在div里 只显示aa
);
}
}
/*数组实现 使用{} 来在html元素等中解析变量 等*/
// const array = [
// <Ticks/>,
// <Welcome name="arrays"/>
// ]
// ReactDOM.render(
// <div>{array}</div>,
// document.getElementById('interval')
// );
//官网实例
// class Apps extends React.Component{
// render(){return (
// <div>
// <Welcome name="Sara" />
// <Welcome name="Cahal" />
// <Welcome name="Edite" />
// </div>
// );
// }}
// ReactDOM.render(
// <Apps />,
// document.getElementById('interval')
// );
//纯函数:
//无论是使用函数或是类来声明一个组件,它决不能修改它自己的props。来看这个sum函数:
function sum(a, b) {
return a + b;
}
// 类似于上面的这种函数称为“纯函数”,它没有改变它自己的输入值,当传入的值相同时,总是会返回相同的结果。
// 与之相对的是非纯函数,它会改变它自身的输入值:
// React是非常灵活的,但它也有一个严格的规则:
// 所有的React组件必须像纯函数那样使用它们的props。
function withdraw(account, amount) {
account.total -= amount;
}
/**
* //笔记三: 生命周期和state(和java 类似, 面向对象) 和constructor, 数据自上而下流动, 可以将属性传递给字组件
* 这通常被称为自顶向下或单向数据流。 任何状态始终由某些特定组件所有,并且从该状态导出的任何数据或 UI 只能影响树中下方的组件。
*/
class Clock1 extends React.Component {
/*constructor*/
constructor(props){
super(props);
// this.state = {date: new Date()};
this.state = {
date:new Date(),
comments:[]
}
}
//componentDidMount() 组件装载调用方法
// componentDidMount() {
// this.timerID = setInterval(
// () => this.tick(),
// 1000
// );
// }
componentDidMount() {
// fetchDate().then(response => {
// this.setState({
// date:response.date,
// })
// })
// response
// fetchDate 应该是定义在外面 和tick同级的方法, then方法是
// es6的方法 2个参数,分别为成功和失败调用funtion
// p.then(onFulfilled, onRejected);
// p.then(function(value) {
// // fulfillment
// }, function(reason) {
// // rejection
// });
// fetchComments().then(response => {
// this.setState({
// comments:response.comments,
// })
// })
this.timeId = setInterval(
() => this.tick(),
1000
// /**中函数不指定参数的类型,不检查实参的类型,不检查形参的个数
// 这里是将tick 绑定位interval的 java的lamader表达式 */
);
}
//componentWillUnmount() 卸载方法
componentWillUnmount() {
clearInterval(this.timeId)
};
tick() {
console.log(this.state.comments);
console.log('555');
this.setState({
date: new Date()
});
}
/**
*
*/
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
ReactDOM.render(
<Clock1/>,
document.getElementById('note3')
);
//note4: react 事件
// 4.1 阻止默认事件
// 传统html 返回false;
// react中 : 通过e.preventDefault(); 来组织默认事件
class LogginButton extends React.Component{
constructor(props){
super(props);
this.state={isToggleOn:true};
// This binding is necessary to make `this` work in the callback
// 这个绑定是必须的, 使在这个回调函数中 工作. 在此处传参, 或者看官网实例使用onClick={this.preventPop.bind(this,this.state.name),即function的prototype属性
this.handleClick = this.handleClick.bind(this,6); //也可以使用箭头函数 自动绑定在这个组件上
}
// handleClick = ()=>{
// //this.setState应该是一个内置的方法, 所有的属性都放在state中,
// this.setState(
// prevState =>({
// isToggleOn:!prevState.isToggleOn
// //handleClick:null,
// })
// )
// }
handleClick(name,e){
console.log(name);
console.log(typeof(e));
//this.setState应该是一个内置的方法, 所有的属性都放在state中,
this.setState(
prevState =>({
isToggleOn:!prevState.isToggleOn
//handleClick:null,
})
)
}
render(){
return(
<button onClick={this.handleClick}>{this.state.isToggleOn ? 'on' : 'off'}默认取消</button>
// <button onClick={(e) => {
// console.log("click");
// e.preventDefault();
// }}>默认取消</button>
)
}
}
class LogginButton2 extends React.Component{
render(){
return(
<a href="#" onClick={(e) => {
console.log("click");
e.preventDefault();//原来的默认点击事件会被取消,不会跳到指定网址
}}>默认取消</a>
)
}
}
ReactDOM.render(
<LogginButton/>,
document.getElementById("event")
)
//伍: es6中新加入了箭头函数=>,箭头函数除了方便之外还有而一个特征就是将函数的this绑定到其定义时所在的上下文。这个特征也可以帮助我们解决这个问题
function Mailbox(props) {
const unreadMessages = props.unreadMessages;
return (
<div>
<h1>Hello!</h1>
{unreadMessages.length > 0 && //如果unreadMessages.length > 0 位false,那么&&后面不渲染,如果为真,则渲染, 注意:&&也可以连接字符串,不只是expression
<h2>
You have {unreadMessages.length} unread messages.
</h2>
}
</div>
);
}
const messages = ['React', 'Re: React', 'Re:Re: React'];
// ReactDOM.render(
// <Mailbox unreadMessages={messages} />,
// document.getElementById('root')
// );
//陆 数组转换 和key
// Map()函数转换:
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((number) => number * 2);
// const doubled = numbers.map((number) => <li key={number}>numberM<li>; 输出一个<li>标签1-5 key用法,
//ReactDOM.render(
// <ul>{listItems}</ul>, 也可以直接渲染
// document.getElementById('root')
// );
console.log(doubled);
//代码打印出[2, 4, 6, 8, 10]
// keyKeys可以在DOM中的某些元素被增加或删除的时候帮助React识别哪些元素发生了变化。因此你应当给数组中的每一个元素赋予一个确定的标识。
// key 必须在同级之间 唯一,不需要全局唯一 JSX允许在大括号中嵌入任何表达式
function ListItem(props) {
// 对啦!这里不需要指定key:
return <li>{props.value}</li>;
}
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
// 又对啦!key应该在数组的上下文中被指定
<ListItem key={number.toString()}
value={number} />
);
return (
<ul>
{listItems}
</ul>
);
}
// const numbers = [1, 2, 3, 4, 5];
// ReactDOM.render(
// <NumberList numbers={numbers} />,
// document.getElementById('root')
// );
//
function Blog(props) {
const sidebar = (
<ul>
{props.posts.map((post) =>
<li key={post.id}>
{post.title}
</li>
)}
</ul>
);
const content = props.posts.map((post) =>
<div key={post.id}>
<h3>{post.title}</h3>
<p>{post.content}</p>
</div>
);
return (
<div>
{sidebar}
<hr />
{content}
</div>
);
}
const posts = [
{id: 1, title: 'Hello World', content: 'Welcome to learning React!'},
{id: 2, title: 'Installation', content: 'You can install React from npm.'}
];
// ReactDOM.render(
// <Blog posts={posts} />,
// document.getElementById('root')
// );
// 嵌套
// function ListItem(props) {
// return <li>{props.value}</li>;
// }
// function NumberList(props) {
// const numbers = props.numbers;
// return (
// <ul>
// {numbers.map((number) =>
// <ListItem key={number.toString()}
// value={number} />
// )}
// </ul>
// );
// }
// const numbers = [1, 2, 3, 4, 5];
// ReactDOM.render(
// <NumberList numbers={numbers} />,
// document.getElementById('root')
// );
// 多个输入, 组件有什么事件, 都在组件内定义好
class Reservation extends React.Component {
constructor(props) {
super(props);
this.state = {
isGoing: true,
numberOfGuests: 2
};
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
render() {
return (
<form>
<label>
Is going:
<input
name="isGoing"
type="checkbox"
checked={this.state.isGoing}
onChange={this.handleInputChange} />
</label>
<br />
<label>
Number of guests:
<input
name="numberOfGuests"
type="number"
value={this.state.numberOfGuests}
onChange={this.handleInputChange} />
</label>
</form>
);
}
}
//柒 react 多个组件共享state 经常会遇到几个组件需要共用状态数据的情况。这种情况下,我们最好将这部分共享的状态提升至他们最近的父组件当中进行管理。
const scaleNames = {
c: 'Celsius',
f: 'Fahrenheit'
};
function toCelsius(fahrenheit) {
return (fahrenheit - 32) * 5 / 9;
}
function toFahrenheit(celsius) {
return (celsius * 9 / 5) + 32;
}
function tryConvert(temperature, convert) {
const input = parseFloat(temperature);
if (Number.isNaN(input)) {
return '';
}
const output = convert(input);
const rounded = Math.round(output * 1000) / 1000;
return rounded.toString();
}
function BoilingVerdict(props) {
if (props.celsius >= 100) {
return <p>The water would boil.</p>;
}
return <p>The water would not boil.</p>;
}
class TemperatureInput extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
this.props.onTemperatureChange(e.target.value); //通过此处 将2个函数通信, 先调用这个函数,然后传入 handleFahrenheitChange函数并携带e.target.value.参数, 其他语言是赋值, 但是react这个好像2个函数等价了
}
render() {
const temperature = this.props.temperature;
const scale = this.props.scale;
return (
<fieldset>
<legend>Enter temperature in {scaleNames[scale]}:</legend>
<input value={temperature}
onChange={this.handleChange} />
</fieldset>
);
}
}
//第二个组件
class Calculator extends React.Component {
constructor(props) {
super(props);
this.handleCelsiusChange = this.handleCelsiusChange.bind(this);
this.handleFahrenheitChange = this.handleFahrenheitChange.bind(this);
this.state = {temperature: '', scale: 'c'};
}
handleCelsiusChange(temperature) {
this.setState({scale: 'c', temperature});
}
handleFahrenheitChange(temperature) {
this.setState({scale: 'f', temperature});
}
render() {
const scale = this.state.scale;
const temperature = this.state.temperature;
const celsius = scale === 'f' ? tryConvert(temperature, toCelsius) : temperature;
const fahrenheit = scale === 'c' ? tryConvert(temperature, toFahrenheit) : temperature;
return (
<div>
<TemperatureInput
scale="c"
temperature={celsius}
onTemperatureChange={this.handleCelsiusChange} />
<TemperatureInput
scale="f"
temperature={fahrenheit}
onTemperatureChange={this.handleFahrenheitChange} />
<BoilingVerdict
celsius={parseFloat(celsius)} />
</div>
);
}
}
ReactDOM.render(
<Calculator/>,
document.getElementById("note7")
)
//仈 组合 and 继承
//包含
function FancyBorder(props) {
//children 属性将子元素直接传递到输出。 将子元素传递过来
return (
<div className={'FancyBorder FancyBorder-' + props.color}>
{props.children}
</div>
);
}
//<FancyBorder> JSX 标签内的任何内容都将通过 children 属性传入 FancyBorder。
//由于 FancyBorder 在一个 <div> 内渲染了 {props.children},所以被传递的所有元素都会出现在最终输出中
function WelcomeDialog() {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
Welcome
</h1>
<p className="Dialog-message">
Thank you for visiting our spacecraft!
</p>
</FancyBorder>
);
}
ReactDOM.render(
<WelcomeDialog/>,
document.getElementById('note8')
)
//多个子元素 传入
function SplitPane(props) {
return (
<div className="SplitPane">
<div className="SplitPane-left">
{props.left}
</div>
<div className="SplitPane-right">
{props.right}
</div>
</div>
);
}
//类似 <Contacts /> 和 <Chat /> 这样的 React 元素都是对象,所以你可以像任何其他元素一样传递它们
//自定义 属性
// function App3() {
// return (
// <SplitPane
// left={
// <Contacts />
// }
// right={
// <Chat />
// } />
// );
// }
//通过组合来实现的,通过配置属性用较特殊的组件来渲染较通用的组件
function Dialog(props) {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
{props.title}
</h1>
<p className="Dialog-message">
{props.message}
</p>
</FancyBorder>
);
}
function WelcomeDialog2() {
return (
<Dialog
title="Welcome"
message="Thank you for visiting our spacecraft!" />
);
}
// 类中组合
// function Dialog(props) {
// return (
// <FancyBorder color="blue">
// <h1 className="Dialog-title">
// {props.title}
// </h1>
// <p className="Dialog-message">
// {props.message}
// </p>
// {props.children}
// </FancyBorder>
// );
// }
// class SignUpDialog extends React.Component {
// constructor(props) {
// super(props);
// this.handleChange = this.handleChange.bind(this);
// this.handleSignUp = this.handleSignUp.bind(this);
// this.state = {login: ''};
// }
// render() {
// return (
// <Dialog title="Mars Exploration Program"
// message="How should we refer to you?">
// <input value={this.state.login}
// onChange={this.handleChange} />
// <button onClick={this.handleSignUp}>
// Sign Me Up!
// </button>
// </Dialog>
// );
// }
// handleChange(e) {
// this.setState({login: e.target.value});
// }
// handleSignUp() {
// alert(`Welcome aboard, ${this.state.login}!`);
// }
// }
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();