1.React是什么?
- React是由Facebook 开源的一个JS库
- 官方解释:React是一个声明式,高效且灵活的用于构建用户界面的JavaScript库
A JavaScript library for building user interfaces .
2.React的特点
声明式编程
-
什么是声明式编程:
-
它描述目标的性质,让电脑明白目标,而非流程
-
声明式编程是告诉计算机需要计算"什么",而不是"如何" 去计算
-
-
前端开发模式:
-
声明式编程是目前整个大前端的开发的模式:Vue、React、Flutter
-
它允许我们只需要维护自己的状态
-
当状态改变的时候,React可以根据最新的状态去渲染我们的ui界面
-
-
ui = f (state)
-
ui : the layout on the screen
-
f: the build method
-
state: the app state
-
组件化开发
-
组件是React中重要思想
- 它提供了一种抽象,我们可以开发出一个独立可复用的小组件来构造我们的应用
-
组件化思想应用
-
有了组件化的思想,尽可能将页面拆分成一个个小的,可复用的组件
-
这样让我们代码更方便组织和管理,并且扩展性也强
-
多平台适配
- 2013年,React发布之初主要是开发Web页面
- 2015年,Facebook推出了ReactNative,用于开发移动端跨平台(RN)
- 2017年,Facebook推出ReactVR,用于开发虚拟现实Web应用程序
3.React 开发依赖
-
开发React必须依赖这三个库
-
react: 包含react所必须的核心代码
-
react-dom:react渲染不同平台所需要的核心代码
-
babel:将jsx转换成react代码的工具
-
-
React为什么要依赖这三个库:
- 其实, 这三个库是各司其职, 目就是让每一个库单纯做自己的事情
- 为什么要进行拆分呢?
- react中包含了 react 和 react-native 所共同拥有的核心代码
-
react-dom
针对 web 和 native 所完成的事情不同:- web端:
react-dom
会将jsx
最终渲染成真实的DOM
, 显示在浏览器中 - native端:
react-dom
会将jsx
最终渲染成原生的控件 (比如Android中的Butto, iOS中的UIButton)
- web端:
4.认识Bable
-
babel是什么:
- 是目前前端使用非常广泛的编译器、转码器
- 可以将ES6代码转为ES5代码,从而在现有环境执行
-
React
和Babel
的关系:- 默认情况下
React
其实可以不用babel
- 但前提是我们使用
React.createElement
来编写源代码, 它编写的代码非常繁琐可读性差 - 我们就可以直接编写jsx(JavaScript XML)的语法,并且让babel帮助我们转换成
React.createElement
- 默认情况下
5.Hello React 案例
- 在界面上显示文本:hello world
- 点击下方的一个按钮,点击后文本变成hello react
使用react之前,先用原生代码实现,与react进行对比
<body>
<h2 class="title">Hello World</h2>
<button class="btn">改变文本</button>
<script>
// 1.定义数据
let message = "Hello World";
// 2.将数据显示在h2元素中
const titleEl = document.getElementsByClassName("title")[0];
titleEl.innerHTML = message;
// 3.点击按钮 界面的数据发生改变
const btnEl = document.getElementsByClassName("btn")[0];
btnEl.addEventListener("click", (e) => {
message = "Hello React";
titleEl.innerHTML = message;
console.log("按钮发生了点击")
});
</script>
</body>
引入React依赖
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<body>
<div id="app"></div>
<!-- 使用jsx 并且希望script中的jsx代码被解析,必须在script标签中添加一个属性 -->
<script type="text/babel">
// 1.渲染的内容
let message = "Hello World"
// 2.挂载的对象
ReactDOM.render(<h2>{message}</h2>, document.getElementById("app"));
</script>
</body>
-
React.render
函数- 参数一: 要渲染的内容, 可以是HTML元素, 也可以是React的组件
- 参数二: 将渲染的内容, 挂载到哪一个HTML元素上
-
我们可以通过
{}
语法来引入外部的变量或者表达式 -
按钮发生点击
<body>
<div id="app">app</div>
<!-- 使用jsx 并且希望script中的jsx代码被解析,必须在script标签中添加一个属性 -->
<!-- jsx特点: 多个标签(组件) 在最外层(根)只能有一个标签 -->
<script type="text/babel">
// 1.渲染的内容
// 2.挂载的对象
let message = "Hello World";
function btnClick() {
message = "Hello React";
console.log(message); // 数据改变了 但是没有重新渲染函数
// 这样ui就会进行改变了
render();
}
function render() {
ReactDOM.render(
<div>
<h2>{message}</h2>
<button onClick={btnClick}>修改文本</button>
</div>,
document.getElementById("app")
);
}
// 默认要先执行一次render函数
render();
</script>
</body>
react组件化开发
-
整个逻辑可以看成一个整体,那么我们就可以将其封装成一个组件
-
ReactDOM.render 第一个参数式一个html元素或者一个组件
-
所以我们可以先将之前的业务逻辑封装到一个组件中,然后传入到
ReactDOM.render
函数中的第一个参数
-
-
这里暂时使用类的方式封装组件:
- 定义一个类 (类名大写, 组件的名称是必须大写的, 小写会被认为是HTML元素),继承自
React.Component
- 实现当前组件的
render
函数render
当中返回的jsx
内容,就是之后React会帮助我们渲染的内容
- 定义一个类 (类名大写, 组件的名称是必须大写的, 小写会被认为是HTML元素),继承自
//封装APP组件
class App extends React.Component {
render(){
return (<div>hello</div>)
}
}
// 渲染组件
ReactDOM.render(<App/>, document.getElementById ('app')
<body>
<div id="app">app</div>
<!-- 使用jsx 并且希望script中的jsx代码被解析,必须在script标签中添加一个属性 -->
<!-- jsx特点: 多个标签(组件) 在最外层(根)只能有一个标签 -->
<script type="text/babel">
// 封装一个组件
// 函数式组件
function App() {}
// class 组件
class App extends React.Component {
// es6 类中定义属性
constructor() {
super(); // 初始化父类实例
// this.message = "Hello World"; / jsx 依赖了一个数据 并且当这个数据发生改变的时候,希望界面也发生改变
// 不能定义在当前对象的里面 应该定义在state中
this.state = {
message: "Hello World",
};
}
btnClick() {
this.setState({ // 内部会重新调用render函数
message: "Hello React",
});
this.state.message = "hello React" // 不会更改 数据改变了 但是视图没有改变 因为没有调用render函数
// this.message = "Hello React"; // this is undefined 内部调用btnClick.apply(undefined,xxx)
}
render() { // render 不会手动调用 被 react 调用进行重新渲染
return (
<div>
<h2>{this.state.message}</h2>
<button onClick={this.btnClick.bind(this)}>改变文本</button>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("app"));
</script>
</body>
组件化-数据依赖
-
在组件中的数据,我们可以分成两类:
- 参与界面更新的数据:当数据变量时,需要更新组件渲染的内容
- 不参与界面更新的数据:当数据变量时,不需要更新将组建渲染的内容
-
参与界面更新的数据,是定义在当前对象的
state
属性中-
我们通过在构造函数中:
this.state = {定义的数据}
-
当我们的数据发生变化时,我们调用
this.setState
来更新数据,并且通知React进行update操作- 在进行update操作时,就会重新调用render函数, 并且使用最新的数据,来渲染界面
-
class App extends React.Component {
constructor() {
super();
//定义数据
this.state = {
message: 'hello world'
}
}
// 使用数据
render() {
return (
<div>
<h2>{this.state.message}</h2>
</div>
)
}
}
组件化-事件绑定
-
React中事件绑定: 在标签中定义
on + 事件名
- 例如:
<button onClick={this.changeText}>改变文本</button>
- 例如:
-
当前这个函数的this指向的是谁呢?
- 默认情况下是 undefined
- 这次因为React并不是直接渲染成真实的DOM, 我们所编写的button只是一个语法糖, 它的本质React的Element对象
- 那么在这里发生监听的时候,react给我们的函数绑定的
this
,默认情况下就是一个undefined
-
我们在绑定的函数中,可能想要使用当前对象,比如执行
this.setState
函数,就必须拿到当前对象的this- 我们就需要在调用函数时,给这个函数直接绑定this
<button onClick={this.changeText.bind(this)}>改变文本</button>