【React】属性介绍
·
React全家桶
- React基础
- React-Router,专门做路由的
- PubSub,消息管理
- Redux,集中式状态管理的库
- Ant-Design,ui组件库
React简介
- 中文官网
- 用于构建用户界面的javaScript库
- 是一个将数据渲染为HTML视图的开源javaScript库
为什么要学?
原生js,操作DOM繁琐,效率低,且会进行大量的重绘重排,且没有组件化编码方案,代码复用率低
优点
- 采用组件化模式,声明式编码,提高开发效率和组件复用率
- 在React Native中可以使用React语法进行移动端开发
- 使用虚拟Dom+优秀的Diffing算法,尽量减少与真实Dom的交互
总结一下特点
- 声明式编码
- 组件化编码
- React Native编写原生应用
- 高校,优秀的Diffing算法
相关的js库
- react.js React核心库
- react-dom.js 提供操作DOM的react扩展库
- babel.min.js 解析jsx语法代码转为js代码的库,类似es6转es5中有使用
jsx的hello word 示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>hello React</title>
</head>
<body>
<!-- 准备容器 -->
<div id="test"></div>
<!-- 引入react,development必须先引入,全局多了React -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作dom,全局多了ReactDOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js">
</script>
<!-- 此处一定要写babel,不能默认js -->
<script type="text/babel">
// 创建虚拟dom,jsx不加单引号,因为不是字符串
const VDOM = <h1>Hello, React!</h1>;
// 渲染虚拟dom到页面
ReactDOM.render(
VDOM,
document.getElementById('test')
);
</script>
</body>
</html>
js的hello word 示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>hello React</title>
</head>
<body>
<!-- 准备容器 -->
<div id="test"></div>
<!-- 引入react,development必须先引入,全局多了React -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作dom,全局多了ReactDOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
</script>
<script type="text/javascript">
// 创建虚拟dom,createElement(标签名, 属性对象, 标签内容)
const VDOM =React.createElement(
'h1',
null,
'Hello, React!'
);
// 渲染虚拟dom到页面
ReactDOM.render(
VDOM,
document.getElementById('test')
);
</script>
</body>
</html>
jsx和js的区别,为啥用jsx
- jsx创建虚拟dom更简便
- js
const VDOM = React.createElement(
'h1',
{ id: title },
React.createElement(
'span',
null,
'Hello, React!'
)
);
- jsx,创建虚拟dom更简便
const VDOM = <h1 id='title'>Hello,<span>变化的</span> React!</h1>;
虚拟DOM
const VDOM = <h1 id='title'>Hello,<span>变化的</span> React!</h1>;
const TDOM = document.getElementById('test')
console.log(VDOM,'虚拟dom');
console.log(TDOM,'真实dom');

