本小节主要讲述在 React中使用css scss 以及其他第三方如bootstrap的css样式配置
1 前言
在 JSX 中,如果需要写行内样式,不能为 style 设置字符串的值,而是应该写成
style={{ color:'red',zIndex:3}}
在一个使用案例中上一篇中有写到,未设置样式前
设置style 样式后
import React from 'react';
import CourseItem from '@/components/CourseItem';
//父组件
export default class CourseList extends React.Component {
constructor(props) {
super(props);
this.state = {
courseList: [
{id: 1, userNmae: '张三', courseName: '语文'},
{id: 2, userNmae: '张三2', courseName: '语文2'},
{id: 3, userNmae: '张三3', courseName: '语文3'}
]
};
}
render() {
return (
<div>
{/*在JSX中行内样式需要如下这样写*/}
{/*需要注意的是,如果是纯数字类型的可以不写引号,如果是字符串类型的必须使用字符串包裹*/}
<h1 style={{color: 'red', fontSize: '22px', zIndex: 3, fontWeight: 200, textAlign: 'center'}}>课程统计列表</h1>
{/*这里通过map 来构建*/}
{this.state.courseList.map(item => <CourseItem {...item}/>)}
</div>
);
}
}
列表中条目的组件
//列表中条目的组件
import React from 'react';
export default class CourseItem extends React.Component {
render() {
return (
<div style={{border: '1px dashed #ccc', margin: '10px', padding: '10px', boxShadow: '0 0 5px'}}
key={this.props.id}>
<h2 style={{fontSize: '14px'}}>姓名:{this.props.userNmae}</h2>
<p style={{fontSize: '12px'}}>课程内容: {this.props.courseName}</p>
</div>
);
}
}
ReactDOM.render 渲染使用
//用来创建组件、虚拟DOM元素 生命周期
import React from 'react';
//所创建好的组件和虚拟DOM放到页面上展示
import ReactDOM from 'react-dom';
import CourseList from '@/components/CourseList'
//第三步 使用ReactDOM 把虚拟DOM 渲染到页面上
// 参数一 要渲染的虚拟DOM元素
// 参数二 指定页面上的容器
ReactDOM.render(<CourseList/>, document.getElementById('app'));
在上述案例代码中,通过行内设置样式,代码方面有点臃肿,所以在上述的案例中,我们可以把行内设置的样式进一步封装
2 对style样式的封装
2.1 第一层封装
//列表中条目的组件
import React from 'react';
//第一层封装
const itemStyle = {border: '1px dashed #ccc', margin: '10px', padding: '10px', boxShadow: '0 0 5px'};
const itemUserStyle = {fontSize: '14px'};
const itemCourseStyle = {fontSize: '12px'};
export default class CourseItem extends React.Component {
render() {
return (
<div style={itemStyle} key={this.props.id}>
<h2 style={itemUserStyle}>姓名:{this.props.userNmae}</h2>
<p style={itemCourseStyle}>课程内容: {this.props.courseName}</p>
</div>
);
}
}
2.2 第二层封装
import React from 'react';
//第二层封装
const courseItemStyle={
item:{border: '1px dashed #ccc', margin: '10px', padding: '10px', boxShadow: '0 0 5px'},
itemUser:{fontSize:"14px"},
itemCourse:{fontSize:"12px"}
}
export default class CourseItem extends React.Component {
render() {
return (
<div style={courseItemStyle.item} key={this.props.id}>
<h2 style={courseItemStyle.itemUser}>姓名:{this.props.userNmae}</h2>
<p style={courseItemStyle.itemCourse}>课程内容: {this.props.courseName}</p>
</div>
);
}
}
2.3 第三层封装 封装成单独的js文件
然后在使用的时候引入文件
//用来创建组件、虚拟DOM元素 生命周期
import React from 'react';
//所创建好的组件和虚拟DOM放到页面上展示
import ReactDOM from 'react-dom';
import CourseList from '@/components/CourseList'
//第三步 使用ReactDOM 把虚拟DOM 渲染到页面上
// 参数一 要渲染的虚拟DOM元素
// 参数二 指定页面上的容器
ReactDOM.render(<CourseList/>, document.getElementById('app'));
3 使用css样式文件
安装style-loader
cnpm i style-loader css-loader -d
然后在 webpack.config.js 中配置
然后创建 css 样式表
然后在使用的时候引入 css 文件
在上述中通过 import 导入了 css 样式文件,这个样式文件中设定的样式默认是在全局上都有作用,所以这里可以定义 css 样式的作用域,在 webpack.config.js 文件中配置 css-loader 的模块化
const path = require('path');
//导入插件
const HtmlWebPackPlugin = require('html-webpack-plugin');
//创建插件
const htmlPlugin = new HtmlWebPackPlugin({
template:path.join(__dirname,'./src/index.html'),//源文件
filename: 'index.html' //生成内存中首页面的名称
});
//Node.js 两种导出模块的方式:module.exports和exports
//module和exports是Node.js给每个js文件内置的两个对象
//webpack 默认只能打包处理 .js 后缀名类型的文件
module.exports = {
mode: 'development',// production development
//引用插件
plugins: [
htmlPlugin
],
//所有的第三方模块的配置规则
module: {
//匹配规则
rules: [
{test:/\.js|jsx$/,use:'babel-loader',exclude:/node_modules/},
// modules 为精通的css样式文件启动模块化
{test:/\.css$/,use:['style-loader','css-loader?modules']}
]
},
resolve: {
//这里配置这几个文件的后缀名可以省略不写
extensions: ['.js','.jsx','.json','.css'],
//配制别名@ 表示项目根目录中 src的这一层路径
alias:{'@':path.join(__dirname,'./src')}
}
};
启用 css-loader 的模块化功能后,在使用css样式时
在这里需要注意的是,css 模块化,只针对 类选择器与 ID 选择器,不会将标签选择器模块化
在上述效果图中,我们可以看到实际中的class名称是自动行形成的,在这里,我们可以 通过 css-loader 添加参数 localIdentName 来自定义生成的类名格式
- [ path ] 表示样式表相对于根目录所在的路径
- [ name ] 表示样式表文件名称
- [ local ] 表示样式的类名定义名称
- [ hash:length ] 表示32位的 hash 值
例如我们配置如下的规则
//所有的第三方模块的配置规则
module: {
//匹配规则
rules: [
{test:/\.js|jsx$/,use:'babel-loader',exclude:/node_modules/},
// modules 为精通的css样式文件启动模块化
// 这里通过 localIdentName 来配置生成的类名
{test:/\.css$/,use:['style-loader','css-loader?modules&localIdentName=[path][name]-[local]-[hash:5]']}
]
},
上述这样配置是 css-loader 老版本的写法,如果css-loader用的新版本,那么会有异常
ERROR in ./src/css/CourseList.css (./node_modules/_css-loader@3.4.2@css-loader/dist/cjs.js?modules&localIdentName=[path][name]-[local]-[hash:5]!./src/css/CourseList.css)
Module build failed (from ./node_modules/_css-loader@3.4.2@css-loader/dist/cjs.js):
ValidationError: Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
- options has an unknown property 'localIdentName'. These properties are valid:
object { url?, import?, modules?, sourceMap?, importLoaders?, localsConvention?, onlyLocals?, esModule? }
at validate (/Volumes/code/react-study/demo2/node_modules/_schema-utils@2.6.4@schema-utils/dist/validate.js:85:11)
at Object.loader (/Volumes/code/react-study/demo2/node_modules/_css-loader@3.4.2@css-loader/dist/index.js:34:28)
@ ./src/css/CourseList.css 2:26-168 22:4-35:5 25:25-167
@ ./src/components/CourseList.jsx
@ ./src/index.js
那么在高版本的 css-loader 中 ,webpack.config.js 中可以这样配置
//所有的第三方模块的配置规则
module: {
//匹配规则
rules: [
{test: /\.js|jsx$/, use: 'babel-loader', exclude: /node_modules/},
// modules 为精通的css样式文件启动模块化
// 这里通过 localIdentName 来配置生成的类名
{
test: /\.css$/, use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules:{
getLocalIdent: (context, localIdentName, localName, options) => {
return localName;
},
}
}
}
]
}
]
},
然后在浏览器中
在实际开发中,对与 css 文件中启动了模块化,那么当使用 :global 关键字包裹的 类选择器不会被配置模块化
.title {
color: red;
text-align: center;
font-size: 16px;
}
/*这里是全局的*/
:global(.test) {
color: green;
font-size: 18px;
}
4 使用其他三方样式库
例如使用 bootstrap
cnpm i bootstrap@3.3.7 -S
cnpm i sass-loader node-sass -D
cnpm i url-loader -D
cnpm i file-loader -D
处理css中的图片资源时,我们常用的两种loader是file-loader或者url-loader,两者的主要差异在于。url-loader可以设置图片大小限制,当图片超过限制时,其表现行为等同于file-loader,而当图片不超过限制时,则会将图片以base64的形式打包进css文件,以减少请求次数。
sass-loader 用来加载 SASS / SCSS 文件并将其编译为 CSS,
sass-loader 依赖于node-sass
项目中自己创建的样式表定义为 .scss 文件,第三方的样式表还是以 .css 结尾,那么在当前项目中只为自己项目中创建的 .scss 文件启动模块化
然后在 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' //生成内存中首页面的名称
});
//Node.js 两种导出模块的方式:module.exports和exports
//module和exports是Node.js给每个js文件内置的两个对象
//webpack 默认只能打包处理 .js 后缀名类型的文件
module.exports = {
mode: 'development',// production development
//引用插件
plugins: [
htmlPlugin
],
//所有的第三方模块的配置规则
module: {
//匹配规则
rules: [
{test: /\.js|jsx$/, use: 'babel-loader', exclude: /node_modules/},
// modules 为精通的css样式文件启动模块化
// 这里通过 localIdentName 来配置生成的类名
// 一般第三方的样式表都是 .css 结尾的,然后自己项目中创建的样式表可以使用 .scss 或者 less 结尾
{
test: /\.scss$/, use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules:{
getLocalIdent: (context, localIdentName, localName, options) => {
return localName;
},
}
}
},
'sass-loader'
]
},
// 这里配置 css 的规则
{test:/\.css$/, use: ['style-loader','css-loader']},
// 这里配置 字体等规则
{test:/\.ttf|woff|woff2|eot|svg$/,use:'url-loader'},
]
},
resolve: {
//这里配置这几个文件的后缀名可以省略不写
extensions: ['.js', '.jsx', '.json', '.css','.scss'],
//配制别名@ 表示项目根目录中 src的这一层路径
alias: {'@': path.join(__dirname, './src')}
}
};
然后在项目中 使用 bootstrap
然后效果预览
完结