zoukankan      html  css  js  c++  java
  • react入门学习

    初始配置

    $ 1 创建基本的webpack项目

    创建目录

    • npm init -y 创建package.json

    • cnpm i webpack webpack-cli -D 安装webpack webpack-cli

    • 在根目录创建webpack.config.js并写入相应代码module.exports={mode:'development'}

    • 终端里输入webpack进行打包,之后dist文件夹里多出个main.js,打包成功

    配置实时打包编译
    • cnpm i webpack-dev-server -D
      package.jsonscripts里写入"dev": "webpack-dev-server --open --port 3000 --hot --host 127.0.0.1 --progress --compress"webpack-dev-server之后的如--open,--hot等代码是功能性代码,可选择性写
    `--open` 设置自动打开默认浏览器 `--oprn chrome`设置自动打开google浏览器
    `--port 3000` 设置端口号为3000,若不写则默认是8080
    `--host 127.0.0.1`设置域名为127.0.0.1
    `--compress` 压缩
    `http://loaclhost:8080/`
    
    • npm run dev 运行,文件可在http://localhost:8080打开(ctrl+c可以终止npm run dev)
      index.html 中<script src="../dist/main.js"></script> 路径改为/main.js
    因为webpack-dev-server打包好的main.js是托管到内存中的,在内存中是看不到的,
    但却实实在在的存在于根目录中,所以用/main.js引入根目录中的main.js
    
    解决经常访问磁盘目录问题——将index页面也放入内存中即可
    • cnpm i html-webpack-plugin -D 安装在内存中自动生成html页面的插件,解决每保存一次就调用代码消耗磁盘性能的问题
    • webpack.config.js写入如下代码(dirname前是两个 _ )--注意,代码千万不要敲错

    const path=require('path')
    const HtmlWebPackPlugin = require('html-webpack-plugin')
    
    const htmlPlugin = new HtmlWebPackPlugin({
      template: path.join(__dirname,'./src/index.html'),
      filename:'index.html'
    })
    
    module.exports = {
      mode: 'development',
      plugins:[
        htmlPlugin
      ]
    }
    

    在这运行之后,系统会自动把打包好的js注入到页面中去(如下图蓝色部分是系统自动注入的)。所以<script src="/main.js"></script>可以省去了!

    • npm run dev即可(注,不要cnpm run dev, cnpm一般只用来装包)

    ———————————————以上,初步配置完成———————————————

    $ 2 react起步(react中,一切都是用js来表现的)

    安装react react-dom包
    • cnpm i react react-dom -S
    • 在index.js里导入包
      import React from 'react'
      import ReactDOM from 'react-dom'
    • 接下来可以根据格式来写代码了,在index.js里写
    创建虚拟DOM元素: const myh1 = React.createElement("h1",{id:"myh1",title:"thish1"},"这是一个h1标签及其内容")
    `参数1:标签类型:div,h1,input等:
    参数2:标签属性,{attr:"aa",attr:"bb"},不设置就写null`
    `参数3:标签子节点,或者说内容
    参数n:其他更多子节点`
    调用render函数渲染: ReactDOM.render(myh1,document.getElementById("list1"))
    `参数1:要渲染的那个虚拟DOM元素,如myh1;
    参数2:指定html页面上的一个容器(必须写成dom元素的形式,就是这里的document.getElementById)
    如<div id="list1"></div>`
    

    标签嵌套写法

    JSX
    • React.createElement形式写起来太繁琐
    • 于是react开发出了在js中,混合写入类似于html的语法,我们称之为JSX
    • 写好之后通过babel转换成React.createElement形式执行便可
    • jsx 语法的本质:并不是直接把 jsx 渲染到页面上,而是内部先转换成了 createElement 形式,再渲染的
    配置babel

    (版本配置问题,避免踩坑从我做起 https://blog.csdn.net/tj310/article/details/88134512 )

    • 安装 babel 插件
      • 运行cnpm i babel-loader @babel/core @babel/plugin-transform-runtime @babel/runtime -D
      • 运行 cnpm i @babel/preset-env @babel/plugin-proposal-class-properties -D
    • 安装能够识别转换jsx语法的包,就是将jsx转化为js @babel/preset-react
      • 运行cnpm i @babel/preset-react -D
    • 在根目录添加 .babelrc 配置文件
    {
      "presets": ["@babel/preset-env", "@babel/preset-react"],
      "plugins": ["@babel/plugin-transform-runtime", "@babel/plugin-proposal-class-properties"]
    }
    
    • 在webpack.config.js的module.exports中添加babel-loader配置项:
    module: { //要打包的第三方模块
        rules: [
          { test: /.js|jsx$/, use: 'babel-loader', exclude: /node_modules/ }  //exclude一定不能丢
        ]
    }
    
    
    • 后缀名的省略及改变路径
    在以上,在webpack.config.js之中的module下方添加如下代码
     resolve: {
        extensions: ['.js', '.jsx', '.json', '.vue'], // 表示,这几个文件的后缀名,可以省略不写
        alias: { // 表示别名
          '@': path.join(__dirname, './src') // 这样,@ 就表示 项目根目录中 src 的这一层路径
        }
      }
    
    创建组件(两种方法,本质区别是有无state属性)

    方法1:普通function模式创建组件(用的不多)

    1、 src目录下创建components文件夹,里面创建组件文件(如comp1.jsx),在里面写入组件
        `如`
            import React from "react"     `*****必须引入React包*****`
            function Hello(props) {          `***组件名称首字母大写***`
              return <div>这是一个Hello组件----{props.name}----{props.age}----{props.weight}</div>
            }
            export default Hello           `*****必须暴露组件*****`
    
    2、在index.js文件里引入组件
            import Hello(组件名称) from "./components/comp1.jsx"   `*****必须引入组件*****`
    
            const arrStr = ["haha", "heihei", "hehe", "xixi"]
    
            const dog={
                name:"金毛",
                age:"2",
                sex:"公",
                weight:"50kg"
            }
    
            ReactDOM.render(<div>
    
              <Hello {...dog}></Hello>      `***使用组件,以组件做标签名来使用,记住要和组件名一模一样***`
                                                          `{...dog}`,es6语法---展开运算符
    
              {arrStr.map(item => < div key = {item.id}><h3>{item}</h3></div > )}   //map方法映射数组,箭头函数,key
    
             </div>, document.getElementById("list1"))
         
    
    方法2:class关键字创建组件
    • 先了解什么是class关键字
    创建一个动物类
    //在class的{}区间内只能写构造器(内部包含实例属性),静态属性,实例方法,静态方法
    //class关键字内部,还是原来的js方法来写,只不过更方便了,因此把class关键字称作 语法糖
    const Animal {    // 这是class关键字
    构造器://class关键字内必须要有。每当执行new这个类的时候,会优先执行构造器中的代码
        constructor("name","age"){
            this.name=name      
            this.age=age
        }
    静态属性://在class内部,通过static修饰的属性
        static info = "aaaaa"
    实例方法(经常用到)
        yaoweiba(){
            console.log("这是一个实例方法")
        }
    静态方法(用的不多)
        static yaoweiba(){
            console.log("这是Animal的静态方法")
        }
    }
    
        const a1 = new Animal("金毛", 2)
        console.log(a1)
        a1.yaoweiba()   这是实例方法的调用
        Animal.yaoweiba()   这是静态方法的调用
    
    • class关键字的继承
    class Person{     //父类
        constructor(name,age){     //这里是公用样式
            this.name=name
            this.age=age
           }
        sayHello(){
            console.log("大家好")
            }
      }
    
    class American extends Person{    `// class 子类名 extends 父类名`
        constructor(name,age){
        super(name,age)                 `//如果写构造器了,则super()必须要有,而且必须放在构造器里的第一行`
            }
      }
    const am1 = new American("jack",20)
    console.log(am1)
    am1.sayHello()
    
    class Chinese extends Person{
         constructor(name,age,IdNumber){
            super(name,age)   
            this.IdNumber = IdNumber
          }
      }
    const ch1  = new Chinese("张三",22,"342422************")
    console.log(ch1)
    ch1.sayHello()
    
    • class关键字创建组件
    // 如果要使用 class 定义组件,必须 让自己的组件,继承自 React.Component
    class Person extends React.Component {
       constructor() {   //给class创建的组件绑定私有数据(普通创建不支持)
          super()
          // 只有调用了 super() 以后,才能使用 this 关键字
          this.state = { // 这个 this.state = {} 就相当于 Vue 中的 data() { return { } }
            msg: '大家好,我是 class 创建的 Person组件'
          }
        }
          // 在 组件内部,必须有 render 函数,作用:渲染当前组件对应的 虚拟DOM结构
          render(){
              // render 函数中,必须 返回合法的 JSX 虚拟DOM结构
            this.state.msg="msg的值被我修改了"   //state私有数据的值是可以修改的,而props是不可修改的
            return <div>
            <h5>这是 class 创建的组件---{this.props.name}---{this.props.age}---{this.props.wife}</h5>
            <h2>{this.state.msg}</h2></div>
    //在 class 关键字创建的组件中,如果想使用外界传递过来的 props 参数,不需接收,直接通过 this.props.属性名 访问
         }
    }
    
    const person={
        name:"林子闲",
        age:22,
        wife:"乔韵"
     }
    
    ReactDOM.render(<div>
      <Person name={person.name} age={person.age} wife={person.wife}></Person>     
     //必须用组件名以标签的形式调用
       <Person {...person}></Person>
    </div>,document.getElementById("list1"))
    
    使用CSS样式美化组件

    详细教程请看 https://www.bilibili.com/video/av25294556/?p=42 (第42集)

    1、先下载相关包
          cnpm i style-loader css-loader -D
    2、在webpack.config.js内的rules里配置如下代码
         { test: /.css$/, use: ['style-loader', 'css-loader']} 
    3、在src文件夹下创建css文件夹,再在里面创建css文件,然后写样式
          如 src > css > style1.css
          在style1.css里写样式
             .mystyle{
                  color:red;
                  font-size: 14px;
              }
    4、在相关文件中引入css文件
          import cssobj from "@/css/style1.css"    //这里固定写法cssobj,而非css
    5、接下来可以在相关文件中通过className给定样式了
          如<div className="mystyle">哈哈</div>
    
    CSS模块化——避免css样式污染全局代码问题,让其只在当前区域生效
    * css模块化只针对 `类选择器` 和 `id选择器` 生效
    1、 将webpack.config.js内的rules里的以下代码
         { test: /.css$/, use: ['style-loader', 'css-loader']} 改为
         { test: /.css$/, use: ['style-loader', 'css-loader?modules']} 
    2、 给定样式的方式改成
       如  <div className={cssobj.mystyle} id={css.obj.mystyle2}>哈哈</div>
    
    如果有某些css元素不想被模块化,想全局生效
    1、将webpack.config.js内的rules里的一下代码
         { test: /.css$/, use: ['style-loader', 'css-loader?modules']} 改为
         { test: /.css$/, use: ['style-loader', 'css-loader?modules&localIdentName=[path][name]-[local]-[hash:5]'] }
    //[path]  表示样式表 相对于项目根目录 所在路径
    //[name]  表示 样式表文件名称
    //[local]  表示样式的类名定义名称
    //[hash:length]  表示最多32位的hash值,length可以指定具体数值  
    2、  :global(.allstyle){    //这样写就不会被模块化了 :local(属性名)
          font-size: 12px;
          padding: 0;
      }
    3、然后在相关文件里引用
      <div className={cssobj.mystyle} className={.allstyle}>哈哈</div>
    也可以这么写
    <div className={cssobj.mystyle+" allstyle"}>哈哈</div>   //allstyle前面有空格哦
    也可以这么写
    <div className={[cssobj.mystyle,"allstyle"].join(" ")}>哈哈</div>   //空格哦
    
    在项目中启用模块化并同时使用bootstrap

    原理:第三方的样式表是以.css为后缀名,而我们将自己的样式用scss或less来做后缀名, 这样就可以区分开来自己的样式和第三方样式,从而可以给scss,less启用模块化,而不 影响第三方样式

    1、下载bootstrap包   cnpm i bootstrap -S
    2、下载包处理字体文件的url包   cnpm i url-loader -D    cnpm i file-loader -D
    3、webpack.config.js的rules里添加   { test:/.ttf|woff|woff2|eot|svg$/,use:'url-loader'}
    4、下载sass的包   cnpm i sass-loader node-sass -D
    5、webpack.config.js的rules里添加   { test:/.scss$/,use:['style-loader','css-loader?modules&localIdentName=[path][name]-[local]-[hash:5]','sass-loader']}
    6、将{ test: /.css$/, use: ['style-loader', 'css-loader?modules&localIdentName=[path][name]-[local]-[hash:5]','sass-loader'] }
       改为{ test: /.css$/, use: ['style-loader', 'css-loader'] }
    7、在相应jsx或js文件里引入   import "bootstrap/dist/css/bootstrap.css"  
       然后尽情发挥吧
    

    webpack.config.js里本阶段rules最终版如下

    rules: [
          {test: /.js|jsx$/,use: 'babel-loader',exclude: /node_modules/},
          { test: /.css$/, use: ['style-loader', 'css-loader'] },
          { test:/.ttf|woff|woff2|eot|svg$/,use:'url-loader'},
          { test:/.scss$/,use:['style-loader','css-loader?modules&localIdentName=[path][name]-[local]-[hash:5]','sass-loader']}
        ] 
    
    为按钮绑定事件及修改私有数据

    onClick onMouseenter onMouseover等 要采用小驼峰命名

    import React from "react"
    import "bootstrap/dist/css/bootstrap.css"
    
    export default class Hello extends React.Component{
      constructor(){
        super()
        this.state={
            msg: '我没被修改呢'
        }
      }
      render(){
        /*this.state.msg="我被一this.state.msg的方式修改了"*/
        return <div>
                <h5>这是一个Hello组件</h5><br/>
                <h5>{this.state.msg}</h5>
                <button className="btn btn-primary" onClick={ ()=>{this.myclickHandler(参数1,参数2)}} >按钮</button>         
    //函数调用用这种形式来写,可以不写参数  onClick={()=>{this.myclickHandler()}}
              </div>
    
      }
      myclickHandler=(a,b)=>{     //函数部分用箭头函数来写,可以不写参数a,b   myclickHandler=()=>{ }
        alert("我被点击了"+a+b);
        this.setState({       //若要修改私有数据state,react给定了一个方法 this.setState({ }),同时记住this.state.msg在这里不可用
          msg:'我被以this.setState的方式修改了'
        },function(){this.state.msg})   //此处为回调函数,可不加
      }
    }
    
    文本框与state值之间的双向绑定
    import React from 'react'
    
    export default class BindEvent extends React.Component {
        constructor() {
          super()
          this.state = {
            msg: '哈哈',
            age: 22,
          }
        }
    
        render() {
          return <div>
            {/* 需求:点击按钮,把修改 msg 的值 */}
            <button onClick={() => this.show('aa', 'bb')}>按钮</button>
            <h3>{this.state.msg}</h3>
    
    
            /* 如果 我们只是把 文本框的 value 属性,绑定到了 state 状态,但是,如果不提供   onChagne 处理函数的话,得到的文本框,将会是一个只读的文本框 */
            /* 当为文本框绑定 value 值以后,要么同时提供一个 readOnly, 要么,提供一个   onChange 处理函数 */
            /* <input type="text" style={{  '100%' }} value={this.state.msg} readOnly /> */
            <input type="text" style={{  '100%' }} value={this.state.msg} onChange={(e) => this.txtChanged(e)} />
                  </div>
        }
      
        // 每当文本框的内容变化了,必然会调用 这个 txtChanged
        txtChanged = (e) => {
          // 在 onChange 事件中,获取 文本框的值,通过事件参数 e 来获取
          // console.log(e.target.value);
    
          const newVal = e.target.value
    
          this.setState({
            msg: newVal
          })
      }
    

    快速搭建react项目

    1、电脑里新建文件夹
    2、npm create react-app 项目名称    如 npm create react-app huihuidemo / yarn create react-app huihuidemo
    3、cd 项目名称    如 cd huihuidemo
    4、npm run start
    5、安装antd    cnpm i antd -S / yarn add antd 
    6、在css文件中最顶部引入  @import '~antd/dist/antd.css';   //分号不能丢
        (也可在js文件里直接引入,  import 'antd/dist/antd.css';  )
    7、在js jsx文件中引入需要使用的组件   import {Button,Icon...} from 'antd';
    8、(以后必要)安装路由和ajax请求插件   yarn add react-router-dom axios 
    
    具体可见antd官网   https://ant.design/docs/react/use-with-create-react-app-cn
    
    解决react脚手架不支持less的问题
    1、安装less相关包    cnpm i less less-loader -S / yarn add less less-loader 
    2、暴露webpack    npm run eject / yarn eject   (此语句执行后会有config和scripts文件夹生成)   
          若出现以下错误: (Remove untracked files, stash or commit any changes, and try again.)
          是因为我们使用脚手架创建一个项目的时候,自动给我们增加了一个.gitignore文件,而我们本地却没有文件仓库
          这样解决: 先输入  git add .      再输入  git commit -m 'up' 
    3、找到webpack.config.js的const cssRegex = /.css$/; (第38行) 做出如下改动
        - const cssRegex = /.css$/;
        + const cssRegex = /.(css|less)$/;
    4、找到webpack.config.js的const loaders ,在里面最后一组后面添加
        { loader: require.resolve('less-loader') },
    添加之后是这样的:
    const loaders = [
          isEnvDevelopment && require.resolve('style-loader'),
          isEnvProduction && {...
           },
          {...
          },
          {...
          },
          {
            loader: require.resolve('less-loader')
          },
        ].filter(Boolean);
    5、大功告成
    
    ps:若npm start失败,出现这个问题(Build fails after eject: Cannot find module '@babel/plugin-transform-react-jsx' )
    则可以
    1、删除 node_modules 文件夹
    2、运行 yarn
    3、cnpm i less less-loader -S / yarn add less less-loader
    3、重新 npm start / yarn start
    
  • 相关阅读:
    poj4474 Scout YYF I(概率dp+矩阵快速幂)
    网络编程之TCP异步群聊:服务器端代码
    平衡树(AVL)详解
    网络编程之TCP异步群聊:客户端代码
    [置顶] android 图片库的封装
    oracle的nvl函数的使用解析
    七天美音英标学习总结
    软考(7)——看图心想 标准化和知识产权
    Node.js学习(7)----包
    Ubuntu bitnami gitlab 安装
  • 原文地址:https://www.cnblogs.com/huihuihero/p/10801094.html
Copyright © 2011-2022 走看看