- 1,本质是Object类型的对象(一般对象)
- 2,虚拟dom比较‘轻’(自身携带的属性少),真实dom比较重(自身携带的属性多)
- 3,虚拟dom最终会被react转化为真实dom,展现在页面上
jsx介绍
- 全程javaScript XML
- react定义的一种类似xml的js扩展语法:js+xml
- 本质是React.createElement()的语法糖
- 作用,简化DOM
- jsx不是字符串,不要写引号,也不是html/xml标签
- jsx渲染js表达式,只能渲染表达式,需要花括号{ }包裹
- jsx渲染css,不能采用class,使用className
- jsx内联样式,采取双花括号{{key:value}}
- jsx只能有一个根标签,不能有多个
- jsx的标签首字母, 若小写开头,在转html过程中,若html无该对应的标签同名,则报错
- jsx的标签首字母, 若大写开头,则去渲染对应的组件,若组件没有定义,则报错
- 标签必须闭合,类似下面的input
- jsx最终产生的就是一个js对象
<style>
.title {
background: blue;
}
</style>
<!-- 变量和样式和内联样式-->
<script type="text/babel">
const name = 'Hello,'
//根标签仅有一个
const VDOM = <div>
<h1 className='title'>{name}<span style={{ color: 'white', fontSize: '16px' }}>变化的</span> React!</h1><h1 className='title'>{name}<span style={{ color: 'white', fontSize: '16px' }}>变化的</span> React!</h1>
<input type="text"/>
</div>;
ReactDOM.render(
VDOM,
document.getElementById('test')
);
</script>
jsx渲染表达式
注意区分js语句和js表达式
- 表达式,一个表达式会产生一个值,可以放在任何一个需要值的地方
- 类似:a,a+b,num(),arr.map(),function num()
- 语句(代码),控制代码走向,没有值
- 类似,if判断,for循环,switch等
<script type="text/babel">
const data = [1, 2, 3, 4, 5]
//data.map是js表达式,有返回值,循环必须有惟一的key值
const VDOM = <div>
<ul>
{
data.map((item, index) => {
return <li key={index}>{item}</li>
})
}
</ul>
</div>;
ReactDOM.render(
VDOM,
document.getElementById('test')
);
</script>
模块与组件
- 模块,向外提供特定功能的js程序,一般就是一个js文件
- 组件,用来实现局部功能的代码和资源集合(html/css/js/image)
- 模块化的应用,应用的js都以模块编写,
- 组件化的应用,应用是多组件实现的
React面向组件编程
常用游览器开发插件
- 扩展商店搜 React Developer Tools
创建组件
函数式组件,用函数定义的组件
注意事项:
1,组件的首字母必须大写
2,函数必须有返回值
3,渲染的时候必须要写组件标签
- 实现流程:
- React解析组件Mydemo组件标签,找到Mydemo组件
- 发现组件是使用函数定义的,随后调用该函数,将返回的虚拟dom转为真实dom,随后呈现在页面上
<script type="text/babel">
//创建函数式组件
function Mydemo(params) {
console.log(this);
//undefined,babel编译完开启严格模式,严格模式下禁止this指向windows
return <h2>我是用函数定义的组件</h2>
}
// 渲染组件到页面,不对,不能直接把组件这么渲染
// ReactDOM.render(demo, document.getElementById('test'))
ReactDOM.render(<Mydemo/>, document.getElementById('test'))
</script>
类式组件,用类定义的组件
介绍一下类的基本知识
1,类中的构造器不是必须写的(可省略),要对实例进行初始化操作的时候,如添加指定属性的时候
2,如果a继承b,且b有构造器,且a类的super必须调用
3,类中所定义的方法,都是放在类的原型对象上,供实例使用
注意事项:
1,组件的首字母必须大写
2,类里必须有render()
3,render()里面必须有return
- 实现流程:
- React解析组件Mydemo组件标签,找到Mydemo组件
- 发现组件是使用类定义的,随后new出来该类的实例,然后通过该实例调用到原型上的render的方法
- 将render返回的虚拟dom转为真实dom,呈现到页面上
<script type="text/babel">
//react的类,必须继承React.Component
class MyDemo extends React.Component {
// render是放在MyDemo原型对象上,供实例使用
// render的this,指向是MyDemo组件实例对象
render() {
return <h2>我是用类定义的组件</h2>
}
}
//<MyDemo />,react帮你new了个实例
ReactDOM.render(<MyDemo />, document.getElementById('test'))
</script>
两者区别

