碰到的一些的问题
启动本地服务,停止,没有解除端口占用。
- 问题描述:
yarn start 启动,Ctrl+C 停止服务。在同一窗口启动服务,或者未关闭窗口在另一个窗口启动此服务,提示当前端口还在占用,并没有停止。
- 环境:
WIN 10,git bash
- 原因:
webpack-dev-server 端口占用的问题
解决方案:
- 使用 windows 自带的 cmd 执行 npm run dev ,可以通过 ctrl+c 杀死 node 进程
- 直接在 git Bash 中 task kill node,直接 kill node 进程
- 多按几次 ctrl+c(个人习惯此种方式)
参考: windows 系统下 webpack-dev-server 占用端口
react 中 less 样式未生效
-
产生了什么问题?
配置好了 less-loader,但引用.less 文件,样式并未生效,以下是对应的 webpack 配置。
{
test: /\.less$/,
exclude: /node_modules/,
use: [
"style-loader",
{
loader: "css-loader",
options: {
modules: true,//开启了css modules
localIdentName: '[path][name]__[local]--[hash:base64:5]'//定义哈希类名
importLoaders: 2,
localsConvention: "camelCase",
esModule: true,
sourceMap: true,
},
},
{
loader: "postcss-loader",
options: {
sourceMap: true,
},
},
{
loader: "less-loader",
options: {
sourceMap: true,
lessOptions: {
javascriptEnabled: true,
},
},
},
],
}
-
上网查询,分析原因:
css-loader 自带 css modules,会把所有类名编译为哈希字符串.less 文件中写的样式已经被重命名了,但 react 中的 className 并没有一起被处理。
-
解决方案:
-
按 css modules 的方式引用样式,使用
style.cptbutton
import style from './index.less';
-
css modules 使用全局作用域。
在 less 文件中,所有内容外用:global 语法 包裹住。:global 声明一个全局规则,凡是这样声明的 class,都不会被编译成哈希字符串。
-
webpack css-loader,可以直接设置禁用 css modules。
-
-
什么是 css modules
css modules,是通过构建工具达到样式的 scope。
-
css modules 解决了什么问题
避免全局命名冲突,只需要保证组件内的命名不冲突,因为命名会被编译。
这里也踩过坑,有的项目没有开启 css modules,同事也没注意写的 css 的作用域,本来已经完成的页面,布局被同事写的 css 覆盖搞乱了!最后自己得背锅,泪的教训 😥!还是开启 css modules 好了,再也不用担心 css 命名冲突了~😆
解决选择器嵌套层次过深的问题。
模块化:可以使用 composes 来引入自身模块中的样式以及另一个模块的样式。
checkbox 监听不生效
-
产生了什么问题:
react 组件里的 checkbox 上的监听事件不生效。
-
问题的背景:
组件用 react,antd,但整体项目是 jsp。事件,请求使用 requirejs,jquery。
原来写在普通 dom 结构里的 checkbox,点击事件正常。移动至 react 组件内 checkbox 的点击事件不生效,监听不见了。
react 是用 script 标签,以及 babel 运行时进行转换的。
-
分析原因:
可能监听事件的函数在先,react 的 checkbox 在后,监听事件没拿到对应的元素。所以将 react 的 script 标签移动至最前面,但未生效。
通过简单的 demo 尝试,在 cra 脚手架的 react 组件里写 checkbox,并在 index.html 添加 dom 事件,发现事件生效。所以与单纯的框架,组件没有关系,原因应该就是监听的元素丢失。
为什么没有监听到对应的元素呢?通过在浏览器调试,添加监听的时候控制台打出这个元素,发现监听事件时的元素与在后面点击的元素不是一个 😂
为什么不是同一个元素了?监听事件是写在原来的结构里,使用 requirejs,只加载一次,监听了第一次 dom 结构的对应元素。但碰巧的是,第一次 dom 里对应的 checkbox 是不显示的。在进行了其他的操作,使 react 重新渲染了,重新 render,对应元素已经被卸载又重新加载了。
-
解决方案:
在不移动针对此事件的各种操作的前提下,使用事件委托,监听事件添加到了父元素或者爷爷元素等不变元素,通过 e.target 确定点击的范围,达到了想要的目的。
-
总结:
之前在完全的 react 项目中,如果对一个元素添加事件,是在组件内部,didMount 的时候添加监听,willUnmount 的时候清楚监听。即使 react 重新渲染,也会在 didmount 的时候再添加监听,确保每次监听是生效的。而这次监听事件在 react 外,在重新渲染后监听事件丢失了。
-
再次总结:
按照高内聚的思想,我把原来的 checkbox 移动至 react 里,但是针对他的行为,事件没有移动至 react 内,造成了这个问题。如果事件按照 react 组件内部的行为模式(didMount 添加监听),不会产生监听失效的问题。但是原来针对此元素的事件,以及原生 dom 操作耦合性太强,比较复杂,暂且继续使用。移动至 react 内的工作量比较大,也可能会产生新的问题。
-
针对这个问题再说两句,不就是一个 render 重新渲染,对应元素卸载重新挂载的问题嘛,不知不觉扯了这么多。😜
为什么我把对应的 checkbox 移动到了 react 里,因为新加的一些功能,按照 UI 要使用 antd。之前的一部分可以算作属于新加的大功能内部的,为了这部分的 UI 一致性。
那为什么不把对应的事件,原来相关的所有逻辑都移动进来呢?没有移进来确实在整体的结构上不够好,至少我理解的是没有高内聚。但是目前的要求是业务优先,稳定是重要的。自己重构了这一小部分的逻辑,是没有对应的测试来帮忙覆盖的,只有自测,对自测并不是很自信...之前是有改某一块就把部分逻辑重构了,但是很危险...在公司人手不是很富裕的情况下,贸然重构的风险太大。
在本菜菜的角度,原来的逻辑不是很清楚的情况下是不能贸然重构的。重构的基础是,你对原来的功能逻辑足够熟悉,能够和前端负责人,产品对整体的功能逻辑沟通。并在重构后,安排一定量的测试。