React用于构建用户界面的JavaScript库。
React由FaceBook开发的,并且已经开源。
babel的作用:
react.development.js 和 react-dom.development.js文件的作用:
1.引入react的三个核心文件
2.创建虚拟DOM,将虚拟DOM渲染到页面。
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello_reacttitle>
head>
<body>
<div id="test">div>
<script type="text/javascript" src="../js/react.development.js">script>
<script type="text/javascript" src="../js/react-dom.development.js">script>
<script type="text/javascript" src="../js/babel.min.js">script>
<script type="text/babel">
// 1.创建虚拟dom
const VDOM = <h1>Hello,React</h1>
// 2.渲染虚拟dom到页面
// ReactDOM是react-dom.development.js中的
// ReactDOM.render有两个参数:虚拟DOM 和 容器
ReactDOM.render(VDOM,document.getElementById('test'))
script>
body>
html>
document.createElement(tagName[, options]) 这是创建真实dom。
React.createElement(标签名,标签属性,标签内容) 这是创建虚拟dom。
第一种:js方式,通过React.createElement的方式创建虚拟dom。
第二种:jsx方式,通过babel将jsx转换成React.createElement的形式进而创建虚拟dom。
js判断一个数据的类型方式如下几种:
// js判断一个不认识的元素类型方式:
// 1.直接打印
console.log('虚拟dom',VDOM)
// 2.typeof来输出该元素类型
console.log(typeof VDOM)
// 3.使用instanceof来一个个进行判断
console.log(VDOM instanceof Object)
虚拟DOM:
1.定义虚拟DOM时,不要写引号。
const VDOM = (
<h2 id="itholmes">
<span>hello,react</span>
</h2>
)
ReactDOM.render(VDOM,document.getElementById('test'))
2.标签中混入JS表达式时要用{}。
const myId = 'IthoLmes111'
const myData = 'Hello,React'
const VDOM = (
// 这里将上面转换为了小写。
<h2 id={myId.toLowerCase()}>
<span>{myData.toLowerCase()}</span>
</h2>
)
3.虚拟DOM没有class,样式的类名指定要用className来指定样式。
<style>
.title{
background-color: red;
}
</style>
<!-- 准备好一个容器 -->
<div id="test"></div>
<script type="text/babel">
const myId = 'Itholmes111'
const myData = 'Hello,React'
// 虚拟DOM没有class,通过className来指定样式。
const VDOM = (
<h2 id={myId.toLowerCase()} className="title">
<span>{myData.toLowerCase()}</span>
</h2>
)
</script>
4.内联样式,要用style={{key:value}}的形式去写。
const VDOM = (
<h2 id={myId.toLowerCase()} className="title">
<span style={{color:'white',fontSize:'30px'}}>{myData.toLowerCase()}</span>
</h2>
)
5.jsx的虚拟DOM只能有一个根标签。
7.React的标签首字母。
将一个data数组中的数据渲染到页面上面:
<!-- 准备好一个容器 -->
<div id="test"></div>
<!-- fixme 引入是有顺序的! -->
<!-- 1. 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 2. 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 3. 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
// 将data数据渲染到页面
const data = ['Angular','React','Vue']
const VDOM = (
<div>
<h1>前端js框架列表</h1>
<ul>
{
// {} 只能写js表达式。
data.map((item,index)=>{
return <li key={index}>{item}</li>
})
}
</ul>
</div>
)
ReactDOM.render(VDOM,document.getElementById('test'))
</script>
我们写出的jsx文件,可以去babel官方转换成react:
函数式组件编程如下:
ReactDOM.render(<函数式组件名称/>…)的 执行过程:(重要!!)
注意:
<!-- 准备好一个容器 -->
<div id="test"></div>
<!-- fixme 引入是有顺序的! -->
<!-- 1. 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 2. 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 3. 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
// 1.创建函数式组件
function Demo(){
// 此处的this是undefined,因为babel编译后开启了es5的严格模式。
console.log(this)
return <h2>我是用函数定义的组件(适用于简单组件的定义)</h2>
}
// 2.渲染组件到页面
// 注意jsx语法,自定义的组件首字母必须大写!!
ReactDOM.render(<Demo/>,document.getElementById('test'))
</script>
1.类的构造函数 和 普通方法
<script type="text/javascript">
// 创建一个person类
class Person{
//构造器方法
constructor(name,age) {
// 构造器中的this是谁? - 类的实例对象就是下面的p1和p2。
this.name = name
this.age = age
}
// 一般方法 speak方法放在了哪里?- 类的原型对象上,供实例使用。
speak(){
// 通过Person实例调用speak时,speak中的this就是Person的实例(p1,p2)。
console.log(`我叫${this.name},我的年龄是${this.age}`)
}
}
// 创建一个Person的实例对象
const p1 = new Person('tom',18)
const p2 = new Person('jerry',19);
p1.speak()
p2.speak()
</script>
2.类的继承
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
<head>
<meta charset="UTF-8">
<title>类的基本知识</title>
</head>
<body>
<script type="text/javascript">
// 创建一个person类
class Person{
//构造器方法
constructor(name,age) {
// 构造器中的this是谁? - 类的实例对象就是下面的p1和p2。
this.name = name
this.age = age
}
// 一般方法 speak方法放在了哪里?- 类的原型对象上,供实例使用。
speak(){
// 通过Person实例调用speak时,speak中的this就是Person的实例(p1,p2)。
console.log(`我叫${this.name},我的年龄是${this.age}`)
}
}
class Student extends Person{
// Student默认是继承Person的构造函数
// 如果,Student也可以自己实现构造函数,顺序最好与父类相同!
constructor(name,age,grade) {
// 必须实现super()方法 ,并且super()必须最开始调用!
super(name,age);
this.grade = grade
}
spark(){
console.log(`我叫${this.name},我的年龄是${this.age},我的年级是${this.grade}`)
}
}
const s1 = new Student('小张',18)
console.log(s1)
</script>
</body>
</html>
3.通过实体类原型可以看到当前实体类对应的一系列类的信息:(包括构造方法、普通方法等等)
5.在类中可以直接写赋值语句,相当于给Car添加了属性(例如:a = 1 ,名为a,值为1)
React的类式组件满足以下几个条件:
<!-- 准备好一个容器 -->
<div id="test"></div>
<!-- 1. 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 2. 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 3. 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
// 1.创建类式组件 必须继承React.Component这个类!!
class MyComponent extends React.Component{
// 2.必须实现render函数
render(){
// 3.render函数必须要有返回值!!
return <h2>我是用类定义的组件(适用于[复杂组件]的定义)</h2>
}
}
ReactDOM.render(<MyComponent/>,document.getElementById('test'))
</script>
类式组件编程如下:
ReactDOM.render(<类式组件名称/>…)的 执行过程:(重要!!)
注意:类式组件其实是React内部创建了实例对象的,通过该实例对象调用render方法。
在这区分一下,简单组件和复杂组件,无状态的组件是简单组件;有状态的就是复杂组件。
这里的状态其实就是实现React.Component类的实例对象上的state。注意:并不是React.Component类上面的,而是实例对象上的!
对state状态的简单操作:
<script type="text/babel">
// 1.创建组件
class Weather extends React.Component{
// 必须创建构造器以及参数prop
constructor(prop) {
super(prop);
// 初始化状态
this.state = {isHot:true}
}
render() {
console.log(this)
// 读取状态,通过解构方式来展示。
const {isHot} = this.state
return (
<div>
<h1>
今天天气很{isHot ? '炎热' : '凉爽'}
</h1>
</div>
);
}
}
// 2.渲染组件到页面
ReactDOM.render(<Weather />,document.getElementById('test'))
</script>
注意以下几点:
1.onClick中间的字母C必须大写。
2.这里的方法demo不能添加括号,会将demo函数执行一边的返回值返回给onClick。
3.onClick要的是这个demo函数!!!
<script type="text/babel">
// 1.创建组件
class Weather extends React.Component{
constructor(prop) {
super(prop);
this.state = {isHot:true}
}
render() {
console.log(this)
// 通过解构方式来展示。
const {isHot} = this.state
return (
// 1.onClick中间的字母C必须大写。
// 2.这里的方法demo不能添加括号,会将demo函数执行一边的返回值返回给onClick。
// 3.onClick要的是这个demo函数!!!
<h1 onClick={demo}>
今天天气很{isHot ? '炎热' : '凉爽'}
</h1>
);
}
}
function demo(){
console.log('标题被点击了。')
}
// 2.渲染组件到页面
ReactDOM.render(<Weather />,document.getElementById('test'))
</script>
js的严格模式:
<script type="text/javascript">
// 当前的 demo和demo2 是全局window的一个函数。
function demo(){
// 开启严格模式。只在函数内使用严格模式
'use strict'
console.log(this)
}
function demo2(){
// 没有开启严格模式。
console.log(this)
}
// 因为开启了局部严格模式,所以外界调用会显示undefined。
demo()
// 没有开启严格模式,就可以直接调用! 打印出来是全局window对象。
demo2()
</script>
再者如下案例:
<script type="text/javascript">
class Person{
demo2(){
console.log(this)
}
}
let p = new Person()
p.demo2() // 打印Person{}对象
// 类中的方法默认是开启严格模式的!因此,这里的p2直接调用是不可以的!
let p2 = p.demo2
// p2调用的话是直接调用,并不是实例调用!
p2() // 打印undefined
</script>
严格模式的限制:
最重要重要的一点,严格模式的this指向:
function f(){
return !this;
}
// 返回false,因为"this"指向全局对象,"!this"就是false
function f(){
"use strict";
return !this;
}
// 返回true,因为严格模式下,this的值为undefined,所以"!this"为true。
function f(){
"use strict";
this.a = 1;
};
f();// 报错,this未定义
React的事件调用完全复刻了上面的操作,所以才会出现事件绑定后调用方法this为undefined的问题!
通过调用bind方法来解决方法this的指针问题。
constructor(prop) {
super(prop);
this.state = {isHot:true}
// 这里相当于给当前实例对象添加了一个经过bind方法加工后的changeWeather方法
this.changeWeather = this.changeWeather.bind(this)
}
js的bind方法使用:
<script type="text/javascript">
function demo(){
console.log(this)
}
// bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
// bind的作用:就是将demo函数复刻成一个新函数,并且将this替换成了指定的内容。
// x的this就变成了{a:1,b:2}。
const x = demo.bind({a:1,b:2})
console.log(x)
x()
</script>
所以就通过了bind方法来解决这个react类的this指向问题:
<!-- 准备好一个容器 -->
<div id="test"></div>
<!-- 1. 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 2. 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 3. 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
// 1.创建组件
class Weather extends React.Component{
constructor(prop) {
super(prop);
this.state = {isHot:true}
// 这里相当于给当前实例对象添加了一个经过bind方法加工后的changeWeather方法
this.changeWeather = this.changeWeather.bind(this)
}
render() {
const {isHot} = this.state
return (
<h1 onClick={this.changeWeather}>
今天天气很{isHot ? '炎热' : '凉爽'}
</h1>
);
}
changeWeather(){
console.log(this)
this.state.isHot = !this.state.isHot
}
}
// 2.渲染组件到页面
ReactDOM.render(<Weather />,document.getElementById('test'))
</script>
注意:状态state不可以直接更改,要借助一个内置的API去更改。
在React.Component类原型上面有一个setState方法。
必须通过setState进行修改更新。此外,setState的参数会合并到state,并不会替换,就不会影响其他属性。
<!-- 准备好一个容器 -->
<div id="test"></div>
<!-- 1. 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 2. 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 3. 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
// 1.创建组件
class Weather extends React.Component{
constructor(prop) {
super(prop);
this.state = {isHot:true,wind:'微风'}
// 这里相当于给当前实例对象添加了一个经过bind方法加工后的changeWeather方法
this.changeWeather = this.changeWeather.bind(this)
}
render() {
const {isHot,wind} = this.state
return (
<h1 onClick={this.changeWeather}>
今天天气很{isHot ? '炎热' : '凉爽'},{wind}
</h1>
);
}
changeWeather(){
let {isHot} = this.state
// 必须通过setState进行修改更新。此外,这里的参数会合并到state,并不会替换,就不会影响其他属性。
this.setState({isHot:!isHot})
}
}
// 2.渲染组件到页面
ReactDOM.render(<Weather />,document.getElementById('test'))
</script>
总结起来:
因为类可以直接写赋值语句。所以我们就可以直接写成赋值语句来简写。
注意:函数赋值必须要使用箭头函数,使其this指向实例对象。
通过这种方式就没必要创建constructor构造器了。
<script type="text/babel">
// 1.创建组件
class Weather extends React.Component{
// 类中可以直接写赋值语句,转为当前this的属性。
state = {isHot:true,wind:'微风'}
// 这里必须要使用箭头函数,让this指向外侧的this,也就是实例对象!
changeWeather = () => {
let {isHot} = this.state
this.setState({isHot:!isHot})
}
render() {
const {isHot,wind} = this.state
return (
<h1 onClick={this.changeWeather}>
今天天气很{isHot ? '炎热' : '凉爽'},{wind}
</h1>
);
}
}
// 2.渲染组件到页面
ReactDOM.render(<Weather />,document.getElementById('test'))
</script>