目前对于前端开发来说,几乎很少直接使用原生的JavaScript
来开发应用程序,而是选择一个JavaScript库(框架)
。
jQuery
是被使用最多的JavaScript
库65%
使用了jQuery
,是当时最受欢迎的JavaScript
库,但是,目前甚至已经处于淘汰的边缘了而无论是国内外,最流行的其实是三大框架:Vue、React、Angular
,如下:
框架Google指数对比:
NPM下载量对比:
Github数据对比:
React
由Facebook
来更新和维护,它是大量优秀程序员的思想结晶:
React
的流行不仅仅局限于普通开发工程师对它的认可;React
的思想;Vue.js
框架设计之初,有很多的灵感来自Angular和React
。
Vue3
很多新的特性,也是借鉴和学习了React
React Hooks
是开创性的新功能Vue Composition API
学习了React Hooks
的思想Flutter
的很多灵感都来自React
:
Flutter中的Widget – Element – RenderObject
React的就是JSX – 虚拟DOM – 真实DOM
所以React可以说是前端的先驱者,它总是会引领整个前端的潮流。
React
发布之初主要是开发Web
页面;Facebook
推出了ReactNative
,用于开发移动端跨平台Facebook
推出ReactVR
,用于开发虚拟现实Web应用程序开发React
必须依赖三个库:
react
:包含react
所必须的核心代码 react-dom
:react
渲染在不同平台所需要的核心代码babel
:将jsx
转换成React
代码的工具第一次接触React
会被它繁琐的依赖搞蒙,居然依赖这么多东西:
Vue
来说,我们只是依赖一个vue.js
文件即可,但是react
居然要依赖三个包React
的0.14
版本之前是没有react-dom
这个概念的,所有功能都包含在react
里;为什么要进行拆分呢?原因就是react-native
。
react
包中包含了react web
和react-native
所共同拥有的核心代码。react-dom
针对web
和native
所完成的事情不同:web端
:react-dom
会将jsx
最终渲染成真实的DOM
,显示在浏览器中native端
:react-dom
会将jsx
最终渲染成原生的控件(比如Android中的Button,iOS中的UIButton)
Babel是什么呢?
Babel
又名 Babel.js
ES6
的语法,但是确实ES6
的语法非常的简洁和方便,我们开发时希望使用它ES6
来编写,之后通过Babel
工具,将ES6
转成大多数浏览器都支持的ES5
的语法React和Babel的关系:
React
其实可以不使用babel
React.createElement
来编写源代码,它编写的代码非常的繁琐和可读性差jsx(JavaScript XML)
的语法,并且让babel
帮助我们转换成React.createElement
所以,我们在编写React
代码时,这三个依赖都是必不可少的。
那么,如何添加这三个依赖:
CDN
引入npm
管理(后续脚手架再使用)◼ 暂时我们直接通过CDN
引入,来完成示例程序
ps: 这里有一个crossorigin的属性,这个属性的目的是为了拿到跨域脚本的错误信息
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
在界面上通过React
显示一个Hello World
,代码如下:
<body>
<div id="root">div>
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin>script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin>script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js">script>
<script type="text/babel">
// ReactDOM.render(Hello World
, document.querySelector('.root'))
const root = ReactDOM.createRoot(document.querySelector('#root'))
root.render(<h2>Hello React18</h2>)
script>
body>
ReactDOM.createRoot
函数:用于创建一个React
根,之后渲染的内容会包含在这个根中
HTML
元素上,这里我们已经提定义一个id为app的div{}
语法来引入外部的变量或者表达式React
的script
代码中,必须添加 type="text/babel"
,作用是可以让babel
解析jsx
的语法。新增按钮,点击后修改message
的值,代码如下:
<div id="root">div>
<script type="text/babel">
let message = 'hello world'
const root = ReactDOM.createRoot(document.querySelector("#root"))
function changeMessage(){
message = 'hello react'
root.render(
<div>
<h2>{message}</h2>
<button onClick={changeMessage}>点我</button>
</div>
)
}
root.render(
<div>
<h2>{message}</h2>
<button onClick={changeMessage}>点我</button>
</div>
)
script>
整个逻辑其实可以看做一个整体,那么我们就可以将其封装成一个组件:
root.render
参数是一个HTML
元素或者一个组件ReactDOM.render
函数中的第一个参数在React
中,如何封装一个组件呢?这里我们暂时使用类的方式封装组件:
HTML
元素),继承自React.Component
render
当中返回的jsx
内容,就是之后React
会帮助我们渲染的内容在组件中的数据,我们可以分成两类:
参与界面更新的数据我们也可以称之为是参与数据流
,这个数据是定义在当前对象的state
中
this.state = {定义的数据}
this.setState
来更新数据,并且通知Reac
进行update
操作update
操作时,就会重新调用render
函数,并且使用最新的数据,来渲染界面事件绑定中的this
===>在类中直接定义一个函数,并且将这个函数绑定到元素的onClick事件上,当前这个函数的this
指向的是谁呢?
默认情况下是undefined
undefined
DOM
操作中,监听点击,监听函数中的this
其实是节点对象(比如说是button
对象)React
并不是直接渲染成真实的DOM
,我们所编写的button
只是一个语法糖,它的本质React的Element
对象;react
在执行函数时并没有绑定this
,默认情况下就是一个undefined
this.setState
函数,就必须拿到当前对象的this
this
类似于下面的写法:
当然也可以在组件的构造函数中对方法进行绑定,如下:
<script type="text/babel">
// 编写React代码(jsx语法)
// jsx语法 -> 普通的JavaScript代码 -> babel
// 渲染Hello World
// React18之前: ReactDOM.render
ReactDOM.render(<h2>Hello World</h2>, document.querySelector("#root"))
// React18之后:
const root = ReactDOM.createRoot(document.querySelector("#root"))
root.render(<h2>Hello World</h2>)
script>
<body>
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin>script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin>script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js">script>
<div id="root">div>
<script type="text/babel">
class AppMain extends React.Component {
constructor() {
super()
this.state = {
movies: ['大话西游', '功夫', '西游降魔', '赌圣']
}
}
render() {
return (
<div>
<h2>电影列表</h2>
<ul>
{this.state.movies.map(item => {
return <li>{item}</li>
})}
</ul>
</div>
)
}
}
const root = ReactDOM.createRoot(document.querySelector("#root"))
root.render(
<AppMain />
)
script>
body>
<body>
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin>script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin>script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js">script>
<div id="root">div>
<script type="text/babel">
class AppMain extends React.Component {
constructor() {
super()
this.state = {
count: 100
}
this.add = this.add.bind(this)
this.sub = this.sub.bind(this)
}
add() {
this.setState({
count: this.state.count + 1
})
}
sub() {
this.setState({
count: this.state.count - 1
})
}
render() {
let { count } = this.state
return (
<div>
<h2>当前数值:{count}</h2>
<button onClick={this.add}>点我+1</button>
<button onClick={this.sub}>点我-1</button>
</div>
)
}
}
const root = ReactDOM.createRoot(document.querySelector("#root"))
root.render(
<AppMain />
)
script>
body>