• react基础语法


    1.react与vue的对比

    1.1什么是模块化

    是从代码的角度进行分析的,把一些可复用的代码,抽离为单个的模块,便于项目的维护和开发。

    1.2什么是组件化

    是从UI界面的角度来进行分析的,把一些可复用的UI元素,抽离为单独的组件,便于项目的维护和开发。

    好处:随着项目规模的增大,手里的组件越来越多,很方便就能把现有的组件,拼接成一个完整的项目

    1.3Vue如何实现组件化

    通过 .vue 文件,来创建对应的组件,还可以通过Vue.component()   Vue.extends() 创建组件

    • template 结构
    • script 行为
    • style  样式

    1.4react如何实现组件化

    react中有组件化的概念,但并没有像vue这样的模板文件,react中,一切都是以 js 来表现的

    2.react中几个核心的概念

    2.1虚拟dom

    2.1.1dom的本质

    浏览器中的概念,用js对象来表示页面上的元素,并提供了操作dom对象的api

    2.1.2react中的虚拟dom

    用js对象来模拟页面上的dom和dom嵌套,目的是为了实现页面元素的高效更新

    2.1.3为什么要实现虚拟dom

    为了实现页面中,dom元素高效更新

    2.1.4dom和虚拟dom的区别

    dom:浏览器中提供的概念,用js对象,表示页面上的元素,并提供操作元素的api

    虚拟dom:是框架中的概念,而是开发框架的程序员,手动用js对象来模拟dom元素和嵌套关系

    2.2dom树

    <div id="mydiv" title="嘻嘻">今天天气真好</div>
    var div={
                tagName:'div',
                attrs:{
                    id:'mydiv',
                    titie:'嘻嘻'
                },
                childrens:[
                    '今天天气真好'
                ]
            }

    2.3diff算法

    • tree diff:新旧两颗dom树,逐层对比的过程,就是tree diff,当整颗dom树逐层对比完毕,则所有需要按需更新的元素必然能够找到;
    • component diff:在进行tree diff的时候,每一层中,组件级别的对比,叫做component diff,如果对比前后,组件的类型相同,则暂时认为此组件不需要更新,如果对比前后组件的类型不同,则需要移除旧组件,创建新组件,并追加到页面上;
    • element diff:在进行组件对比的时候,如果两个组件类型相同,则需要进行元素级别的对比,这叫做element diff;

     3.搭建webpack4.x项目

    创建一个文件夹,用vs code打开

    1. 运行  npm init -y 快速初始化项目

    2.在项目根目录创建src源代码目录和dist产品目录

    3.在src目录下创建index.html 和index.js

    4.使用npm安装webpack,运行 npm i webpack -D

    5.使用npm安装webpack-cli,运行 npm i webpack-cli -D

    6.在package.json 修改如下配置,指定dve 为webpack

      "scripts": {
        "test": "echo "Error: no test specified" && exit 1",
        "dev" : "webpack"
      },

    7.在根目录下创建 webpack.config.js 文件,添加如下内容

    //向外暴露一个打包的配置对象
    module.exports={
        mode: 'development' //production二选一
    }

    8.通过命令 npm run dev 来启动项目

    注意:webpack 4.x 提供了约定大于配置的概念,目的是为了尽量减少配置文件的体积,默认约定了打包的入口src->index.js 打包的输出文件dist->main.js

    9.配置项目自动更新打包

    运行 命名 npm i webpack-dev-server -D 当项目修改后会进行自动打包,并修改配置文件package.json

      "scripts": {
        "test": "echo "Error: no test specified" && exit 1",
        "dev" : "webpack-dev-server"
      },

    注意:此时运行npm run dev 会报出如下错误,原因是webpack-cli版本太高

    Error Cannot find module 'webpack-cli/bin/config-yargs' 

    解决办法:(1)npm uninstall webpack-cli 卸载当前的webpack-cli

    (2)重新安装 webpack-cli 3.* 版本npm install webpack-cli@3 -D

    10.在index.html中加入如下内容

        <script src="/main.js"></script> <!--实际在内存中生产-->

    11.将index页面导入内存中

    使用命令 npm i html-webpack-plugin -D 安装插件

    在webpack.config.js配置插件

    const path=require('path')
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    
    //创建一个插件的实例对象
    const htmlPlugin = new HtmlWebpackPlugin({
        template:path.join(__dirname,'./src/index.html'),//__dirname代表根目录,拼接源文件路径
        filename:'index.html'
    })
    
    //向外暴露一个打包的配置对象
    module.exports={
        mode: 'development', //production二选一
        plugins:[
            htmlPlugin
        ]
    }

    12.重新npm run dev 就可以实现实时编译

    4.在项目中使用react

    4.1安装react

    运行 npm i react react-dom -S 安装包

    • react:专门用于创建组件和虚拟dom的,同时组件的生命周期都在这个包中
    • react-dom:专门进行dom操作的,最主要的应用场景就是ReactDOM.render()

    4.2初步使用react

    在index.js 中配置虚拟dom

    //这两个包名接收的成员名必须这么写
    import React from 'react'  //创建组件、虚拟dom元素,生命周期
    import ReactDOM from 'react-dom'  //把创建好的组件和虚拟dom 放到页面上展示
    
    //创建虚拟dom元素
    //参数1:创建的元素的类型,字符串,表示元素的名称
    //参数2:是一个对象或null,表示 当前这个DOM 元素的属性
    //参数3:子节点(包括其他虚拟DOM 获取文本子节点)
    //参数n:其他子节点
    //<div id="weather" title="today">今天天气真好</div>
    const hh=React.createElement('div',{id:'weather',title:'today'},"今天天气真好")
    //使用ReactDOM把虚拟dom渲染到页面上
    //参数1:要渲染的那个虚拟dom元素
    //参数2:指定页面上的一个容器的dom元素
    ReactDOM.render(hh,document.getElementById("app"))

    在index.html中指定容器

        <div id="app"></div>

    然后访问页面就可以实现虚拟dom的渲染

    使用React.createElement实现虚拟DOM嵌套

    const hh=React.createElement('div',{id:'weather',title:'today'},"今天天气真好")
    const div=React.createElement('div',null,'这是一个div',hh)
    ReactDOM.render(div,document.getElementById("app"))

    5.JSX

    5.1什么是JSX

    在js中,混合写入类似于HTML的代码,叫做JSX语法,符合xml规范的js,JSX 语法上更接近 JavaScript 而不是 HTML,例如:

    const mydiv=<div id="mydiv" title="div aaa">这是一个div元素</div>

    注意:JSX语法的本质,还是在运行的时候,被转换成了React.createElement形式来执行的

    5.2如何启用JSX语法

    使用jsx语法前首先要安装babel插件

    1. 运行 npm i babel-core babel-loader@7.1.5 babel-plugin-transform-runtime -D
    2. 运行 npm i babel-preset-env babel-preset-stage-0 babel-preset-react -D

    在webpack.config.js配置如下内容

        module: { //所有第三方 模块的配置规则
            rules: [ //第三方匹配规则
                { test: /.js|jsx$/, use: 'babel-loader', exclude: /node_modules/ }
            ]

    在根目录下创建一个.babelrc文件,加入如下配置

    {
        "presets": [
            "env",
            "stage-0",
            "react"
        ],
        "plugins": [
            "transform-runtime"
        ]
    }

     5.3JSX语法

    渲染常量

    let a=10
    ReactDOM.render(<div>{a}</div>,document.getElementById("app"))

    三元表达式

    let boo=false
    ReactDOM.render(<div>{boo?'条件为真':'条件为假'}</div>,document.getElementById("app"))

    绑定属性

    let title="999"
    ReactDOM.render(<div>
        <p title={title}>这是p标签</p>
        </div>,document.getElementById("app"))

    渲染HTML元素

    const mydiv=<div id="mydiv" title="div aaa">这是一个div元素qqq</div>
    
    ReactDOM.render(<div>
        <p title={title}>这是p标签</p>
        <hr/>
        {mydiv}
        </div>,document.getElementById("app"))

    渲染数组元素

    const arr=[
        <h2>这是h2</h2>,
        <h3>这是h3</h3>
    ]
    ReactDOM.render(<div>
        <p title={title}>这是p标签</p>
        <hr/>
        {arr}
        </div>,document.getElementById("app"))

     外部数组遍历渲染forEach

    const arrStr=['灰太狼','喜洋洋','美羊羊','懒羊羊','沸羊羊']
    const nameArr=[]
    arrStr.forEach(item=>{
        const temp=<h5>{item}</h5>
        nameArr.push(temp)
    })
    ReactDOM.render(<div>
        {nameArr}
    </div>,document.getElementById("app"))

    内部数组遍历渲染map

    const arrStr=['灰太狼','喜洋洋','美羊羊','懒羊羊','沸羊羊']
    ReactDOM.render(<div>{arrStr.map(item=><h3 key={item}>{item}</h3>)}</div>,document.getElementById("app"))

    给数组绑定id:key={item}

     JSX内部的注释:JSX内部的注释分为单行注释和多行注释两种,具体语法如下,推荐使用单行注释

         {/*我是单行注释 */}
    {
    //我是多行注释 //我还可以写很多 }

    在注释中可以使用//#region//#endregion来折叠注释 

    为jsx中的元素添加class类名,需要用className来代替class,用 ‘htmlFor’ 替代 label 的 for 属性

    6.react组件

    6.1创建组件

    6.1.1 使用function关键字创建

    在组件中必须返回一个合法的JSX虚拟的DOM元素,组件的首字母必须大写

    function Hello(){
        return <div>这是H1</div>;
    }

    为组件传递数据

    const dog={ 
        name:"大黄",
        age:2,
        gender:"男"
    }
    function Hello(props){ 
        return <div>这是Hello组件----{props.name}----{props.age}---{props.gender}</div>;
    }
     <Hello name={dog.name} age={dog.age} gender={dog.gender}></Hello>   //使用组件并为组件传递props数据

    其中组件的使用还可以使用展开运算符:

    <Hello {...dog}></Hello>

    6.1.2 使用class关键字创建

    最基本的组件结构

    class 组件名称 extends React.Component{
         render(){
           return <div>这是class创建的组件</div>    
      }            
    }

    在组件内部,必须有render函数,必须返回合法的JSX虚拟dom结构,render函数的作用:是渲染当前组件所对应的虚拟dom元素

    6.1.3 两种创建组件方式对比

    注意:使用class创建的组件,有自己的私有数据和生命周期函数

    注意:使用function创建的组件,只有props,没有自己的私有数据和生命周期函数

    • 1.用构造函数创建的组件叫做“无状态组件”
    • 2.用class关键字创建的组件叫做“有状态组件”
    • 3.什么情况下使用有状态组件?什么情况下使用无状态组件?

    有状态组件和无状态组件的本质区别就是:有无state属性,这里的state相当于vue中的data

    6.2 抽离组件

    在项目根目录下创建一个包components,然后创建一个文件 Hello.jsx ,然后将组件注册写在这个文件里面

    import React from 'react'
    
    export default function Hello(props){
        return <div>这是Hello组件----{props.name}----{props.age}---{props.gender}</div>;
    }

    使用抽离组件,在使用组件之前我们要先进行注册组件

    import  Hello from "./components/Hello.jsx";

    注意,这里的jsx后缀名必须要写,不然会报错,但是我们可以通过配置来不写后缀名,可以通过@来配置绝对路径

    在webpack.config.js里配置如下内容

        resolve:{
            extensions:['.js','.jsx','.json'],  //表示这几个文件的后缀名可以不写
            alias: {
                '@': path.join(__dirname,'./src')    //这样@符合代表src的根目录
            }
        }

    6.3 组件属性props

    在class关键字创建的组件中,如果想使用props参数,不需要接收,直接通过this.props.***访问即可

    class Movie extends React.Component{
        render(){
            return <div>hhh+{this.props.name}----{this.props.age}</div>
        }
    }

    组件传递如下

    <Movie name={dog.name} age={dog.age}></Movie>

    组件中的 props 和 state/data 之间的区别

    1. props中的数据都是外界传递过来的
    2. state/data中的数据,都是组件私有的,(通过Ajax获取回来的值,一般都是私有数据)
    3. props中的数据都是只读的,不能重新赋值
    4. state/data中的数据,都是可读可写的

    6.4 for循环生成多组件

    function CmtItem(props){
        return <div>
            <h1>评论人:{props.user}</h1>
            <p>评论内容:{props.content}</p>
        </div>
    }
    
    class CmtList extends React.Component {
        constructor() {
            super()
            this.state = {
                CommentList:[
                    {id:1,user:'张三',content:'哈哈 沙发'},
                    {id:2,user:'李四',content:'哈哈 板凳'},
                    {id:3,user:'王五',content:'哈哈 凉席'},
                    {id:4,user:'赵六',content:'哈哈 砖头'},
                    {id:5,user:'田七',content:'哈哈 最后'},
                ]            
            }
        }
        render() {
            return <div>
                <h1>这是评论列表组件</h1>
                {this.state.CommentList.map(item=><CmtItem {...item} key={item.id}></CmtItem>)}
            </div>
        }
    }
    ReactDOM.render(<div>
        <CmtList></CmtList>
    </div>, document.getElementById("app"))

    6.5 style的使用

    6.5.1 行内使用

    在使用style标签时,要用双大括号

    注意:在行内样式中,如果是数值类型的样式,则可以不用引号包裹,则可以不用引号包裹,如果是字符串类型的样式值,必须使用引号包裹。

    style={{color:'red',fontSize:'16px'}}

    6.5.2 样式抽离

    const styles={
        item:{ border:'1px',margin:'10px'},
        content:{ fontSize:'12px'}
    }

    引入为 style={styles.item}

    6.5.3 引入外部css样式 

    1.首先项目要安装样式loader

    运行命令 npm i style-loader css-loader -D

    2.配置打包处理css样式的第三方loader

    在webpack.config.js的module-rules中加入如下配置

           { test: /.css$/, use: ['style-loader','css-loader'] }

    3.在src目录下新建一个文件夹css,在新建一个css样式文件cmtlist.css,在css中加入代码如下:

    .title{
        color: red;
    }

    4.在页面引入并使用css样式

    首先要导入外部样式,然后标签通过指定显示,具体代码如下

    //导入样式
    import cssObj from '@/css/cmtlist.css'
    
    <h1 className='title'>这是评论列表组件</h1>

    注意:可以通过通过在css-loader之后,通过?追加参数,这里有个固定的参数modules,表示为css样式启用模块化

                { test: /.css$/, use: ['style-loader','css-loader?modules']} //打包处理css样式的第三方loader

    启动模块化样式之后具体引入外部样式为:

    <h1 className={cssObj.title}>这是评论列表组件</h1>

    注意:css模块化只针对类选择器和id选择器生效

    6.5.4 安装外部样式bootstrap

    首先安装bootstrap

    npm i bootstrap@3.3 -S

    然后安装bootstrap所需字体的loader

    npm i url-loader -D

    在webpack.config.js配置打包字体文件loader

    { test: /.ttf|woff|woff2|eot|svg$/, use: 'url-loader' } //打包处理字体文件loader

     最后在页面导入包(注意:在node_modules目录下的包,直接以包名开始引入自己的模块或样式表就可以了

    import bootcss from 'bootstrap/dist/css/bootstrap.css'

    在标签中使用

    <button className={[bootcss.btn,bootcss['btn-primary']].join(" ")}>按钮</button>

    6.5.5 项目启用模块化

    规定:第三方样式表都是以.css结尾的,自己的样式表都要以.scss和.less结尾

    我们只需要为自己的.scss文件,启用模块化即可

    运行下面命令来安装解析scss文件的loader

    npm i sass-loader node-sass -D

    找到module里的css配置部分,修改正则匹配为:/.(css|scss)$/,在use数组里添加sass-loader

    { test: /.scss$/, use: ['style-loader', 'css-loader?modules','sass-loader'] },

    修改css样式表不被模块化

    { test: /.css$/, use: ['style-loader', 'css-loader'] }, 

    然后外部样式引入和使用可直接安装如下写法:

    import 'bootstrap/dist/css/bootstrap.css'
    
    <button className="btn btn-primary">按钮</button>

    这样就大大增加了开发效率

    7.react绑定事件

    1)react事件的名称都是由React提供的,因此名称命名必须按照react的规范,如:onClick、onMouseOver

    2)为事件提供的处理函数,格式如下:

    onClick={ function }

    使用案例:(注意:这种情况无法传参,不建议使用)

        render(){
            return <div>
                BindEvent组件
                <button onClick={this.myClickHandler}>按钮</button>
            </div>
        }
        myClickHandler(){
            alert(1)
        }

    另外一种写法,使用箭头函数:(推荐使用)

        render(){
            return <div>
                BindEvent组件
                <button onClick={()=>this.myClickHandler(this.state.a)}>按钮</button>
            </div>
        }
        myClickHandler=(i)=>{
            alert(i)
        }

    8.修改属性

    在React中,推荐使用this.setState({ }),修改状态值

        myClickHandler = (i) => {
            this.setState({
                msg:"111"+i
            })
        }

    注意:

    (1)使用setState方法时只会把对应的state状态更新,其他的state状态属性值不变

    (2)this.setState方法的执行是异步的

    如果调用完this.setState之后,又想立即拿到最新的state值,需要使用this.setState({ },callback)

    9.绑定属性

    react中没有双向绑定,需要程序员手动进行绑定

    首先创建一个input框,值设定为state值

    <input type='text' onChange={(e)=>this.txtChanged(e)} style={{  '100%' }} value={this.state.msg} />
    实现双向绑定onChange事件
    获取值的两种方法:

    1.onChange事件传递一个对象e,通过e.target.value来获取
        txtChanged=(e)=>{
            console.log(e.target.value)
        }

    2.通过refs来获取,this.refs.txt.value

    <input type='text' onChange={()=>this.txtChanged()} ref='txt' style={{  '100%' }} value={this.state.msg} />
        txtChanged=()=>{
            console.log(this.refs.txt.value)
        }

    3.同步数据

    然后将获取最新的值赋值给state,就可以实现数据的双向绑定了

        txtChanged=()=>{
            const newVal = this.refs.txt.value
            this.setState({
                msg:newVal
            })
        }

    10.组件的生命周期

    10.1 组件创建阶段

    特点:一辈子只执行一次

    1)componentWillMount

    componentWillMount()一般用的比较少,它更多的是在服务端渲染时使用。它代表的过程是组件已经经历了constructor()初始化数据后,但是还未渲染DOM时。

    2)componentDidMount

    组件第一次渲染完成,此时dom节点已经生成,可以在这里调用ajax请求,返回数据setState后组件会重新渲染

    10.2 组件运行阶段

    特点:根据props属性或者state状态的改变,有选择性的执行0到多次

    1)shouldComponentUpdate(nextProps,nextState)

    • 主要用于性能优化(部分更新)
    • 唯一用于控制组件重新渲染的生命周期,由于在react中,setState以后,state发生变化,组件会进入重新渲染的流程,在这里return false可以阻止组件的更新
    • 因为react父组件的重新渲染会导致其所有子组件的重新渲染,这个时候其实我们是不需要所有子组件都跟着重新渲染的,因此需要在子组件的该生命周期中做判断

    2)componentWillUpdate

    shouldComponentUpdate返回true以后,组件进入重新渲染的流程,进入componentWillUpdate,这里同样可以拿到nextProps和nextState。

    3)render

    render函数会插入jsx生成的dom结构,react会生成一份虚拟dom树,在每一次组件更新时,在此react会通过其diff算法比较更新前后的新旧DOM树,比较以后,找到最小的有差异的DOM节点,并重新渲染。

    4)componentDidUpdate

    组件更新完毕后,react只会在第一次初始化成功会进入componentDidmount,之后每次重新渲染后都会进入这个生命周期,这里可以拿到prevProps和prevState,即更新前的props和state。

    5)componentWillReceiveProps(nextProps)

    • 在接受父组件改变后的props需要重新渲染组件时用到的比较多
    • 接受一个参数nextProps
    • 通过对比nextProps和this.props,将nextProps的state为当前组件的state,从而重新渲染组件

    10.3 组件销毁阶段

    特点:一辈子只执行一次

    1)componentWillUnmount

    在此处完成组件的卸载和数据的销毁。

    1. clear你在组建中所有的setTimeout,setInterval
    2. 移除所有组建中的监听 removeEventListener

    一点点学习,一丝丝进步。不懈怠,才不会被时代所淘汰!

  • 相关阅读:
    小木虫等论坛自动签到程序发布
    第一篇随笔
    工作和兴趣哪个更重要?
    weblogic 启动时 报错
    C#动态调用webservice (转载)
    U盘加载,卸载,拔出,插入(转载)
    Simple zip archive unzipper(转载)
    Best C# Blogs(强烈推荐)
    数据无法导入ArcSDE
    Oracle10.2.0.1.0升级Oracle10.2.0.2.0补丁安装指南(转载)
  • 原文地址:https://www.cnblogs.com/fqh2020/p/12093787.html
Copyright © 2020-2023  润新知