React 学习第三天

# React 第三天学习

在 react 项目中 添加样式

加载外部 css 样式文件

css 样式作用域的问题(modules,localIdentName, local 和 global)

在 React 项目中 使用 bootsrtap( 使用 sass )

React 中 绑定事件

React 中双向绑定事件(e.target.value 和 this.refs.txt.value)

React 组件的生命周期

Dream what you want to dream; go where you want to go; be what you want to be, because you have only one life and one chance to do all the things you want to do!

做你想做的梦吧,去你想去的地方吧,成为你想成为的人吧,因为你只有一次生命,一个机会去做所有那些你想做的事。

# 在 react 项目中 添加样式

# 第一种方式:

<h1 style={{ color: "red", fontSize: "50px" }}>这是评论列表组件</h1>

# 第一层封装:

将样式对象抽离出来

const cmtStyle={color:'red',fontSize:'30px'}

<h1 style={cmtStyle}>这是评论列表组件</h1>

# 第二层封装:

合并成一个大的样式对象

import React from "react";

const styles = {
  Item: { border: "1px dashed #ccc", margin: "10px 10px" },
  user: { color: "#333" },
  content: { color: "green", fontSize: "22px" },
};

export default function CmtItem(props) {
  return (
    <div style={styles.Item}>
      <h3 style={styles.user}>评论人:{props.user}</h3>
      <p style={styles.content}>评论内容:{props.content}</p>
    </div>
  );
}

mark

# 第三层封装

抽离为单独的 样式表模块

mark

CmtItem.jsx

import React from 'react
import styles from '@/components/styles'

export default function CmtItem(props) {
    return <div style={styles.Item}>
        <h3 style={styles.user}>评论人:{props.user}</h3>
        <p style={styles.content}>评论内容:{props.content}</p>
    </div>
}

styles.js:

export default {
  Item: { border: "1px dashed #ccc", margin: "10px 10px" },
  user: { color: "#333" },
  content: { color: "green", fontSize: "22px" },
};

# 加载外部 css 样式文件

index.js:

import React from "react"; //创建组件,虚拟DOM元素,生命周期
import ReactDOM from "react-dom"; //把创建好的 组件 和 虚拟DOM 放到页面上展示的

import CmtList from "@/components/CmtList";

//使用 ReactDOM 把虚拟 DOM 渲染到页面上
ReactDOM.render(
  <div>
    <CmtList></CmtList>
  </div>,
  document.getElementById("app")
);

CmtList.jsx

import React from "react";
import CmtItem from '@/components/CmtItem'

const cmtStyle = {color: 'red', fontSize: '30px', textAlign: 'center'}
import cssobj from cmtList.scss


export default 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: '到处happy'},
                {id: 5, user: '周琛', content: '帅的不要不要了!'}
            ]
        }
    }

    render() {
        return <div>
            <h1>这是评论列表组件</h1>
            {this.state.CommentList.map(item =>
                <CmtItem {...item} key={item.id}></CmtItem>
            )}

        </div>
    }
}

CmtItem.jsx

import React from "react";

import styles from "@/components/styles";

export default function CmtItem(props) {
  return (
    <div style={styles.Item}>
      <h1 style={styles.user}>评论人:{props.user}</h1>
      <p>评论内容:{props.content}</p>
    </div>
  );
}

webpack.config.js:

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: "production",
  devServer: {
    open: true,
    port: 3000,
    contentBase: path.join(__dirname, "src"),
  },
  plugins: [htmlplugin],
  module: {
    rules: [
      {
        test: /\.m?js|jsx$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: "babel-loader",
          options: {
            presets: [
              "@babel/preset-env",
              [
                "@babel/preset-react",
                {
                  pragmaFrag: "DomFrag", // default is React.Fragment
                  throwIfNamespace: false, // defaults to true
                },
              ],
            ],
            plugins: ["@babel/plugin-proposal-class-properties"],
          },
        },
      },
      { test: /\.css$/, use: ["style-loader,css-loader"] },
    ],
  },
  resolve: {
    extensions: [".js", ".jsx", ".json"],
    alias: {
      "@": path.join(__dirname, "./src"), //这样,@ 就表示 项目根目录中 的src 这一层路径
    },
  },
};

