
刚开始不会直接使用组件化进行开发,因此需要引入在线的几个js库
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script><script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script><script crossorigin src="https://cdn.bootcss.com/prop-types/15.6.1/prop-types.js"></script><script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
基础知识
虚拟DOM
由于React使用jsx的语法,因此我们编写的代码需要通过babel的翻译成js,因此type要写成text/babel
<script type="text/babel"></script>
比如,我们可以这样创建一个虚拟的DOM
const VDOM = <h1>Hello,React</h1>ReactDOM.render(VDOM, document.getElementById("app"))
当我们的虚拟DOM有多层结构的时候,需要统一由一个父标签所包裹,如下所示:
const VDOM = (<div><div>Hello</div><div>World</div></div>)ReactDOM.render(VDOM,document.querySelector('.test'))
JSX语法
- 定义虚拟DOM的时候,不能使用
""进行包裹(创建的是虚拟DOM而不是字符串) - 标签中如果需要混入
js表达式,那么需要使用{}包裹 - 样式的类名指定不能使用
class,而要用className - 元素的style样式要使用
{{}}包裹 - 对于一个虚拟DOM来说,有且仅有一个根标签
 - 标签必须闭合,自闭合也可以
 - 如果标签是小写字母开头,那么就转化为原生
html中的同名元素,如果找不到,则报错;如果是大写字母开头,则去找对应的组件,找不到就报错JSX小练习
根据动态数据渲染列表(对数据使用map函数)const data = ['A','B','C']const VDOM = (<div><ul>{data.map((item,index)=>{return <li key={index}>{item}</li>})}</ul></div>)ReactDOM.render(VDOM,document.querySelector('.test'))
组件化
同Vue一样,React中也是可以将某个部分拆分成某个独立的组件,进行组件化开发函数式组件
定义一个函数,并且接收一个可选的**props**参数不是所有的组件都会从外界接受参数,因此
props参数是可选的 
function MyList(props) {return <div>name: {props.name}</div>}ReactDOM.Render(<Welcom name="yxr" />,document.getElementById("app"));
类式组件
如果使用类式组件,那么对
JavaScript的运用本领提出了一定的要求,主要是this的指向问题

最后的优化结果如下
class MyList extends React.Component {state = {isHot: false}render() {const {isHot} = this.state;return <h1 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉快'}</h1>}changeWeather = () => {const {isHot} = this.state;this.setState({isHot: !isHot})}}
在学习的过程中,发现这一块涉及到
js面向对象的部分还是蛮多的,并且有些复杂
- 第一版本:对
state的使用出错 

打开浏览器,发现控制台报错,不能直接对state中的值进行修改
而是要用React给我们提供的方法进行修改:
- 第二版本:方法绑定出错
 
这一部分,由于涉及到this指向的问题,稍微有些难度
现在假设我们有如下所示的代码
class Person {constructor(name) {this.name = name;}say() {// console.log("Hello,World");console.log(this);}}let p = new Person('Tom');let fun = p.say;p.say();fun();
我们将实例P上的say()方法赋值给了fun变量,并进行调用,在js的严格模式下,输出如下结果:
也就是说,只有当我们通过某个类的实例调用类中的方法时,this的指向才指向实例本身
如果通过上述这种方式进行调用,则this的指向为undefined
同理,我们现在将代码修改成如下图片所示
相当于将
click方法赋值给了某个变量,并交由onClick调用
如果看明白上面的描述,那么你应该知道,这种写法会出错,并报undefined异常
原因是我们的click方法中,调用了this
如何处理这种this指向的问题?有如下两种方式
- 绑定this
 
在我们的构造函数中,调用bind方法,绑定this的指向
但假如我们有很多的方法,那么就需要很多个绑定处理,不够优雅
- 使用箭头函数
 
与普通函数不同的是,箭头函数本身不具有this,因此他会找到外面一级,并将this指向它
我们修改上述示例js中的代码,如下所示:
由于箭头函数的特性,我们不难分析到,两次函数调用输出的结果应该是一样的,都是指向实例本身:
因此,我们可以将上述React代码改写:
- 第三版本:没有分清楚赋值和调用
 
如下所示,上面的是将函数的返回值绑定给onClick,而下面是将函数本身绑定给onClick
但假如我们想使用调用的那种方式,就需要使用高阶函数,如下所示:
受控组件和非受控组件
在
React中,数据是单向的,而不是像vue中的双向数据绑定 因此组件也分成了:受控组件和非受控组件两种
- 受控组件:表单组件的输入组件随着输入的变化,将内容存储到状态中
 - 非受控组件:表单组件的输入组件的内容在有需求的时候,才存储到状态中
受控组件
监听输入类组件的数据变化,并不断存储到状态中
非受控组件
只有在需要的时候,才写入到状态中
在React中,更推荐使用受控组件组件实例的三大属性
state
React 把组件看成是一个状态机(State Machines)。通过与用户的交互,实现不同状态,然后渲染 UI,让用户界面和数据保持一致。 React 里,只需更新组件的 state,然后根据新的 state 重新渲染用户界面(不要操作 DOM)。
 
对写法进行简化,我们不再在构造函数中初始化状态,而是直接作为属性写入
并且,在React中,并不能直接修改state中的值来重新渲染页面中的内容,而是要用给我们提供好的setState方法
this.setState(partialState, [callback]);
有如下两种写法:
写法1:
this.setState({weather: "凉爽"})
写法2:
this.setState((state) => {return {count: state.count + 1,};});
setState操作是合并操作,而不是替换操作render()的执行次数是1+n(每一次的setState都会自动调用一次render)props
与state不同的是,state是组件自身自带的状态,而props是外界传递给组件的值
- 通过在组件标签上传递值,在组件中就可以获取到所传递的值
 - 在构造器里的props参数里可以获取到 props
 - 可以分别设置 propTypes 和 defaultProps 两个属性来分别操作 props的规范和默认值,两者都是直接添加在类式组件的原型对象上的(所以需要添加 static)
 - 同时可以通过…运算符来简化
 
refs
同vue中的refs一样,React提供了一种方式,允许我们访问DOM节点或者在render方法中创建的React元素
不用再使用
document.getElementById()这样的方法来获取的DOM节点了
一共有三种创建refs的方法,分别是:
- 字符串形式
 - 回调形式
 createRef形式
字符串形式
虽然目前这种方法因为性能问题已经被废弃,但是临时使用一下还是很方便的
回调形式
createRef形式

