React和JSX语法
在 React 中使用 JSX 语法描述用户界面,它是一种 JavaScript 语法扩展。
在 React 代码执行之前,Babel 会将 JSX 语法转换为标准的 JavaScript API。
JSX 语法就是一种语法糖,让开发人员使用更加舒服的代码构建用户界面。
JSX 语法
可以在JSX中使用表达式,JSX本身其实也是一种表达式,可以将它赋值给变量,当作参数传递,作为返回值
const user = {
name: 'tom',
age: 10
}
const element = <h1>hello {user.name} </h1>
function userInfo () {
return <div>{element}<div>age: {user.age}</div></div>
}
插值表达式
插值表达式中各种数据的插值状态
-
number——正常输出
-
true / false——不输出
-
undefined——不输出
-
null——不输出
-
数组——去掉逗号后渲染在页面
-
对象——需要调用属性名,不然会报错
function App () { const booleanVal = true const numberVal = 10 const nullVal = null const undefinedVal = undefined const arrayVal = [1, 2, 3, 4] const ObjectVal = { name: 'tom' } return ( <div> <div>{booleanVal}</div> {/* 不输出 */} <div>{numberVal}</div> {/* 输出 10 */} <div>{nullVal}</div> {/* 不输出 */} <div>{undefinedVal}</div> {/* 不输出 */} <div>{arrayVal}</div> {/* 输出 1234 */} {/* {ObjectVal} 报错 */} <div>{ObjectVal.a}</div> {/* 输出 tom */} </div> )}
列表渲染
function test2 () {
const arrayVal = [1, 2, 3, 4, 5]
return (
<ul>
{
arrayVal.map(item => {
return <li>itemVal: {item}</li>
})
}
</ul>
)}
JSX中属性值为字符串类型要加上引号,属性名称最好用驼峰式命名法;属性值式Javascript表达式时,属性值不用引号,要用大括号;类名必须使用className,不能用class;JSX中的标签必须闭合,不然会报错
const element1 = <div greeting="普通属性值" ></div>
const element2 = <img src={user.avatarUrl} /> {/* 值是表达式用大括号 */}
const element3 = <input type="text" /> {/* 标签必须闭合 */}
const element4 = <div className="user-avatar round">类目属性一定要用className</div>
标签中的事件
JSX中事件的绑定涉及this的指向,需要注意
{/* 第一个参数即是事件对象 不需传递 */}
<button onClick={this.eventHandler}>按钮</button>
{/* 需要传递事件对象 */}
<button onClick={e=>this.eventHandler('arg',e)}>按钮</button>
{/* 最后一个参数即是事件对象 不需传递 */}
<button onClick={this.eventHandler.bind(null, 'arg')}>按钮</button>
{/* 绑定this的指向 */}
constructor () {
{/* 在构造函数中将当前eventHandler进行强绑定 指向当前类组件实例 */}
this.eventHandler = this.eventHandler.bind(this)
}
eventHandler () {}
<button onClick={this.eventHandler}>按钮</button>
{/* 另一种方式是用箭头函数 */}
addAge = ()=>{
console.log(this)
}
<button onClick={this.addAge}>按钮</button>
组件
React中组件分为 类组件 和 函数组件
组件名称首字母必须大写,用来区分组件和普通标签
在JSX语法的外层必须有一个根元素
- 函数式组件
- 函数的名称就是组件的名称
- 函数的返回值就是组件要渲染的内容
- 函数组件中没有this
- 类式组件
- 组件类必须继承
React.Component - 组件类必须有
render方法 - 类组件中this指向实例本身
- 组件类必须继承
类组件
import React, { Component } from 'react';
class App extends Component {
constructor() {}
render () {
return <div>Hello, 我是类组件</div>
}
}
函数组件
const Person = () => {
return <div>Hello, 我是函数型组件</div>;
}
组件props传递
在调用组件时可以向组件内部传递数据,在组件中可以通过props获取外部传递进来的数据
-
props 对象中存储的数据是只读的,不能在组件内部被修改。
-
当 props 数据源中的数据被修改后,组件中的接收到的 props 数据会被同步更新。( 数据驱动DOM )
<Person name="乔治" age="20"/> <Person name="玛丽" age="10"/> // 类组件 class Person extends Component { constructor(props) { super(props) // 会将props挂载到当前实例的this上 // 这里可以拿到props 也可以用this.props } render() { return ( <div> <div>姓名:{this.props.name}</div> <div>年龄:{this.props.age}</div> </div> ); } } // 函数组件 // 通过函数的参数接收props const Person = props => { return ( <div> <div>姓名:{props.name}</div> <div>年龄:{props.age}</div> </div> ); }
设置props默认值
// 类组件
class App extends Component {
// 作为props的默认值 和传入props重复时,传入props值覆盖
static defaultProps = {
defaultName: 'tom'
}
}
// 函数组件
function ThemedButton(props) {
}
ThemedButton.defaultProps = {
theme: "secondary",
label: "Button Text"
}
组件children
通过props.children可以获取到在调用时填充到组件标签内部的内容(类似Vue的slot)
<Person>组件内部的内容</Person>
const Person = (props) => {
return (
<div>{props.children}</div> {/* 组件内部的内容 */}
);
}
单向数据流
-
在React中, 关于数据流动有一条原则, 就是单向数据流动, 自顶向下, 从父组件到子组件.
-
单向数据流特性要求我们共享数据要放置在上层组件中.
-
子组件通过调用父组件传递过来的方法更改数据.
-
当数据发生更改时, React会重新渲染组件树.
-
单向数据流使组件之间的数据流动变得可预测. 使得定位程序错误变得简单.
类组件state
类组件除了能够从外部 (props) 接收状态数据以外还可以拥有自己的状态 (state),此状态在组件内部可以被更新,状态更新 DOM 更新。
组件内部的状态数据被存储在组件类中的 state 属性中,state 属性值为对象类型,state 这个属性名称固定不可更改。
class App extends Component {
constructor () {
super()
this.state = {
person: { name: '张三', age: 20 },
}
}
render () {
return (
<div>
{this.state.person.name}
{this.state.person.age}
</div>
);
}
}
更改组件状态
state 状态对象中的数据不可直接更改,如果直接更改 DOM 不会被更新,要更改 state 状态数据需要使用 setState方法。
class App extends Component {
constructor () {
this.state = {
person: { name: '张三', age: 20 },
}
this.changePerson = this.changePerson.bind(this)
}
changePerson () {
this.setState({
person: {
name: '李四',
age: 15
}
})
}
render() {
return (
<div>
{this.state.person.name}
{this.state.person.age}
<button onClick={this.changePerson}>按钮</button>
</div>
);
}
}
state和props区别
- state 的主要作用是用于组件保存、控制、修改 自己 的可变状态,在组件内部进行初始化,也可以在组件内部进行修改,但是组件外部不能修改组件的 state
- props 的主要作用是让使用该组件的父组件可以传入参数来配置该组件,它是外部传进来的配置参数,组件内部无法控制也无法修改
- state 和 props 都可以决定组件的外观和显示状态。通常,props 做为不变数据或者初始化数据传递给组件,可变状态使用 state