# 配置好相应的文件后,但是却意外的发生了错误!

mark

查阅资料:参考 [Error: Cannot resolve module ‘style-loader’](https://stackoverflow.com/questions/35171288/error-cannot-resolve-module-style-loader)

但是不知咋地,我瞎弄了一下,突然就好了!~

结果

mark

# 引出 css 样式作用域的问题

# 给普通样式表加模块化

CSS MODULE 是一种 css in javascript 的方式,当我们把一个 css 文件 import 到一个 js 模块时,这个 css 文件会暴露一个对象,这个对象映射所有的本地和全局 css 类名

你真的知道 css-loader 怎么用吗?

# modules

操作

  • 配置 webpack.config.js: 追加参数 modules:表示为 普通的 css 样式表,启用模块化。
{test:/\.css$/,use:['style-loader','css-loader?modules']}

注意

  • css 模块化,只针对 类选择器Id 选择器生效。
  • css 模块化,不会将 标签选择器 模块化。

使用

import cssobj from cmtList.scss

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

mark

# localIdentName

通常 modules 参数还要通过 localIdentName 的配合来设置 css 的类名。在上文中我们看到没有设置 localIdentName 的 css 编译后是一串随机字符串,可读性很差,因此我们还需要对它的类名进行处理,这就用到了 localIdentName。

mark

使用 localIdentName 设置 css-modules 模式下 local 类名的命名。

例如

【path】:

{test:/\.css$/,use:['style-loader','css-loader?modules&localIdentName=[path]']}

mark

【path】【name】:

{test:/\.css$/,use:['style-loader','css-loader?modules&localIdentName=[path][name]']}

mark

【path】【name】【local】:

{test:/\.css$/,use:['style-loader','css-loader?modules&localIdentName=[path][name]-[local]']}

mark

【path】【name】【local】【hash】:

{test:/\.css$/,use:['style-loader','css-loader?modules&localIdentName=[path][name]-[local]-[hash]']}

mark

# 通过 local 和 global 设置类名是否被模块化

:local() 包裹起来的类名,会被模块化,默认情况下,所有的类名和 ID 都被模块化了。

被 :global () 包裹起来的类名,不会被模块化,而会全局生效。

需求

mark

解决方案: 可以参考

:global(.test) {
  margin: 10px 10px;
}

结果

  • test 类名 未被模块化 ,而是 全局生效

mark

# 在 React 项目中 使用 bootsrtap

  1. 安装 bootstrap 我一般使用 3.3.7 版本
npm i bootstrap@3.3.7 -S
  1. 安装 相关 路径 图标 加载依赖
npm i url-loader file-loader -D
  1. 配置 webpack-config-js 文件
{test:/\.ttf|woff|woff2|eot|svg$/,use:'url-loader'}
  1. 导入 bootstrap 包 并且 使用 bootstrap 类
import bootcss from "bootstrap/dist/css/bootstrap.min.css";

<button className={[bootcss.btn, bootcss["btn-primary"]].join(" ")}>
  点我
</button>;

mark

# 升级:

问题:className={[bootcss.btn,bootcss [‘btn-primary’]].join (’ ')} 这样调用太麻烦了

自己规定

第三方的 样式表:(例如: bootsrtap 等) 都是以 .css 结尾,这样,我们不要为普通的 .css 启用模块化。

自己定义样式表:都要以 .scss 或 .less 结尾,只为 .scss 或 .less 结尾的启用模块化。

# 使用 sass

Sass/Scss、Less 是什么?

  1. 安装:
npm i sass-loader node-sass -D
  1. 配置 webpack.comfig.js :
{test:/\.css$/,use:['style-loader','css-loader']},

{test:/\.scss/,use:['style-loader','css-loader?modules&localIdentName=[path][name]-[local]-[hash:5]','sass-loader']}
  1. 导入 bootstrap 包 并且 使用 bootstrap 类只用导入第三方路径即可
import "bootstrap/dist/css/bootstrap.min.css";

<button className="btn btn-danger">点我</button>;

mark

# React 中 绑定事件

# 基本使用

BindEvent.jsx:

import React from "react";

export default class BindEvent extends React.Component {
  constructor() {
    super();
    this.state = {};
  }
  render() {
    return (
      <div>
        BindEvent组件
        <hr />
        <button
          onClick={function () {
            console.log("ok");
          }}
        >
          按钮
        </button>
      </div>
    );
  }
}

mark

分离

import React from "react";

export default class BindEvent extends React.Component {
  constructor() {
    super();
    this.state = {};
  }

  render() {
    return (
      <div>
        <h1>BindEvent组件!</h1>
        <hr />
        <button
          onClick={() => {
            this.myClickHandler();
          }}
        >
          你敢点我吗?
        </button>
      </div>
    );
  }

  myClickHandler = () => {
    alert("这是myClickHandler方法!");
  };
}

mark

传递参数

import React from "react";

export default class BindEvent extends React.Component {
  constructor() {
    super();
    this.state = {};
  }

  render() {
    return (
      <div>
        <h1>BindEvent组件!</h1>
        <hr />
        <button
          onClick={() => {
            this.myClickHandler("哈哈哈哈哈哈!");
          }}
        >
          你敢点我吗?
        </button>
      </div>
    );
  }

  myClickHandler = (arg1) => {
    alert("这是myClickHandler方法!" + arg1);
  };
}

mark

# 需求:点击按钮,改变 this.state 里面的值

this.setState 方法的使用

注意:this.setState 方法的执行是 异步

mark

import React from "react";

export default class BindEvent extends React.Component {
  constructor() {
    super();
    this.state = {
      msg: "周琛!",
    };
  }

  render() {
    return (
      <div>
        <h1>BindEvent组件!</h1>
        <hr />
        <button
          onClick={() => {
            this.myClickHandler("哈哈哈哈哈哈!", "大傻瓜!");
          }}
        >
          你敢点我吗?
        </button>
        <h3>{this.state.msg}</h3>
      </div>
    );
  }

  myClickHandler = (arg1, arg2) => {
    // alert('这是myClickHandler方法!'+arg1+arg2)
    this.setState({
      msg: "张三",
    });
  };
}

mark

注意:在执行 this.setState 后,又想立即拿到最新的 state 值,需要使用 this.setState ({},callback)

myClickHandler = (arg1, arg2) => {
  // alert('这是myClickHandler方法!'+arg1+arg2)
  this.setState(
    {
      msg: "张三" + arg1 + arg2,
    },
    function () {
      console.log(this.state.msg);
    }
  );
};

# React 中绑定文本框与 State 中的值

类似于 Vue 的双向绑定

# 第一种双向绑定实现方式

<input
  type="text"
  style={{ width: "100%" }}
  value={this.state.msg}
  onChange={(e) => this.txtChanged(e)}
/>;

txtChanged = (e) => {
  this.setState({
    msg: e.target.value,
  });
};

mark

# 使用 ref 获取 DOM 元素引用

Vue 中,Vue 为页面上的元素提供了 ref 的属性,获取元素引用,则需要使用 this.$refs 引用名称

React 中 获取元素的引用 :this.refs

第二种双向绑定实现方式

<input
  type="text"
  style={{ width: "100%" }}
  value={this.state.msg}
  onChange={(e) => this.txtChanged(e)}
  ref="txt"
/>;

txtChanged = (e) => {
  this.setState({
    msg: this.refs.txt.value,
  });
};

# React 组件的生命周期

可以参考

mark

如图,React 生命周期主要包括三个阶段:初始化阶段、运行中阶段和销毁阶段,在 React 不同的生命周期里,会依次触发不同的钩子函数,下面我们就来详细介绍一下 React 的生命周期函数

Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2015-2021 zhou chen
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信