建立文件夹
package.json
这是所有的包,直接复制使用cnpm i
来下载就可以了
一些包名babel的解释
{
"name": "03react",
"version": "1.0.0",
"description": "",
"main": "webpack.config.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack-dev-server --open --port 3000 --hot"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"babel-core": "^6.26.3",
"babel-loader": "^7.1.5",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.7.0",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-0": "^6.24.1",
"css-loader": "^2.1.0",
"file-loader": "^3.0.1",
"html-webpack-plugin": "^3.2.0",
"less": "^3.9.0",
"less-loader": "^4.1.0",
"node-sass": "^4.11.0",
"sass-loader": "^7.1.0",
"style-loader": "^0.23.1",
"url-loader": "^1.1.2",
"webpack": "^4.29.3",
"webpack-cli": "^3.2.3",
"webpack-dev-server": "^3.1.14"
},
"dependencies": {
"react": "^16.8.4",
"react-dom": "^16.8.4"
}
}
webpack的配置
webpack配置文档
webpack主要就四个核心的概念:入口,出口,插件,loader
const path = require('path')
const htmlWepackPlugin = require('html-webpack-plugin')
module.exports = {
entry:path.join(__dirname,'/src/main.js'),//入口
output:{//出口
path:path.join(__dirname,'/dist'),
filename:'bundle.js'
},
plugins:[
new htmlWepackPlugin({
template:path.join(__dirname,'/src/index.html'),
filename:'index.html'
})
],
module:{
rules:[
{test:/\.css$/,use:['style-loader','css-loader']},
{test:/\.less$/,use:['style-loader','css-loader','less-loader']},
{test:/\.scss$/,use:['style-loader','css-loader','sass-loader']},
{ test: /\.(jpg|png|gif|bmp|jpeg)$/, use: 'url-loader?limit=5000&name=[hash:8]-[name].[ext]' },
{test: /\.(ttf|eot|svg|woff|woff2)$/, use: 'url-loader' },
{ test: /\.jsx?$/, use: 'babel-loader', exclude: /node_modules/ },
]
}
}
- path:因为webpack是基于node的,所以我们引入node的核心模块path路径
- entry规定入口文件;
- output是规定出口文件,通过 output.filename 和 output.path 属性,来告诉 webpack bundle 的名称,以及我们想要 bundle 生成(emit)到哪里
- plugins:是我们的插件,则可以用于执行范围更广的任务,里面配置的htmlWebpackPlugin可以查看webpack官方文档,它的主要作用是在内存生成模板文件,并且主动帮我们注入bundle.js
- loader 让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块,然后你就可以利用 webpack 的打包能力,对它们进行处理。test 属性,用于标识出应该被对应的 loader 进行转换的某个或某些文件。use 属性,表示进行转换时,应该使用哪个 loader。
- 我们把webpack-dev-server直接在package.json里面配置了,所以不需要在配置,当然在webpack配置可以查看devServer的配置
.babelrc文件的配置
{
"presets":["env","stage-0","react"],
"plugins":["transform-runtime"]
}
运行项目
cnpm i //如果是复制package文件的话,需要安装包
cnpm run dev //直接运行项目
抽离介绍关于React的配置的
上面关于react基本的配置都已经配置完成了,介绍一下react的配置
其中下载该包是使用JSX语法的
cnpm i babel-preset-react -D
而react和react-dom则是我们需要的
cnpm i react react-dom -S
需要在.babelrc进行JSX语法配置{"presets":["react"]}
React学习
React 是一个采用声明式,高效而且灵活的用来构建用户界面的框架。
Hello world
- react 这个包,是专门用来创建React组件、组件生命周期等这些东西的;
- react-dom 里面主要封装了和 DOM 操作相关的包,比如,要把 组件渲染到页面上,React DOM 首先会比较元素内容先后的不同,而在渲染过程中只会更新改变了的部分。
- 引入react
import React from 'react'
import ReactDom from 'react-dom'
- 创建元素并渲染
- React.createElement(元素,属性,子节点) 方法创建虚拟DOM对象,接收三个及以上参数
- React.render(‘要渲染的虚拟dom’,要渲染到哪个位置)
- 第一个例子
index.html里面写入一个容器:在此 div 中的所有内容都将由 React DOM 来管理,所以我们将其称之为 “根” DOM 节点;在此div里面写入的内容都会被替换
<div id="app"></div>
渲染dom
var myH1 = React.createElement('h1', null, 'Hello World!')
ReactDom.render(myH1, document.getElementById('app'))
使用浏览器查看我们,在开发是最好安装扩展React Developer Tools,便于我们对数据的观看
JSX
JSX 本身其实也是一种表达式,在编译之后呢,JSX 其实会被转化为普通的 JavaScript 对象。将它赋值给变量,当作参数传入,作为返回值
JSX内部在运行的时候,也是先把 类似于HTML 这样的标签代码, 转换为了 React.createElement 的形式;JSX需要注意的几个点:
- 如果要直接使用 JSX 语法,需要先安装相关的 语法转换工具
babel-preset-react
- 当 编译引擎,在编译JSX代码的时候,如果遇到了<那么就把它当作 HTML代码去编译,如果遇到了 {} 就把 花括号内部的代码当作 普通JS代码去编译;
- 在JSX语法内部书写代码,要写在{}内部;所以注释也需要写在或括号里面
- 如果要为元素添加class属性了,那么,必须写成className,因为 class在ES6中是一个关键字
- label标签的 for 属性需要替换为 htmlFor.
- 和vue组件一样,所有的节点,必须有唯一的根元素进行包裹
通过一个代码来了解一下JSX语法,代码的括号可以去掉
let eleArr = []
for(var i = 0; i < 5; i++){
var p = <p className="myp" key={i}>jsx语法的使用</p>
eleArr.push(p)
}
var box = (<div>
<label htmlFor="id">必须使用唯一的根元素包裹</label>
{/* 这是我的注释,需要加花括号 */}
{eleArr}
</div>)
ReactDom.render(box, document.getElementById('app'))
无状态组件
用构造函数创建出来的组件:专业的名字叫做“无状态组件”;也就是无state
- 我们在main.js使用构造函数
function Hello(){
return <div>
<h1>无状态组件</h1>
</div>
}
ReactDom.render(<Hello></Hello>, document.getElementById('app'))
React在解析所有的标签,是以首字母来区分的,如果首字母大写,则按照组件的形式,如果首字母小写,则按照html去解析,这个结果解析成<div id="app"><hello></hello></div>
ReactDom.render(<hello></hello>, document.getElementById('app'))
使用JSX独立的组件,在src新建compones文件夹,并新建一个HELLO.JSX文件,在main.js引入
import React from 'react'
function Hello() {
return <div>
<h1>这是单独一个组件</h1>
</div>
}
// 把创建的组件暴露出去
export default Hello
import Hello from './components/Hello.jsx'
ReactDom.render(<Hello></Hello>, document.getElementById('app'))
有状态组件
使用有状态的组件,即使用class关键字创建出来的组件,有state属性
class Welcome extends React.Component {
render() {
return <h1>Hello</h1>;
}
}
ReactDom.render(<Welcome></Welcome>, document.getElementById('app'))
使用JSX独立的组件,在src新建compones文件夹,并新建一个HELLO.JSX文件,在main.js引入;从这个例子可可以看出有状态组件和无状态组件的区别
import React from 'react'
export default class List extends React.Component {
constructor(props) {
super(props)
this.state = {
login: [
{ user: '1', content: '1' },
{ user: '2', content: '2' },
{ user: '3', content: '3' },
{ user: '4', content: '4' },
{ user: '5', content: '5' }
]
}
}
render() {
return <div>
<h1 className="title">评论列表案例</h1>
<ul>
{this.state.login.map((item, i) => {
return <li key={i}><a href="#">{item.user}</a><span>{item.content}</span></li>
})}
</ul>
</div>
}
}
- 我们构造函数继承是改变其原型链,这里extends是实现继承;前面是子类后面是父类
- 使用extends继承,必须有super();表示对构造器的引用
- map是一个方法;map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。
- 浏览器每秒钟调用tick()方法;通过调用 setState() ,React 知道状态已经改变,并再次调用 render() 方法来确定屏幕上应当显示什么。
import List from './components/Welcome1.jsx'
ReactDom.render(<List></List>, document.getElementById('app'))
生命周期函数
虚拟DOM
DOM的本质就是用UI创建的对象;虚拟DOM(virtul DOM)就是我们程序员手动模拟实现的,在这里,虚拟DOM通过JS的Object对象模拟DOM中的真实节点对象,再通过特定的render方法将其渲染成真实的DOM节点。
Diff算法
React最值得称道的就是虚拟DOM与Diff算法的结合,让用户可以无所顾忌的刷新页面;Diff算法会帮助我们计算出虚拟DOM真正变化的部分;并只对DOM进行实际的操作,而非渲染整个页面。Diff算法:新旧DOM树,逐层对比的方式(tree)----在对比每一层的时候,组件之间的对比(component)----在组件中,每个元素之间也要进行对比(element)
对生命周期函数做基础了解
- componentsWillMount:组件将要挂载到页面上;即虚拟DOM还没有被创建,同时还没有挂载到页面上。
还没有起床 - render:就已经开始要渲染虚拟dom了,当我们的render执行完;我们的虚拟DOM在内存创建好了,但没有挂载到页面上。
已经起床,执行完了刷牙,还没有上班工作 - componentsDidMount:我们的state数据,和内存中虚拟Dom已经保持一致了。到这里组件创建的阶段已经完毕,组件已经完整挂载到页面中。
上班工作