1. webpack部分:
重点: modules: true, // 为false引入就是空对象, 无法使用
const path = require('path')
const webpack = require('webpack')
const webpackCommonConf = require('./webpack.common.js')
const { smart } = require('webpack-merge')
const { srcPath, distPath } = require('./paths.js')
const HotModuleReplacementPlugin = require('webpack/lib/HotModuleReplacementPlugin')
const DllReferencePlugin = require('webpack/lib/DllReferencePlugin')
module.exports = smart(webpackCommonConf, {
mode: 'development',
module: {
rules: [
// 直接引入图片 url
{
test: /\.(png|jpg|jpeg|gif)$/,
use: 'file-loader'
},
{
test: /\.css$/,
// loader 的执行顺序是:从后往前
loader: ['style-loader', {
loader: "css-loader",
options: {
sourceMap: true,
modules: true
},
}, 'postcss-loader'] // 加了 postcss
},
{
test: /\.scss$/,
// 增加 'less-loader' ,注意顺序
loader: ['style-loader', {
loader: "css-loader",
options: {
sourceMap: true,
modules: true,
}
}, {
loader: "sass-loader",
}]
}
]
},
// 输出source-map, 方便直接调试es6源码
devtool: 'source-map',
plugins: [
new webpack.DefinePlugin({
// window.ENV = 'development'
'process.env': {
NODE_ENV: JSON.stringify(process.env.NODE_ENV)
}
}),
// 热更新
new HotModuleReplacementPlugin(),
new DllReferencePlugin({
// 描述react动态链接库的文件内容(告知webpack索引的位置)
manifest: require(path.join(distPath, 'react.manifest.json')),
}),
],
devServer: {
hot: true,
port: 8111,
progress: true, // 显示打包的进度条
contentBase: distPath, // 根目录
open: false, // true:自动打开浏览器
compress: true, // 启动 gzip 压缩
// 设置代理
proxy: {
'/api': 'http://localhost:8000',
'/api2': {
target: 'http://localhost:8111',
pathRewrite: {
'/api2': ''
}
}
}
}
})
2. 组件使用:
import styles from 'xx/path';
然后在标签的className使用styles.xxx或者styles['xxx'], 有中划线或者下划线的需要使用style['xxx-xxx']
import React, { useState } from "react";
import connect from './connect';
import { mapStateTotProps } from "./mapStateToProps";
import { mapDispatchToProps } from "./mapDispatchToProps";
import styles from './TodoInput.scss'
// 子组件
const TodoInput = (props) => {
console.log(styles, 'styles')
const [text, setText] = useState("");
const {
addTodo,
showAll,
showFinished,
showNotFinish,
} = props;
const handleChangeText = (e: React.ChangeEvent) => {
setText((e.target as HTMLInputElement).value);
};
const handleAddTodo = () => {
if (!text) return;
addTodo({
id: new Date().getTime(),
text: text,
isFinished: false,
});
setText("");
};
return (
<div className={styles["todo-input"]}>
<input
type="text"
placeholder="请输入代办事项"
onChange={handleChangeText}
value={text}
/>
<button className={styles.btn} onClick={handleAddTodo}>+添加</button>
<button className={styles.btn} onClick={showAll}>show all</button>
<button className={styles.btn} onClick={showFinished}>show finished</button>
<button className={styles.btn} onClick={showNotFinish}>show not finish</button>
</div>
);
};
export default connect(mapStateTotProps, mapDispatchToProps)(TodoInput);
注意事项:
- 作为模块化引入使用相当于vue的style标签加scope的效果, 因为会对class类解析生成唯一性字符串, 而标签是不会解析的, 如果class类的名称不想被改变使用:global{...}
scss文件:
// :global写在里面, 因为外面的类的关系, 不会被全局样式影响
.todo-input {
:global {
.aaa {
color: red;
}
}
}
// 写在最外层作用域, class名称是aaa的, 全局都会被影响
:global {
.aaa {
color: red;
}
}
组件使用:
import styles from './TodoInput.scss'
<input
type="text"
placeholder="请输入代办事项"
onChange={handleChangeText}
value={text}
className="aaa"
/>
- 也支持import 'xxx.scss'语法, 不过就没有styles对象了, scss里面的类名叫什么写什么
组件使用:
import './TodoInput.scss'
<input
type="text"
placeholder="请输入代办事项"
onChange={handleChangeText}
value={text}
className="aaa"
/>
<button className="btn" onClick={handleAddTodo}>+添加</button>