美文网首页
react学习笔记

react学习笔记

作者: MickeyMcneil | 来源:发表于2018-12-10 23:31 被阅读19次

公司最近要做react的项目,所以,小白继续学习中……整理笔记如下……

React 和 Vue的对比

模块化:从代码的角度分析,把可复用的代码,抽离为单个的模块,便于项目的维护和开发。
组件化:从ui的角度分析,把可复用的ui抽离为单独的组件,便于项目的维护和开发。

vue的组件化

通过.vue文件,来创建对应的组件

  • template 结构
  • script 行为
  • style 样式
react的组件化

没有像vue这样的组件模板文件。一切都是以js来表现。

虚拟DOM的概念

DOM -- Document Object Model
浏览器中的概念,用js对象来表示页面上的元素

虚拟DOM -- Virtual Document Object Model
框架中的概念,程序员用js对象来模拟页面上的DOM和DOM嵌套
目的:实现页面元素的高效更新

虚拟DOM为什么能高效更新?举个栗子……

我是栗子

需求:
点击日期和姓名旁的小三角,实现对应表格的数据排序

过程分析:

  1. 数据来源 -- 点击小三角,从数据库查询数据
  2. 数据存放 -- 查询到的数据,存放在浏览器的内存中,以对象数组的形式来表示
  3. 数据渲染 -- 循环拼接字符串 或 模板引擎

问题: 每次拿到数据后,内存中的对象数组是新的,页面总是要重新渲染。性能没有做到最优。
解决思路: 按需渲染。

如何实现按需渲染?

先了解网页的呈现过程:

  1. 浏览器请求服务器,获得HTML
  2. 浏览器在内存中,解析DOM结构,并在浏览器内存中,渲染出DOM树
  3. 浏览器把DOM树,呈现到页面上

因此,拿到内存中的新旧两棵DOM树,进行对比,就能得到需要按需更新的DOM元素

but,如何拿到新旧两棵DOM树呢?
浏览器中,没有直接提供获取DOM树的API,因此,只能程序员手动模拟DOM树

模拟对象:

      <div id="ergou" title="fxd">
          二狗有多哈
          <p>非常哈</p>
      </div>

模拟结果:

var div = {
    tagName: 'div',
    attrs: {
        id: 'ergou',
        title: 'fxd'
    },
    childrens: [
        '二狗有多哈',
        {
            tagName: 'p',
            childrens: [
                '非常哈'
            ]
        }
    ]
}

对比新旧模拟结果的js对象,即可实现页面元素的高效更新。这就是react中虚拟DOM的概念。

如何进行对比呢?

diff算法
diff -- different的缩写

  • tree diff
    新旧两棵DOM树,逐层对比的过程
  • component diff
    对比前后,如组件类型相同,暂时认定不需要更新
    对比前后,组件类型不同,则移除旧组件,创建新组件,并追加到页面上
  • element diff
    如果是component diff中的情况1,则进行元素级别的对比

正式开始react的学习,准备工作,安装 webpack webpack-cli webpack-dev-server html-webpack-plugin,搭建基本的项目结构,在package.json中配置项目启动的具体参数,在webpack.config.js中对项目插件进行配置

在项目中使用react

之前搭建的文件结构如下


  1. 先导入包,包的作用在入口文件中讲
import React from 'react'
import ReactDOM from 'react-dom' 
  1. index.html文件中,挖坑,方便放入react创建的虚拟DOM
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>index</title>
    <!-- <script src="./main.js"></script> -->
</head>
<body>
    <h1>这是首页</h1>
    <div id="app"></div> // 这里是坑
</body>
</html>
  1. 在入口文件index.js中写入
// 入口文件
import React from 'react' // 创建组件、虚拟DOM元素、生命周期
import ReactDOM from 'react-dom' // 把创建好的 组件 和 虚拟DOM 放到页面上展示

// 创建虚拟DOM元素
// 目标 <h1 title="啊,五环" id="myh1">你比四环多一环</h1>
// 参数1 - 字符串类型的参数,对应标签名
// 参数2 - 对象类型的参数,对应属性节点
// 参数3 - 子节点
// 参数4 - 关联的子元素
const myh1 = React.createElement(
    'h1', 
    {
    title: '啊,五环',
    id: 'myh1'
    },
    '你比四环多一环'
)

const mydiv = React.createElement(
    'div',
    null,
    '这是一个div',
    myh1
)
// 渲染虚拟DOM元素
// 参数1 - 要渲染的虚拟DOM对象
// 参数2 - 指定容器,需要放容器的DOM对象
ReactDOM.render(mydiv, document.getElementById('app'))

JSX语法

// 导入包
import React from 'react'
import ReactDOM from 'react-dom'

// 创建虚拟DOM元素
// const mydiv = React.createElement('div', {id: 'mydiv', title: 'div aaa'}, '这是一个div元素')

// JSX的写法 - JS中,默认不能写类似于HTML的标记,所以要使用babel来转化这些JS中的标签
// JSX语法的本质,还是在运行的时候,被转化为了React.createElement形式来执行
const mydiv = <div id="mydiv" title="div aaa">这是一个div元素</div>

// 调用render函数渲染
ReactDOM.render(mydiv, document.getElementById('app'))
  1. 安装如下

babel插件
cnpm i babel-core babel-loader babel-plugin-transform-runtime -D
cnpm i babel-preset-env babel-preset-stage-0 -D

转换JSX语法的包
cnpm i babel-preset-react -D

  1. 根目录添加.babelrc文件,配置
{
  "presets": ["env", "stage-0", "react"],
  "plugins": ["transform-runtime"]
}
  1. webpack.config.js配置
module: { //要打包的第三方模块
    rules: [
      { test: /\.js|jsx$/, use: 'babel-loader', exclude: /node_modules/ }
    ]
}

语法及注意

import React from 'react'
import ReactDOM from 'react-dom'

let a = 10
let str = 'hello'
let boo = false
let title = 'FXD'
const hh = <h1>好好吃饭 做个好人</h1>
const arr = [
    <h2>111111</h2>,
    <h2>22222222222</h2>
]
const arrStr = ['11', '22', '33', '44']
// 所有节点,必须有唯一根元素进行包裹
ReactDOM.render(<div>
    {a}
    <hr/>
    {str}
    <hr/>
    {boo ? 'z' : 'j'}
    <hr/>
    <p title={title}>pppp</p>
    <hr/>
    {hh}
    <hr/>
    {arr}
    <hr/>
    {/* 知识点: */}
    {/* 1. 注释只能用此方法 */}
    {/* 2. key存在的意义,是为了保持状态 - 多选框勾选时,新推入值,勾选项不发生改变 */}
    {/* 3. key必须写在最外层 */}
    {/* 4. 此处可用foreach在jsx外处理,区别,foreach不返回值,map要返回值,并且map必须写return */}
    {arrStr.map(item => <div key={item}><h3>{item}</h3></div>)}
    <hr/>
    {/* className -- class */}
    <p className="myclass">!!!!!!!</p>
    <hr/>
    {/* htmlFor -- for */}
    <label htmlFor="ooo">1111</label>
</div>, document.getElementById('app'))

相关文章

网友评论

      本文标题:react学习笔记

      本文链接:https://www.haomeiwen.com/subject/aoyjhqtx.html