构造器constructor
- 可省略
- 在react中,构造器仅能用于以下两种情况
- 1,通过给this。state赋值对象来初始化内部state
- 2,为事件处理函数绑定实例
- 注意:constructor()函数中不要调用setState()方法,如果你的组件使用内部state,直接在构造函数中为this.state赋值初始化state
- 注意: super(props)要在其它语句之前调用,否则可能会出现未定义的bug
- 注意:构造器是否想通过this访问props,想就要将props传递给super
//构造器的使用
class Weather extends React.Component {
constructor(props) {
super(props)
this.state = {
isUser: false,
name: '乞力马扎罗',
newname: '罗曼蒂克',
}
this.changeName = this.changeName.bind(this)
}
render() {
const { isUser, name, newname } = this.state
return <h2 onClick={this.changeName}>我是用复杂组件,我叫{isUser ? name : newname}</h2>
}
changeName(params) {
const { isUser } = this.state
this.setState({
isUser: !isUser
})
}
}
- 省略构造器的使用
class Weather extends React.Component {
state = {
isUser: false,
name: '乞力马扎罗',
newname: '罗曼蒂克',
}
changeName = (params) => {
const { isUser } = this.state
this.setState({
isUser: !isUser
})
}
render() {
const { isUser, name, newname } = this.state
return <h2 onClick={this.changeName}>我是用复杂组件,我叫{isUser ? name : newname}</h2>
}
}
React属性新变化(和Vue区别)
- 样式class,变为className
- 行内样式style={},变为style={{}}
- 事件点击onclick,变为onClick,React所有onxxx都变为onXxx
- 事件点击οnclick=“demo()”,变为onClick={demo}
组件实例的三大核心属性
- 类组件中render方法中的this为组件实例对象
- 自定义组件的方法的this是undefined
state
- state是组件对象最重要的属性,值是对象
- 组件被成为状态机,通过更新组件到state来更新对应的页面显示
初始化state方法
- 构造器constructor里面初始化state的值
- 直接通过state={ }赋值
自定义方法的绑定this的方式
强制绑定this,通过函数对象的bind()
- this.changeName = this.changeName.bind(this)重写方法,挂载新方法到实例对象自身,传递实例对象
箭头函数
- 采用赋值语句+箭头函数绑定this,获取不到this时候会向外层去获取, changeWeather = () => {this.setState({ temperature: ‘33’ });}
setState修改状态值
- state的数据不能直接修改或更新,需通过setState
- this.setState({isUser: !isUser}),this.setState更改state状态值
- this.setState是个合并动作,不会删除其它属性
类的属性调用 次数
- 构造器constructor,只会调用一次
- render,会调用1+n次,1是初始化的1次,n是点击setState状态更新的n次
- 自定义方法,点几次,调用几次
<script type="text/babel">
// 简单组件
class MyDemo extends React.Component {
render() {
return <h2>我是简单</h2>
}
}
//有状态组件/复杂组件
class Weather extends React.Component {
constructor(props) {
super(props)
// 初始化状态
this.state = {
isUser: false,
name: '乞力马扎罗',
newname: '罗曼蒂克',
}
// 解决changeName的this丢失问题,传递了Weather实例对象
// 将原型上的changeName挂载给当前Weather实例对象自身
// 这的bind相当于重写方法挂载this.changeName,如果这里改名,下面onClick={this.changeName}调用也得改名
this.changeName = this.changeName.bind(this)
}
render() {
// 读取状态
const { isUser, name, newname } = this.state
return <h2 onClick={this.changeName}>我是用复杂组件,我叫{isUser ? name : newname}</h2>
}
changeName(params) {
//changeName放在weather原型上,供实例使用
//changeName只能实例调用,通过Weather实例调用changeName,changeName的this就是Weather实例
//this.changeName方法里面this丢失,因为changeName作为onClick的回调,不是实例调用,是直接调用
//类中的方法开启默认局部严格模式,所以changeName的this丢失,为undefined
console.log(this);
// this.state.isUser = !this.state.isUser
//注意:state状态数据不支持直接修改,借助内置api,this.setState更改
const { isUser } = this.state
//更新状态
this.setState({
isUser: !isUser
})
}
}
//这里的this丢失,所以不能使用,方法1 ,外层定义that,Weather缓存this,但不建议这样使用
// function changeName(params) {
// console.log("点击事件,修改isUser", this.state.isUser);
// console.log("点击事件,修改isUser", that.state.isUser);
// }
ReactDOM.render(<MyDemo />, document.getElementById('test'))
ReactDOM.render(<Weather />, document.getElementById('test2'))
</script>


