一.首先React 是Javascript库,遵从javascript语法,先显示Hello World 熟悉下语法格式
直接在 https://codepen.io/gaearon/pen/ZpvBNJ?editors=1011 网页中直接观察React 效果.
1. 直接在页面中输出Hello World.
ReactDOM.render( <h1>Hello,World</h1>, document );
记得React后面的DOM全部大小,ReactDOM操作中render html标签 在 DOM 节点中(DOM 节点使用javascript进行操作)
通过ReactDOM API 可以一起操作html和javascript 。
之前使用javascript 是操作的字符串
1 document.write("<h1>22222</h1>");
或者是
document.getElementsByTagName('body')[0].innerHTML="<h1>22222</h1>";
都要拼接字符串。这是react留给我们的第一个印象。
不熟悉javascript 语法的,请看这里 https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript
2.再来一个加强一下React语感
render 一个变量
1 const element = 2 <h1> 3 Hello, World 4 </h1> 5 6 7 ReactDOM.render( 8 element, 9 document.getElementById('root') 10 );
还是不需要拼接字符串 双引号。感觉很好
1 var user = { 2 Name:"michelle", 3 Email:"[email protected]" 4 } 5 const element = 6 <h1> 7 Hello, World {user.Name,user.Email} 8 </h1> 9 10 11 ReactDOM.render( 12 element, 13 document.getElementById('root')
如果想要显示自己定义的javascript对象或者函数可以使用{}符号。不仅不需要拼接字符串,还给变量附加了javascript的强大功能。JSX语法或者理解成XML中使用JavaScript
3.介绍一个新名词props(properties 属性 既组件的属性)
属性的概念我们并不陌生,比如<img src=""/>,src 就是img 标签的属性,src 中输入了正确的url地址,浏览器解析到该img标签的时候就会load一张图片。是不是很强大。
jquery也有操作prop属性的api,可以获取和设置标签的prop值。React 的props相对jquery的prop是复数的概念。是不是意味着更强大。
注意:React 可以自定义组件,也可以使用html 中的标签,自定义组件时,组件名称以大写字母开始,定义为一个函数.也可以使用ES6的语法定义为一个继承React.Component 的Class.
1 function Welcome(props) { 2 return <h1>Hello, {props.name}</h1>; 3 } 4 5 const element = <Welcome name="Michelle" />; 6 ReactDOM.render( 7 element, 8 document.body 9 );
Welcome 组件的 name 就是props属性,是不是和html的标签很类似。
但是props 是不可以改变的。你只能在组件中输入一个值附加到props属性上,但是不能使用代码变化props的值,如果你让组件的属性可以用代码进行变化。那么你只能使用state.
4.我们再来看一下另一个新名词state,状态,这是什么东西呢。
1 function Welcome(props){ 2 state = {Name:'Hi! I am here'}; 3 return <h1> {state.Name} {props.Name}</h1>; 4 } 5 ReactDOM.render( 6 <Welcome Name="not here"/>, 7 document.getElementById('root') 8 );
props 是在Welcome组件标签上进行赋值的,state 是在组件内部赋值的。如果你想代码变化state 值,必须借助setState 函数进行操作
1 class Toggle extends React.Component { 2 constructor(props) { 3 super(props); 4 this.state = {isToggleOn: true}; 5 6 // This binding is necessary to make `this` work in the callback 7 this.handleClick = this.handleClick.bind(this); 8 } 9 10 handleClick() { 11 this.setState(prevState => ({ 12 isToggleOn: !prevState.isToggleOn 13 })); 14 } 15 16 render() { 17 return ( 18 <button onClick={this.handleClick}> 19 {this.state.isToggleOn ? 'ON' : 'OFF'} 20 </button> 21 ); 22 } 23 } 24 25 ReactDOM.render( 26 <Toggle />, 27 document.getElementById('root') 28 );
注意:
你必须谨慎对待 JSX 回调函数中的 this
,类的方法默认是不会绑定 this
的。如果你忘记绑定 this.handleClick
并把它传入 onClick
, 当你调用这个函数的时候 this
的值会是 undefined
。
通常情况下,如果你没有在方法后面添加 ()
,例如 onClick={this.handleClick}
,你应该为这个方法绑定 this
。
bind 可以有另两种实现绑定this的同样效果,可以使用lambda的箭头表达式,或者在onClick中直接传递参数e.
class LoggingButton extends React.Component {
// This syntax ensures `this` is bound within handleClick.
// Warning: this is *experimental* syntax.
handleClick = () => {
console.log('this is:', this);
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
);
}
}
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
// This syntax ensures `this` is bound within handleClick
return (
<button onClick={(e) => this.handleClick(e)}>
Click me
</button>
);
}
}
5.state 和 props 混合使用,状态提升
1 const scaleNames = { 2 c: 'Celsius', 3 f: 'Fahrenheit' 4 }; 5 6 function toCelsius(fahrenheit) { 7 return (fahrenheit - 32) * 5 / 9; 8 } 9 10 function toFahrenheit(celsius) { 11 return (celsius * 9 / 5) + 32; 12 } 13 14 function tryConvert(temperature, convert) { 15 const output = convert(temperature); 16 const rounded = Math.round(output * 1000) / 1000; 17 return rounded.toString(); 18 } 19 20 function BoilingVerdict(props) { 21 if (props.celsius >= 100) { 22 return <p>The water would boil.</p>; 23 } 24 return <p>The water would not boil.</p>; 25 } 26 27 class TemperatureInput extends React.Component { 28 constructor(props) { 29 super(props); 30 this.handleChange = this.handleChange.bind(this); 31 } 32 33 handleChange(e) { 34 this.props.onTemperatureChange(e.target.value); //子组件的props关联了父组件的state e.target.value(handleCelsiusChange,handleFahrenheitChange) 35 } 36 37 render() { 38 const temperature = this.props.temperature; 39 const scale = this.props.scale; 40 return ( 41 <fieldset> 42 <legend>Enter temperature in {scaleNames[scale]}:</legend> 43 <input value={temperature} 44 onChange={this.handleChange} /> 45 </fieldset> 46 ); 47 } 48 } 49 50 class Calculator extends React.Component { 51 constructor(props) { 52 super(props); 53 this.handleCelsiusChange = this.handleCelsiusChange.bind(this); 54 this.handleFahrenheitChange = this.handleFahrenheitChange.bind(this); 55 this.state = {temperature: '', scale: 'c'}; 56 } 57 58 handleCelsiusChange(temperature) { 59 this.setState({scale: 'c', temperature}); 60 } 61 62 handleFahrenheitChange(temperature) { 63 this.setState({scale: 'f', temperature}); 64 } 65 66 render() { 67 const scale = this.state.scale; 68 const temperature = this.state.temperature; 69 const celsius = scale === 'f' ? tryConvert(temperature,toCelsius) : temperature; 70 const fahrenheit = scale === 'c' ? tryConvert(temperature,toFahrenheit) : temperature; 71 72 return ( 73 <div> 74 <TemperatureInput 75 scale="c" 76 temperature={celsius} 77 onTemperatureChange={this.handleCelsiusChange} //handleCelsiusChange 是setState方法 /> 78 <TemperatureInput 79 scale="f" 80 temperature={fahrenheit} 81 onTemperatureChange={this.handleFahrenheitChange} //handleFahrenheitChange是setState方法 /> 82 <BoilingVerdict 83 celsius = {parseFloat(temperature)} /> 84 </div> 85 ); 86 } 87 }; 88 89 90 ReactDOM.render(<Calculator />,document.getElementById('root'));
核心方法是父组件处理setState,进行值的变化,子组件使用props显示,并挂接上父组件改变state的方法。好像props的值也可以改变了。props值变成state了。
注意:判断哪些是state哪些是props的一些原则:
a)是否通过 props(属性) 从父级传入? 如果是这样,它可能不是 state(状态) 。
b)是否永远不会发生变化? 如果是这样,它可能不是 state(状态)。
c)是否可以由组件中其他的 state(状态) 或 props(属性) 计算得出?如果是这样,则它不是 state(状态)。
二.React 进阶