一、虚拟DOM和真实DOM
<script type="text/babel">
const VDOM = (
<h1 id="title">
<span>Hello, React!</span>
</h1>
)
ReactDOM.render(VDOM, document.getElementById('box'))
const TDOM = document.getElementById('test')
console.log('虚拟DOM', VDOM)
console.log('真实DOM', TDOM)
debugger;
</script>
关于虚拟DOM:
- 本质是Object对象(一般对象)
- 虚拟DOM比较“轻”(属性和方法少),真实DOM比较“重”(属性和方法多),因为虚拟DOM是React内部在用,无需真实DOM上那么多属性
- 虚拟DOM最终都会被React转换为真实DOM,最终呈现在页面。
二、jsx的语法规则
- 定义虚拟DOM时,不要用引号
- 标签中混入js表达式时,使用{}
- 样式的类名指定不能用class,要使用className,因为要与es6中的关键字类(class)做区分
- 内联样式,要使用{{key:value}}的形式去写,外层{}表示里边的内容为js,内层{}表示对象
- 只能有一个根标签
- 标签必须闭合
- 标签首字母:
1)首字母小写开头,则将该标签转为html中的同名元素,若html中无与之对应的同名元素,则报红色警告
2)首字母大写开头,react会去渲染对应的组件,若组件没有定义,则报错。
<script type="text/babel">
const myId = 'container'
const myData = 'Hello, React'
const VDOM = (
<div>
<h1 className="title" id={myId}>
<span style={{color: 'white'}}>{myData}</span>
</h1>
<h1 className="title" id={myId+'2'}>
<span style={{color: 'white'}}>{myData}</span>
</h1>
<good>222</good>
</div>
)
ReactDOM.render(VDOM, document.getElementById('box'))
</script>
三、组件实例的三大属性
- state
<script type="text/babel">
class Weather extends React.Component {
constructor(props) {
console.log('constructor')
super(props)
this.state = {isHot: false, wind: '微风'}
this.changeWeather = this.changeWeather.bind(this)
}
render() {
console.log('render')
let {isHot, wind} = this.state
return <h1 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '寒冷'},{wind}</h1>
}
changeWeather() {
console.log('changeWeather')
const isHot = this.state.isHot
this.setState({isHot: !isHot})
}
}
ReactDOM.render(<Weather/>, document.getElementById('box'))
</script>
简写方式
<script type="text/babel">
class Weather extends React.Component {
state = {isHot: false, wind: '微风'}
render() {
let {isHot, wind} = this.state
return <h1 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '寒冷'},{wind}</h1>
}
changeWeather = () => {
const isHot = this.state.isHot
this.setState({isHot: !isHot})
}
}
ReactDOM.render(<Weather/>, document.getElementById('box'))
</script>
- props
<script type="text/babel">
class Person extends React.Component {
render() {
const {name, age, gender} = this.props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{age}</li>
<li>年龄:{gender}</li>
</ul>
)
}
}
ReactDOM.render(<Person name="tom" age="28" gender="男"/>, document.getElementById('box1'))
const p = {name: 'daisy', age: '21', gender: "女"}
ReactDOM.render(<Person {...p}/>, document.getElementById('box2'))
</script>
简写方式
<script type="text/babel">
class Person extends React.Component {
static propTypes = {
name: PropTypes.string.isRequired,
age: PropTypes.number,
gender: PropTypes.string,
}
static defaultProps= {
age: 10,
gender: '男'
}
render() {
const {name, age, gender} = this.props
return (
<ul>
<li>姓名:{name}</li>
<li>年龄:{age + 1}</li>
<li>性别:{gender}</li>
</ul>
)
}
}
ReactDOM.render(<Person name="tom"/>, document.getElementById('box1'))
</script>
函数式组件使用props
<script type="text/babel">
function Person(props) {
const {name, age, gender} = props
return (
<ul>
<li>姓名:{name}</li>
<li>年龄:{age + 1}</li>
<li>性别:{gender}</li>
</ul>
)
}
Person.propTypes = {
name: PropTypes.string.isRequired,
age: PropTypes.number,
gender: PropTypes.string,
}
Person.defaultProps= {
age: 10,
gender: '男'
}
ReactDOM.render(<Person name="tom"/>, document.getElementById('box1'))
</script>
- ref
<script type="text/babel">
class Demo extends React.Component{
myRef = React.createRef()
myRef2 = React.createRef()
showData = () => {
alert(this.myRef.current.value)
}
showData2 = () => {
alert(this.myRef2.current.value)
}
render() {
return (
<div>
<input ref={this.myRef} type="text" placeholder="点击按钮提示数据" />
<button onClick={this.showData}>点我提示左侧数据</button>
<input ref={this.myRef2} type="text" placeholder="失去焦点提示数据" onBlur={this.showData2}/>
</div>
)
}
}
ReactDOM.render(<Demo/>, document.getElementById('box'))
</script>
四、事件处理
<script type="text/babel">
class Demo extends React.Component{
myRef = React.createRef()
myRef2 = React.createRef()
showData = () => {
alert(this.myRef.current.value)
}
showData2 = (event) => {
alert(event.target.value)
}
render() {
return (
<div>
<input ref={this.myRef} type="text" placeholder="点击按钮提示数据" />
<button onClick={this.showData}>点我提示左侧数据</button>
<input type="text" placeholder="失去焦点提示数据" onBlur={this.showData2}/>
</div>
)
}
}
ReactDOM.render(<Demo/>, document.getElementById('box'))
</script>
事件处理总结:
- 通过onXxx属性指定事件处理函数(注意大小写)
a)React使用的是自定义(合成)事件,而不是使用的原生DOM事件 ----为了更好的兼容性
b)React中的事件是通过事件委托方式处理的(委托给组件最外层的元素) ---- 为了更高效 - 通过event.target得到发生事件的DOM元素对象 ---- 不要过度使用ref
五、组件的生命周期(详细代码在下一篇笔记)
旧版与新版对比图示:

附:使用html学习React基础代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>demo</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="box"></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="https://unpkg.com/react@16/umd/react.development.js"></script>
<!-- 引入react扩展库 -->
<script type="text/javascript" src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转换为js -->
<script type="text/javascript" src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<!-- 引入prop-types,用于对组件标签的限制 -->
<script type="text/javascript" src="../../../js/prop-types/prop-types.js"></script>
<script type="text/babel">
</script>
</body>
</html>