JSX
JSX
是一种JavaScript语法的拓展,React
中就是用JSX来描述用户界面的。
在JavaScript中写JSX代码,必须要有:
<script type="text/babel"></script>
在写js或jq的时候,我们可以不用写type
,但这个一定要写,引用JSX文件也要写。
元素是构成 React 应用的最小单位,JSX 就是用来声明 React 当中的元素,而这个元素就是我们在js中的对象。
声明元素
var myDivElement = <div className="foo" />;
const element = <h1>Hello, world!</h1>;
和js的声明有一些像,但又有不同,它直接声明了一个对象,并且:
在ReactDOM中,使用className代替class,用htmlFor代替for
渲染元素
那么我们怎么把React元素渲染到页面中?
我们是用ReactDOM.render(渲染元素,插入节点)
方法。
const text = <h1>hello word!</h1>;
ReactDOM.render(
text,
document.querySelector("div")
);
//把text对象插入到div中
ReactDOM.render()
方法每次只能传递一个元素,如果想要传递多个元素
,比如:p+span+ul li
,这种的,可以嵌套HTML代码
,用div包裹
他们,相当于直接传递了div这一个元素。
ReactDOM.render(
<div>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<p>123</p>
</div>
,
document.querySelector("div")
);
但包裹的时候,我们无法在里面直接使用我们定义的变量,比如:
ReactDOM.render(
<div>
text
<p>123</p>
</div>
,
document.querySelector("div")
);
这样会直接输出text,会把他直接当成文本来处理。那我们怎么才能使用变量呢?那就需要使用{}
。
{}
{}
中可以写很多东西。
- 表达式
var i=1;
ReactDOM.render(
<div>
<p>123</p>
<p>{1*2+3}</p>
<p>{i == 1 ? "true" : "false" }</p>
//不能使用if else语句,可以使用三元运算符
</div>
,
document.querySelector("div")
);
- css样式
var mystyle={
color: 'red', //颜色值要用引号括起来
fontSize: 20 //React会直接在后面加px
};//可以把mystyle看成对象,{}作用是展开,和数组一结合更能看出来
ReactDOM.render(
<div>
<p style = {mystyle} >123</p>
</div>
,
document.querySelector("div")
);
- 注释
ReactDOM.render(
//没有在标签内部,可以
<div>
<p style = {mystyle} >123</p>
//在js中这种注释可以,但在标签内部不可以
{/*在标签内部,只能使用这种注释*/}
</div>
,
document.querySelector("div")
);
csdn中都会变斜体,因为这是js的代码环境。
- 数组
var arr = [
<h1>菜鸟教程</h1>,
<h2>学的不仅是技术,更是梦想!</h2>,
];
ReactDOM.render(
<div>{arr}</div>,
document.getElementById('example')
);
- 函数
function formatName(user) {
return user.firstName + ' ' + user.lastName;
}
const user = {
firstName: 'harper',
lastName: 'Perez'
}
const element = <h1> Hello, {formatName(user)}! </h1>
ReactDOM.render (
element,
document.querySelector('div')
)
{}的展开作用
:
ReactDOM.render(
<div>
<p style={{fontSize:20,color:'blue'}}>123</p>
<div>{[<h1>123</h1>,<h2>123</h2>]}</div>
</div>
,
document.querySelector("div")
);
组件
在JSX中定义组件
,最简单的方式就是定义一个function函数
。
而这个组件的第一个字母必须大写!
function HelloMessage(props) {
return <h1>Hello {props.name}!</h1>;
}
const element = <HelloMessage name="Runoob"/>;
HelloMessage
就是我们自定义的一个组件
,props
是传递的参数
,我们使用< HelloMessage />
来渲染组件,相当于调用函数。
并且在< HelloMessage />
后面的name
会作为props
的一个属性
来使用,我们可以使用props.name
来使用这个属性。
function Name(props) {
return <h1>网站名称:{props.name}</h1>;
}
function Url(props) {
return <h1>网站地址:{props.url}</h1>;
}
function Nickname(props) {
return <h1>网站小名:{props.nickname}</h1>;
}
function App() {
return (
<div>
<Name name="菜鸟教程" />
<Url url="http://www.runoob.com" />
<Nickname nickname="Runoob" />
</div>
);
}
ReactDOM.render(
<App />,
document.getElementById('example')
);
练习
基本的东西也不多,下面主要根据阮一峰的react入门来练习,不过它上面的代码是es5的了,现在推荐使用es6,所以我会把他的代码转成新版来写,可以对照着看。
this.props.children
class NotesList extends React.Component{
render = ()=>{
return (
<ol>
{
React.Children.map( //this指向类,this.props.children是NotesList下的两个节点,map方法用于遍历
this.props.children,function(child){
return <li>{child}</li>
}
)
}
</ol>
);
}
}
ReactDOM.render(
//定义一个NotesList组件,里面包含两个节点,把他们渲染到div中
<NotesList>
<span>hello</span>
<span>word</span>
</NotesList>
,
document.querySelector('div'),
)
React.Children
用来处理this.props.children,再使用map遍历
子节点。
this.props.children
的值有三种可能:如果当前组件没有子节点,它就是 undefined
;如果有一个子节点,数据类型是object
;如果有多个子节点,数据类型就是 array
。
PropTypes
组件中有PropTypes
属性,用来验证实例的属性是否符合要求
。
class Example extends React.Component{
render = ()=>{
return (
<h1>{this.props.title}</h1>
);
}
}
Example.propTypes = {
title:PropTypes.string//规定title只能是string
};
ReactDOM.render(
<Example title={123}/>
,
document.querySelector('div'),
)
默认值
Example.defaultProps = {
name : 'bob'
}
使用defaultProps
为 props
设置默认值,如果构造实例时并没有规定name值,则会使用默认值。
获取真实的DOM节点
组件并不是真正的DOM节点,而是存在于内存中的一种数据结构,叫虚拟DOM。当它插入文档后,才会变成真正的DOM。所有的变动,都现在虚拟DOM上发生,然后再反映到真正的DOM上。也就是说,组件和真正的DOM节点并不是直接操作的,但我们有时候需要获取真正的DOM节点。
class Example extends React.Component{
constructor(props){
super(props);
this.handleClick=this.handleClick.bind(this);
}
handleClick(){
this.refs.myinput.focus();
}
render = ()=>{
return (
<div>
<input type="text" name="" id="" ref="myinput"/>
<input type="button" value="Focus the text input" onClick={this.handleClick}/>
</div>
);
}
}
ReactDOM.render(
<Example/>
,
document.querySelector('div'),
)
效果:
文本输入框必须有一个 ref
属性,然后 this.refs.[refName]
就会返回这个真实的 DOM 节点。
this.state
组件最重要的作用就是跟用户互动,互动就会有更新。在React中,组件就是一个状态机,一开始有一个初始状态,用户互动,会导致状态发生改变,重新渲染。
class Example extends React.Component{
constructor(props){
super(props);
this.state = {liked : false};//初始化state状态,属性liked为false
this.handleClick=this.handleClick.bind(this);//将this绑定在此类
}
handleClick(){
this.setState({liked : !this.state.liked});//改变属性liked
}
render = ()=>{
var text = this.state.liked ? 'like' : 'haven\'t liked';
return (
<p onClick={this.handleClick}>
You {text} this. Click to toggle.
</p>
);
}
}
ReactDOM.render(
<Example/>
,
document.querySelector('div'),
)
setState
的用法可以参考这个:https://blog.csdn.net/qq_44162474/article/details/107752079?utm_medium=distribute.pc_relevant.none-task-blog-baidulandingword-4&spm=1001.2101.3001.4242
当用户点击组件,导致状态变化,this.setState 方
法就修改状态值,每次修改以后,自动调用 this.render
方法,再次渲染组件。
表单
用this.state获取表单改变时的值。
class Example extends React.Component{
constructor(props){
super(props);
this.state = {value : 'Hello!'};//初始化state状态
}
handleChange = (event) => {//event代表发生事件源
this.setState({value : event.target.value});
//setState可以改变
}
render = ()=>{
return (
<div>
<input type="text" value={this.state.value} onChange={this.handleChange} />
<p>
{this.state.value}
</p>
</div>
);
}
}
ReactDOM.render(
<Example/>
,
document.querySelector('div'),
)
组件的生命周期
组件的生命周期被分为三个状态:
-
Mounting:
已插入真实DOM
-
Updating:
正在被重新渲染
-
Unmouting:
已移出真实DOM
状态处理函数:
will 函数在进入状态之前调用,did 函数在进入状态之后调用
componentWillMount()
componentDidMount()
componentWillUpdate(object nextProps, object nextState)
componentDidUpdate(object prevProps, object prevState)
componentWillUnmount()
-
componentWillReceiveProps(object nextProps):
已加载组件收到新的参数时调用
-
shouldComponentUpdate(object nextProps, object nextState):
组件判断是否重新渲染时调用
class Example extends React.Component{
constructor(props){
super(props);
this.state = {opacity : 1.0};//初始化state状态
}
componentDidMount=function(){//当组件插入到真实dom树后执行的操作
this.timer=setInterval(function () {
var opacity=this.state.opacity;//1.0
opacity -= 0.5;//0.5
if(opacity<0.1){
opacity = 1.0;
}
this.setState({opacity:opacity});
}.bind(this),1000);//每间隔1000毫秒改变透明度
}
render = ()=>{
return (
<div style={{opacity:this.state.opacity}}>
hello{this.props.name}
</div>
);
}
}
ReactDOM.render(
<Example name="world"/>
,
document.querySelector('div'),
)
例子
class Example 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;//获取当前dom元素
const value = target.type === 'checkbox' ? target.checked : target.value;
//当前元素的type如果是checkbox,那么value=false/true,否则是number
const name = target.name;
//当前元素的name属性存到name变量
this.setState({
[name]: value//isGoing:true/false;numberOfGuests:2
//因为现在name是变量,所以需要用[]引用,实现动态修改key值
});
}
render() {
return (
<form>
<label>
是否离开:
<input
name="isGoing"
type="checkbox"
checked={this.state.isGoing}
onChange={this.handleInputChange} />
</label>
<br />
<label>
访客数:
<input
name="numberOfGuests"
type="number"
value={this.state.numberOfGuests}
onChange={this.handleInputChange} />
</label>
</form>
);
}
}
ReactDOM.render(
<Example name="world"/>
,
document.querySelector('div'),
)