React - Basics
概念
- react 是一个构建用户界面的 js 库 react 主要用户构建UI 很多人认为 React 是 MVC 中的V(视图)
- 可编程性更好一些 更底层更灵活 本身只处理ui 也不处理ajax和不关心路由
- 数据驱动视图 只有搭上了全家桶,才可以称之为框架~
- 第一个真正意义上的组件化思想带到前端开发领域
- React Native 是开发原生 App 的
- 虚拟DOM VUE也是虚拟 DOM
- 声明配置设计 data就是响应式数据 methods就是处理函数
- 这样做的好处就是 按照约定好的方法来开发 所有人写的代码就像一个人写的一样
- state 方法就是类成员 也有特定的组件生命钩子
- 三大框架都是 数据驱动视图 组件化 vue生产效率更高一些~
- 特点:
- 组件化 高效(虚拟DOM)
- 灵活(渐进式 本身只处理UI 可以和其他技术栈组合使用)
- 声明式设计(配置设计 方法就是类成员 也有特定的组件生命钩子 )
- JSX(一种预编译js语言 允许让你的js和Html混搭 模板中就是js逻辑)
- 单向数据流(这个单向数据流是组件传值问题 所有数据都是单向的 组件传递的数据都是单向的 Vue也是单向数据流 没有双向数据绑定)
React 开源协议 不同的开源协议对使用者的限制情况不一样
React 和 vue 的对比
- 技术方面
- Vue 生产力更高 ( 更少的代码实现更强的功能 )
- React 的技术占比更高一些
- 框架都采用了 虚拟 DOM 性能都差不多
- 组件化 两个都支持 组件化
- 数据绑定
- 都支持数据驱动视图
- Vue 支持表单空间双向数据绑定 React不支持表单双向数据绑定
- 核心库都很小 都是渐进式js库 搭配全家桶就会发挥更大的作用
- React 采用 JSX 语法来编写组件
- Vue 采用单文件组件
- Native App 开发
- React Native
- 可以原声应用开发
- Weex
- 阿里巴巴内部做出来的一个 基于 Vue
React 相关资源
- React 官网
- 官方教程
- 官方文档
- React - GitHub
- 阮一峰 - React 技术栈系列教程
- awesome react
- awesome - react - components
day1 - day3 React
day1 - React概念基础
library(库) : 小而巧的库 优点就是 方便切换 代码几乎不改变
Framework(框架) : 大而全的就是框架 框架 提供的是一套的解决方案,所以 如果在项目中间想切换到 另外的框架 是比较困难的。
-
模块化 : 是从 代码的角度来进行分析的
- 把一些可复用的代码 抽离成单个模块 便于项目的维护和开发
-
组件化: 是从UI界面的角度 来进行分析的
- 把一些可复用的 UI 元素 抽离成单独的组件
-
组件化的好处 :
- 随着项目规模的增大 手里的组件就越来越多 很方便就能把现有的组件 拼接为一个完整的页面
-
vue 是如何实现组件化的
- Vue.component()
-
.vue
的模板文件,来创建对应的组件;- template 结构
- script 行为
- style 样式
-
React 是如何实现组件化的
- React有组件化的概念但是并没有像 vue 这样的组件模板文件
- React 中 一切都是以 JS 来表现的; 因此 js 基础要合格 es6 7 要合格
- ES7 中 async 和 await 要使用的多一些
为什么要学习 React
React 一切都是基于 js 并且实现了组件化开发的思想
不必担心断更的问题 开关团队实力强
社区强大 很多问题都能找到解决方案
提供了无缝转到 React Native 的开发体验 让我们的技术得到了扩展 增强了我们的核心竞争力
很多企业中 前端项目的技术选型 采用就是React.js
介绍DOM和虚拟DOM的概念
虚拟DOM
-
DOM的本质是什么
- 浏览器中的概念 用JJS对象来表示 页面上的元素并提供了 操作DOM对象的API
-
什么是React中的虚拟DOM:
- 是框架里面的概念 用JS对象来模拟页面上的DOM和DOM嵌套
-
为什么要实现虚拟DOM(虚拟DOM的目的):
- 为了实现页面中 DOM元素的 高效更新
-
数据渲染到页面的方法
手动for循环 整个数组 然后 手动拼接字符串 str += '<tr></tr>'
使用模板引擎 art-template
按需 渲染 页面 只重新传染 更新的数据 所对应的页面元素
-
如何实现页面的 按需 更新呢?
- 获取内存中的 新旧 两棵DOM树 进行对比 得到需要被按需更新的 DOM元素
-
DOM 树的概念
- 浏览器 请求服务器 获取页面HTML代码
- 浏览器要先在内存中 解析DOM结构并在浏览器的内存中 渲染出一颗DOM树
- 浏览器把 DOM树 呈现到 页面上
-
如何获取 新旧 DOM树 从而实现 DOM树的对比呢?
分析 : 浏览器中 并没有直接提供获取 DOM 树的API 因此我们无法拿到浏览器内 存中的DOM树
因此可以手动模拟 新旧两棵 DOM树
<div id="mydiv" title="说实话" data-index="0"> 123 <p>哈哈哈</p> </div> // 手动模拟虚拟DOM元素 var div = { tagName : 'div', attrs : { id : 'mydiv', title : '说实话', 'data-index' : '0' }, childrens : [ '123', { tagName : 'p', attrs : {}, childrens : { '哈哈哈' } } ] } 程序员手动模拟的这两棵 新旧DOM树的 就是React虚拟DOM树的概念
总结 : 什么是虚拟DOM 用JS对象的形式 来模拟页面上DOM进行嵌套关系的(虚拟DOM 是以 JS 对象的形式存在的)
-
这就是 React 中虚拟DOM的概念
- 本质:用JS对象 来模拟DOM元素和嵌套关系
- 目的:就是为了实现页面元素的高效更新
-
DOM和虚拟DOM
- DOM是 浏览器中提供的概念 用JS对象 表示页面上的元素 并提供了操作元素的API
- 虚拟DOM 是框架中的概念 是开发框架的程序员 手动用JS 对象来模拟DOM元素和嵌套关系的
- 本质:用JS对象 来模拟DOM元素和嵌套关系
- 目的:就是为了实现页面元素的高效更新
Diff算法(这个就是新旧DOM对比的过程中的算法)
- tree diff (different 差异)
- 新旧两棵DOM树 逐层对比的过程 就是Tree Diff;当整颗DOM树逐层对比完毕 则所有需要被 按需更新的元素 必然能够被找到
- component diff
- 在进行 tree diff 的时候 每一层中 组件级别的对比 叫做 component Diff
- 如果 对比前后 组件的类型相同 则暂时 认为组件不需要被更新
- 如果 对比i前后 组件的类型不同 则需要移除 组件 创建新组件 并追加到页面上
- element diff
- 在进行组件对比的时候 如果两个组件类型相同 则需要进行 元素级别的对比 这叫做 element diff
webpack4.x 最基本的使用步骤
运行
npm init -y
快速初始化项目在项目根目录创建
src
源代码目录 和dist
产品目录在
src
目录下 创建一个index.html
-
使用 cnpm 安装 webpack 运行
cnpm i webpack -D
- 运行全局
npm i cnpm -g
这个也可以运行安装cnpm - **webpack4 以后需要安装
webpack-cli
** - 这个 webpack-cli 是后边独立出来带有打包功能的脚手架
- 运行全局
-
然后创建一个
webpack.config.js
文件// 向外暴露一个打包的配置对象;这个是webpack打包文件的时候 会去找这么一个文件 然后进行相关的编辑与编译 因为webpack是基于node构建 所以支持所有node的API module.exports = { // mode 是 webpack 4.0 新增的属性 可选的值是 development production // 这个mode选项是必选项 mode : 'development' // development production // development是开发模式 production 是压缩(上线)模式 } export default {} // 这个是不行的 // 这是 ES6 中 向外导出模块的 API 与之对应的是 import ** from '标识符(路径)' // 那些特性 Node 支持? 如果 chrome 浏览器支持那些属性 node就支持那些属性
在
webpack 4.x
中 有一个很大的特性 就是约定大于配置约定 默认的打包入口路径是
src
下面的index.js
然后这里只需要将 main.js 替换成
index.js
文件就好打包的输出文件是
dist
下面的main.js
目的是 为了尽量减少 配置文件的体积
如果 需要不一样的方法 就需要手动去配置
4.x 以上只是提升了打包的性能 和 增加一些约定 其余的都还没有太大变化
webpack-dev-server的基本使用
实时的 打包编译文件 webpack 插件
在 package.json 文件下 配置
“dev” : "wabpack-dev-server"
配置完成后 接下来在运行的时候 就是 cnpm run dev
webpack-dev-server
打包好的main.js
是托管到了内存中 所以在项目根目录中看不到但是我们可以认为 在项目根目录中 有一个看不见的
main.js
然后在 index.html 中直接
<script src="/main.js"></script>
引用即可dev-server 就是在内容中 帮我们实时打包好这个
main.js
文件--open firefox(打开火狐 不配置就是打开默认浏览器) --port 3333 --hot --compress --host 127.0.0.1 // iexplore 是ie的称呼 等等配置package.json文件配置
html-webpack-plugin插件配置
- 如果想要将首页把 首页文件 放到内存中 不再借助于物理磁盘 需要html-webpack-plugin插件
cnpm i html-webpack-plugin -D
- 在 webpack.config.js 中配置
const path = require('path');
const HtmlWebPackPlugin = require('html-webpack-plugin')
//导入 在内存中自动生成 index 页面的插件
// 创建一个插件实例
const htmlPlugin = new HtmlWebPackPlugin({
template : path.join(__dirname,'./src/index.html'), //源文件
filename : 'index.html', // 生成的内存中首页的名称
})
// 将插件放置到 配置对象中
module.exports = {
mode : 'deveiopment',
plugins : [
htmlPlugin
]
}
配置 babel 插件
day1 - 在项目中使用 React(13 虚拟DOM)
-
运行
cnpm i react react-dom -S
安装包、- react:专门用于创建组件和虚拟dom的 同时组件的生命周期都在这个包中
- react-dom :专门进行DOM操作 最主要的应用场景 就是ReactDOM.render()
因为 -S 表示的是 这个项目从开发到上线 都要使用上的安装包
-
在
index.html
页面中 创建容器<!--容器,将来 使用 React 创建的虚拟DOM元素 都会被渲染到这个制定的容器当中--> <div id="app"></div>
-
导入包:
import React from 'react' import ReactDOM from 'react-dom'
-
创建虚拟DOM元素:
// 这是创建虚拟DOM元素API <h1 title="啊,五环" id="nyh1">你比六环少一环</h1> // 第一个参数:字符串类型的参数,表示要创建的标签名字 // 第二个参数:对象类型的参数,表示 创建的元素的属性节点 // 第三个参数:子节点 const myh1 = React.createElement('h1',{title:'啊,五环',id:'myh1'},'你比六环少一环')
-
渲染:
// 3. 渲染虚拟DOM元素 // 参数1 : 表示要渲染的虚拟DOM对象 // 参数2 : 指定容器 注意:这里不能直接放 容器元素的ID字符串 需要放一个容器的 DOM 对象 ReactDOM.render(myh1,document.getElementById('app'))
JSX语法
什么是jsx语法 : 就是符合 xml 规范的 js 语法;(语法格式相对来说 要比 html 严谨的多)
-
如何启用 jsx 语法
-
安装
babel
插件- 运行
cnpm i babel-core babel-loader babel-plugin-transform-runtime -D
- 运行
cnpm i babel-preset-env babel-preset-stage-0 -D
- 运行
-
安装能够识别转换 jsx 语法的包
babel-preset-react
- 运行
cnpm i babel-preset-react -D
- 运行
-
添加
.babelrc
配置文件{ "presets" : ["env","stage-0","react"], "plugins" : ["transform-runtime"] }
-
添加 babel-loader 配置项:
module : { // 所有第三方模块的 匹配规则 rules : [ // 第三方的匹配规则 {test : /\.js|jsx$/,use : 'babel-loader',exclude : /node_modules/}, //千万别忘记 添加 exclude 排除项 ] }
特别注意 这里的
babel-loader
的版本问题 因为babel-core
的版本是 6.26 因为指定 "babel-loader": "^7.1.5", 的版本就可以解决报错的问题
-