state属性精简写法
<script type="text/babel">
class Weather extends React.Component {
// 初始化状态
state = {
temperature: 20 // 初始温度
}
render() {
const { city, temperature } = this.state;
return (
<div>
<h1 className='title'>Weather in {city}</h1>
<p>Temperature: {temperature}°C</p>
<p onClick={this.changeWeather}>修改天气</p>
</div>
);
}
// 自定义方法,采用赋值语句+箭头函数绑定this,获取不到this时候会向外层去获取
changeWeather = () => {
this.setState({ temperature: '33' });
}
}
const VDOM = <div>
<Weather city='Beijing' temperature={20} />
</div>
//渲染组件到页面
ReactDOM.render(
VDOM,
document.getElementById('test')
);
</script>
props
- props是只读的
- 组件上直接传输,this.props获取
<!-- 引入prop-types,用于对组件标签属性进行限制 -->
<script type="text/javascript" src="../js/prop-types.js">
</script>
<script type="text/babel">
class Person extends React.Component {
render() {
const { name, sex, age } = this.props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age}</li>
</ul>
);
}
}
//引入prop-types 标签属性进行限制,speak是函数类型,name是字符串类型且必传
Person.propTypes = {
name: PropTypes.string.isRequired,
speak: PropTypes.func
}
// 标签属性进行默认值设置
Person.defaultProps = {
name: '张三', //默认值
}
//渲染组件到页面
ReactDOM.render(
<Person name='Beijing' sex='男' age='20' />,
document.getElementById('test')
);
//渲染组件到页面,name传number类型,会报错
const p = { name: 1, sex: '男', age: '20' }
function speak(params) {
console.log('hello');
}
ReactDOM.render(
<Person {...p} speak={speak} />,
document.getElementById('test1')
);
</script>
props简写(类组件使用)
<!-- 引入prop-types,用于对组件标签属性进行限制 -->
<script type="text/javascript" src="../js/prop-types.js">
</script>
<script type="text/babel">
class Person extends React.Component {
// 引入prop-types 标签属性进行限制
static propTypes = {
name: PropTypes.string.isRequired,
speak: PropTypes.func
}
// 标签属性进行默认值设置
static defaultProps = {
name: '张三', //默认值
}
render() {
const { name, sex, age } = this.props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age}</li>
</ul>
);
}
}
//渲染组件到页面
ReactDOM.render(
<Person name='Beijing' sex='男' age='20' />,
document.getElementById('test')
);
//渲染组件到页面,name传number类型,会报错
const p = { name: 1, sex: '男', age: '20' }
function speak(params) {
console.log('hello');
}
ReactDOM.render(
<Person {...p} speak={speak} />,
document.getElementById('test1')
);
</script>
函数组件使用props
- props直接使用即可
// 函数组件
function Person2(props) {
const { name, sex, age } = props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age}</li>
</ul>
);
}
ReactDOM.render(
<Person2 {...p} speak={speak} />,
document.getElementById('test2')
);
ref
字符串的ref
class Person extends React.Component {
showDate = () => {
// 通过ref获取input的真实DOM元素,但不建议使用
console.log(this.refs.inputRef);
const { inputRef } = this.refs
alert(inputRef.value)
}
showDate2 = () => {
// 通过ref获取input的真实DOM元素
console.log(this.refs.inputRef2);
const { inputRef2 } = this.refs
alert(inputRef2.value)
}
render() {
const { name, sex, age } = this.props
return (
<div>
<input ref='inputRef' type="text" placeholder='点击按钮提示数据' />
<button ref='buttonRef' onClick={this.showDate}>提示</button>
<input ref="inputRef2" type="text" placeholder='失去焦点提示数据' onBlur={this.showDate2} />
</div>
);
}
}
ReactDOM.render(
<Person />,
document.getElementById('test')
);
回调函数ref写法(建议使用)
- 以这样的内联函数的方式定义的,在更新过程中会执行两次,第一次传入参null,第二次会传入dom元素
- 原因:每次渲染的时候会创建一个新的函数实例,所以react清空旧的,设置新的
- 初始化执行两次,但打印一次,第一次随render执行
- 更新内容的时候执行两次,打印两次
- 解决办法:通过将ref的回调函数定义成class的绑定函数的方式,可以避免打印两次
方式1
class Person extends React.Component {
// 回调函数,默认传的参数是当前元素的真实DOM
// this就是当前组件的实例对象,把ref当前的节点挂载在实例自身上,并且取名input1
showDate = () => {
// 通过ref获取input的真实DOM元素,但不建议使用
console.log(this.input1);
alert(this.input1.value)
}
render() {
const { name, sex, age } = this.props
return (
<div>
<input ref={c => this.input1 = c} type="text" placeholder='点击按钮提示数据' />
<button ref='buttonRef' onClick={this.showDate}>提示</button>
</div>
);
}
}
ReactDOM.render(
<Person />,
document.getElementById('test')
);
方式2 class的绑定函数 建议使用
saveInput = c => {
this.input2 = c
console.log(this.input2);
}
render() {
const { name, sex, age } = this.props
return (
<div>
<input ref={this.saveInput} type="text" placeholder='点击按钮提示数据2' />
<button ref='buttonRef' onClick={this.showDate}>提示</button>
</div>
);
}
createRef形式(建议使用)
- 通过React.createRef()创建一个ref容器对象
- createRef是专人专用的,只能放一个,后者替换前者
<script type="text/babel">
// 类组件
class Person extends React.Component {
// 通过React.createRef()创建一个ref容器对象
myRef1 = React.createRef()
myRef2 = React.createRef()
showDate = () => {
// 通过ref获取input的真实DOM元素
console.log(this.myRef1);
alert(this.myRef1.current.value)
}
showDate2 = () => {
// 通过ref获取input的真实DOM元素
console.log(this.myRef2);
alert(this.myRef2.current.value)
}
render() {
const { name, sex, age } = this.props
return (
<div>
<input ref={this.myRef1} type="text" placeholder='点击按钮提示数据' />
<input ref={this.myRef2} type="text" placeholder='失去焦点提示数据' onBlur={this.showDate2} />
<button ref='buttonRef' onClick={this.showDate}>提示</button>
</div>
);
}
}
ReactDOM.render(
<Person />,
document.getElementById('test')
);
</script>
事件处理
1,通过onXxx属性指定事件处理函数,注意大小写
2,React使用的是自定义事件,而不是使用的原生dom事件(为了更好的兼容性)
3,React中的事件是通过事件委托方式处理的(委托给最外层元素,为了高效)
4,不要过度使用ref,可以通过event.target得到发生事件的dom元素对象
showDate3 = (e) => {
console.log(e.target);
alert(e.target.value)
}
render() {
const { name, sex, age } = this.props
return (
<div>
<input type="text" placeholder='失去焦点提示数据' onBlur={this.showDate3} />
</div>
);
}
非受控组件
- 页面中输入类的值现用现取,不会提前存储
- 得用ref
受控组件(类似双向绑定)
- 页面中输入类的值会实时保存在状态中,需要用的时候直接从状态中取
- 采取state状态
<script type="text/babel">
// 创建类组件
class Person extends React.Component {
handleSubmit = (e) => {
// 阻止表单提交的默认行为
e.preventDefault();
const { username, sex, age } = this;
alert(`用户名:${username.value}, 性别:${sex.value}, 年龄:${age.value}`);
}
// 非受控组件,现用现取
render() {
return (
<form onSubmit={this.handleSubmit}>
用户名:<input type="text" ref={c => this.username = c} /><br />
性别:<input type="text" ref={c => this.sex = c} /><br />
年龄:<input type="text" ref={c => this.age = c} /><br />
<button>登录</button>
</form>
);
}
}
ReactDOM.render(
<Person />,
document.getElementById('test')
);
class Person2 extends React.Component {
// 初始化状态
state = {
username: '',
sex: '',
age: ''
}
saveUsername = (e) => {
this.setState({
username: e.target.value
})
}
saveAge = (e) => {
this.setState({
age: e.target.value
})
}
saveSex = (e) => {
this.setState({
sex: e.target.value
})
}
handleSubmit = (e) => {
// 阻止表单提交的默认行为
e.preventDefault();
const { username, sex, age } = this.state;
alert(`用户名:${username}, 性别:${sex}, 年龄:${age}`);
}
// 受控组件,页面中输入类的值会实时保存在状态中,需要用的时候直接从状态中取
render() {
return (
<form onSubmit={this.handleSubmit}>
用户名:<input type="text" onChange={this.saveUsername} /><br />
性别:<input type="text" onChange={this.saveSex} /><br />
年龄:<input type="text" onChange={this.saveAge} /><br />
<button>登录</button>
</form>
);
}
}
ReactDOM.render(
<Person2 />,
document.getElementById('test2')
);
</script>
更多推荐


所有评论(0)