React
概述
- 英文官网: https://reactjs.org/
- 中文官网: https://doc.react-china.org/
特点
- Declarative(声明式编码)
- Component-Based(组件化编码)
- Learn Once, Write Anywhere(支持客户端与服务器渲染)
- 高效
- 单向数据流
基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>基本使用</title>
</head>
<body>
<div id="test"></div>
<script src="./js/react.development.js"></script>
<script src="./js/react-dom.development.js"></script>
<script src="./js/babel.min.js"></script>
<script type="text/babel">
//创建虚拟DOM元素对象
var vDom = <h1>111</h1>
//将虚拟DOM渲染到页面真实DOM容器中
ReactDOM.render(vDom,document.getElementById('test'))
</script>
</body>
</html>
相关js库
- react.js: React的核心库
- react-dom.js: 提供操作DOM的react扩展库
- babel.min.js: 解析JSX语法代码转为纯JS语法代码的库
虚拟DOM
- React提供了一些API来创建一种
特别
的一般js对象- var element = React.createElement(‘h1’, {id:‘myTitle’},‘hello’)
- 上面创建的就是一个简单的虚拟DOM对象
- 虚拟DOM对象最终都会被React转换为真实的DOM
- 编码时基本只需要操作react的虚拟DOM相关数据, react会转换为真实DOM变化而更新界面
JSX
-
react定义的一种类似于XML的JS扩展语法: XML+JS
-
作用: 用来创建react虚拟DOM(元素)对象
- var ele =
Hello JSX!
- 注意1: 它不是字符串, 也不是HTML/XML标签
- 注意2: 它最终产生的就是一个JS对象
- var ele =
-
标签名任意: HTML标签或其它标签
-
标签属性任意: HTML标签属性或其它
-
基本语法规则
-
遇到 <开头的代码, 以标签的语法解析: html同名标签转换为html同名元素, 其它标签需要特别解析
-
遇到以 { 开头的代码,以JS语法解析: 标签中的js代码必须用{ }包含
-
babel.js的作用
-
浏览器不能直接解析JSX代码, 需要babel转译为纯JS的代码才能运行
-
只要用了JSX,都要加上type=“text/babel”, 声明需要babel来处理
<h1>jsx练习</h1>
<div id="test"></div>
<script src="./js/react.development.js"></script>
<script src="./js/react-dom.development.js"></script>
<script src="./js/babel.min.js"></script>
<script type="text/babel">
const names = ['111','222','333','444']
//创建虚拟DOM元素对象
const ul = (
<ul>
{
names.map((name,index) => <li key={index}>{name}</li>)
}
</ul>
)
//将虚拟DOM渲染到页面真实DOM容器中
ReactDOM.render(ul,document.getElementById('test'))
</script>
模块与组件和模块化与组件化的理解
模块
- 理解- 向外提供特定功能的js程序, 一般就是一个js文件
- 作用 - 复用js, 简化js的编写, 提高js运行效率
组件
- 理解 - 用来实现特定(局部)功能效果的代码集合(html/css/js)
- 作用 - 复用编码, 简化项目编码, 提高运行效率
模块化
当应用的js都以模块来编写的,这个应用就是一个模块化的应用
组件化
当应用是以多组件的方式实现,这个应用就是一个组件化的应用
React面向组件编程
基本理解和使用
<div id="test"></div>
<div id="test1"></div>
<script src="./js/react.development.js"></script>
<script src="./js/react-dom.development.js"></script>
<script src="./js/babel.min.js"></script>
<script type="text/babel">
//定义组件
//方式1 - 工厂函数组件(简单组件)
function MyComponent(){
return <h2>1111</h2>
}
//方式2 - ES6组件(复杂组件)
class MyComponent2 extends React.Component{
render(){
return <h2>2222</h2>
}
}
//进行组件渲染
ReactDOM.render(<MyComponent />,document.getElementById('test'))
ReactDOM.render(<MyComponent2 />,document.getElementById("test1"))
</script>
- 注意
- 组件名必须首字母大写
- 虚拟DOM元素只能有一个根元素
- 虚拟DOM元素必须有结束标签
- render()渲染组件标签的基本流程
- React内部会创建组件实例对象
- 得到包含的虚拟DOM并解析为真实DOM
- 插入到指定的页面元素内部
组件三大属性state
<div id="test"></div>
<script src="./js/react.development.js"></script>
<script src="./js/react-dom.development.js"></script>
<script src="./js/babel.min.js"></script>
<script type="text/babel">
//定义组件
class Like extends React.Component{
constructor(prop){
super(prop)
//初始化状态
this.state = {
isLikeME:false
}
//将新增方法中的this强制绑定为数组对象
this.handleClick = this.handleClick.bind(this)
}
//新增加方法 - 内部的this默认不是组件对象,而是undefined
handleClick(){
//得到状态并取反
const isLikeME = !this.isLikeME
//更新状态
this.setState({isLikeME})
}
//重写组件类的方法
render(){
//读取状态
const {isLikeME} = this.state
//绑定时间
return <h2 onClick={this.handleClick}>{isLikeME? '1111':'2222'}</h2>
}
}
//渲染组件标签
ReactDOM.render(<Like />,document.getElementById('test'))
</script>
- 理解
- state是组件对象最重要的属性, 值是对象(可以包含多个数据)
- 组件被称为"状态机", 通过更新组件的state来更新对应的页面显示(重新渲染组件)
组件三大属性props
<div id="test"></div>
<div id="test1"></div>
<script src="./js/react.development.js"></script>
<script src="./js/react-dom.development.js"></script>
<script src="./js/prop-types.js"></script>
<script src="./js/babel.min.js"></script>
<script type="text/babel">
//定义组件
function Person(props){
return(
<ul>
<li>姓名:{props.name}</li>
<li>年龄:{props.age}</li>
<li>性别:{props.sex}</li>
</ul>
)
}
//指定默认值
Person.defaultProps = {
sex:'男',
age:20
}
//指定属性值的类型的必要性
Person.propTypes = {
name:PropTypes.string.isRequired,
age:PropTypes.number
}
//渲染组件标签
const p1 = {
name:'Tom',
age:10,
sex:'女'
}
// ReactDOM.render(<Person name={p1.name} age={p1.age} sex={p1.sex}/>,document.getElementById('test'))
ReactDOM.render(<Person {...p1}/>,document.getElementById('test'))
const p2 = {
name:'Jack'
}
ReactDOM.render(<Person name={p2.name} age={30}/>,document.getElementById('test1'))
</script>
- 理解
- 每个组件对象都会有props(properties的简写)属性
- 组件标签的所有属性都保存在props中
- 作用
- 通过标签属性从组件外向组件内传递变化的数据
- 注意: 组件内部不要修改props数据
组件三大属性refs属性
<div id="test"></div>
<script src="./js/react.development.js"></script>
<script src="./js/react-dom.development.js"></script>
<script src="./js/babel.min.js"></script>
<script type="text/babel">
//定义组件
class MyDemo extends React.Component{
constructor(props){
super(props)
this.showInput = this.showInput.bind(this)
this.handleBluer = this.handleBluer.bind(this)
}
showInput(){
const input = this.refs.content
//alert(input.value)
alert(this.input.value)
}
handleBluer(event){
alert(event.target.value)
}
render(){
return(
<div>
<input type="text" ref="content" />
<input type="text" ref={input => this.input = input} />
<button onClick={this.showInput}>提示输出</button>
<input type="text" placeholder="失去焦点" onBlur={this.handleBluer}/>
</div>
)
}
}
//渲染组件标签
ReactDOM.render(<MyDemo />,document.getElementById('test'))
</script>
-
组件内的标签都可以定义ref属性来标识自己
-
<input type=“text” ref={input => this.msgInput = input}/>
-
回调函数在组件初始化渲染完或卸载时自动调用
-
在组件中可以通过this.msgInput来得到对应的真实DOM元素
-
作用: 通过ref获取组件内容特定标签对象, 进行读取其相关数据
-
注意事项
- 组件内置的方法中的this为组件对象
- 在组件类中自定义的方法中this为null
- 强制绑定this: 通过函数对象的bind()
- 箭头函数(ES6模块化编码时才能使用)
组件的组合
-
拆分组件: 拆分界面,抽取组件
-
实现静态组件: 使用组件实现静态页面效果
-
实现动态组件
- 动态显示初始化数据
- 交互功能(从绑定事件监听开始)
<div id="test"></div> <script src="./js/react.development.js"></script> <script src="./js/react-dom.development.js"></script> <script src="./js/prop-types.js"></script> <script src="./js/babel.min.js"></script> <script type="text/babel"> class App extends React.Component{ constructor(props){ super(props) //初始化状态 this.state = { todos:['你好','下午好','晚上好'] } this.addTodo = this.addTodo.bind(this) } addTodo(todo){ //this.state.todos.unshift(todo) const {todos} = this.state todos.unshift(todo) //更新状态 this.setState({todos}) } render(){ const {todos} = this.state return( <div> <h1>Simple TODO List</h1> <Add count={todos.length} addTodo={this.addTodo}/> <List todos={todos}/> </div> ) } } class Add extends React.Component{ constructor(props){ super(props) this.add = this.add.bind(this) } add(){ //读取输入的数据 const todo = this.todoTnput.value.trim() //检查合法性 if(!todo){ return } //添加 this.props.addTodo(todo) //清除输入 this.todoTnput.value