0%

问题

组件输出的是 html 字符串,期望能直接渲染出来而不是用字符串形式显示

1
2
let a = "<br>123<br>456"
<div>{a}</div>

解决方法

使用 dangerouslySetInnerHTML 方法,见官方文档: dangerouslySetInnerHTML

1
2
let a = "<br>123<br>456"
<div dangerouslySetInnerHTML={{__html: a}} />

后记

翻译一下方法名:危险的设置 InnerHTML,要注意一下

问题

项目引入了一个js文件,这个js文件不符合eslint规范但却很nb,就期望eslint忽略对这个js文件的检查

至于问我为什么不重构?时间不够啊。

解决问题

解法方法很简单,见官方文档:eslintignore

在项目文件夹下创建 .eslintignore 文件

1
src/xxxx

需求

React 父组件主动触发子组件的方法

解决方法

主要用到了 useRef useImperativeHandle forwardRef 3 个方法

子组件代码如下,用 useImperativeHandle 将方法暴露出去

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import React, { useState, useImperativeHandle, forwardRef } from 'react';
import { MyComponent } from 'my-component';

const Children = forwardRef((props, ref) => {
const [myState, setMyState] = useState([]);
useImperativeHandle(
ref,
() => ({
myState,
setMyState,
}),
[myState]
);
return <MyComponent {...props} />;
});

export default Children;

父组件代码如下,主要是用 useRef

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import React, { useState, useRef } from 'react';
import Children from 'children';

const Parent = (props, ref) => {
const [ref] = useRef(null);

const setState = (params) => {
ref.current.setMyState(params);
};

const getState = () => {
console.log('getState :>> ', ref.current.myState);
};

return (
<div>
<div
onClick={() => {
setState(1111);
}}>
setState
</div>
<div
onClick={() => {
getState();
}}>
getState
</div>
<Children ref={ref} />
</div>
);
};

后记

这个最好看一下react官方文档

公司的脚手架竟然没有加载 svg 图标功能?导致我引入 svg 图片失败。

解决方法

webpack 用 file-loader 引入 svg 图标文件

1
2
3
4
5
6
7
8
9
10
module.exports = {
module: {
rules: [
{
test: /\.svg/,
use: ['file-loader'],
},
],
},
};

后记

当然,用 url-loader 应该也有效果。但是由于我不知道公司的脚手架内部的 url-loader 配置是什么样的,所以我没有覆盖 url-loader 的配置。

问题

需要这两个格式的数据,能够互相转换。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
let obj = {
a: 123,
b: { a: 456, b: 789, c: { d: 111, e: 222 } },
f: 11,
};

let arr = [
{ name: 'a', value: 123 },
{
name: 'b',
value: undefined,
children: [
{ name: 'a', value: 456 },
{ name: 'b', value: 789 },
{
name: 'c',
value: undefined,
children: [
{ name: 'd', value: 111 },
{ name: 'e', value: 222 },
],
},
],
},
{ name: 'f', value: 111 },
];

注意,对象名称为 name,对象的值不一定是 value,对象的值遇见 children 的时候,是个对象。

解决问题

我用的是循环递归,因为我太菜了

群里说的有 BFS 什么的,我知道这东西也大概用过,但说来惭愧,不会。

这个循环递归的方法有个大佬说还会爆栈,内存溢出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 数组转对象
function arrayToObject(params) {
let obj = {};
for (let index = 0; index < params.length; index++) {
const element = params[index];
const { name, value } = element;
if ('children' in element) {
obj[name] = arrayToObject(element.children);
} else {
obj[name] = value;
}
}
return obj;
}

// 对象转数组
function ObjectToArray(params) {
let array = [];
for (const key in params) {
if (Object.hasOwnProperty.call(params, key)) {
const element = params[key];
if (Object.prototype.toString.call(element) === '[object Object]') {
array.push({ name: key, value: undefined, children: ObjectToArray(element) });
} else {
array.push({ name: key, value: element });
}
}
}
return array;
}

console.log(arrayToObject(arr));
console.log(ObjectToArray(obj));

求更好的解法

目前没有求到更好的解法,我先把解法和代码贴出来。

  • 2021年5月17日补充群友德巨Kio的回答
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const o2a = (o) =>
Object
.entries(o)
.map(([name, value]) =>
typeof value !== 'object'
? { name, value }
: { name, value: undefined, children: o2a(value) }
);

const a2o = (a) =>
a.reduce(
(o, i) => ({ ...o, [i['name']]: i['value'] ?? a2o(i['children']) }),
{}
);

问题

只要有一个对象的值为非 true,则返回 true

1
2
3
4
5
6
let test = {
a: true,
b: true,
c: true,
d: false,
};

解决方法

我自己开始傻傻的写了个循环去判断,群里也顺便问了一下有没有更优雅的解法,还真有

我的写法

1
2
3
4
5
6
7
8
9
10
11
function isTrue(params) {
for (const key in params) {
if (Object.hasOwnProperty.call(params, key)) {
const element = params[key];
if (element !== true) {
return false;
}
}
}
return true;
}

群友(@北京-菜鸟-板板/yt )的解法

1
Object.values(test).every((item) => item === true);

大佬的解法是不是更优雅?

后记

后来期望加一个可以复位对象的值为 false 的方法

1
2
3
4
5
6
7
8
9
function resetFalse(params) {
let obj = {};
for (const key in params) {
if (Object.hasOwnProperty.call(params, key)) {
obj[key] = false;
}
}
return obj;
}

在群里问了一圈,被 diss 了,没错,被 diss 了。这都是简单的基操,,我就是想提升一下自己,学习更好的解法。

碰到了个问题,就是子元素设置了 position: absolute; 但是没有相对于上一级的父元素进行定位

我当时 我直接疑惑.jpg 这个表情

后来查了一下,原来是上一级的父元素要设置 position: relative; 属性

需求

元素 A 相对于元素 B 定位

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
#father {
position: relative;
}

#son1 {
position: absolute;
top: 0;
}

#son2 {
position: absolute;
bottom: 0;
}
1
2
3
4
<div id="father">
<div id="son1"></div>
<div id="son2"></div>
</div>

自嘲

3年了,3年了!你前端弄了3年了,这都不知道?

css 最基础的相对定位都不会,这前端怕是白学了

后记

等会,为啥父元素要加 position: relative; 才能生效?

被大佬Diss

你谈的是css样式表,是针对HTML元素生效的, 不是针对什么组件生效的

原来文章中用的是 “组件”

文章中的 “组件” 修改为 “元素”

感谢这位大佬。云香水识,然后这位大佬在招人,Flow+了解一下?

PS: 进这个大佬厂子一年,有大佬带,进去一年顶普通厂子三年,想去的可以给我留言。

我实在是太菜了,一个前端,连这个都不会,还需要查?

CSS :: child set to change color on parent hover, but changes also when hovered itself

需求

鼠标移到父 div 的时候,子 div 显示,鼠标移出父 div 的时候,子 div 隐藏。

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
.parent {
padding: 50px;
border: 1px solid black;
}

.parent span {
position: absolute;
top: 200px;
padding: 30px;
border: 10px solid green;
}

.parent:hover span {
border: 10px solid red;
}

.parent span:hover {
border: 10px solid green;
}
1
2
3
4
<a class="parent">
Parent text
<span>Child text</span>
</a>

自嘲

一个快 3 年的前端,连着都没玩过,还要查资料确认,乐色 乐色 真的乐色 too low

梵大的第一道题,怎么构建一个 express,入口函数实现。

这儿指的应该不是用 express,用 express 太简单了。。

应该是用 node 的 api 实现一个简单的 express。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const http = require('http');
const url = require('url');
const fs = require('fs');

http
.createServer(function (req, res) {

let { url: requestUrl } = req
let q = url.parse(requestUrl, true);

var filename = '.' + q.pathname;

fs.readFile(filename, function (err, data) {
if (err) {
res.writeHead(404, { 'Content-Type': 'text/html' });
return res.end('404');
}
res.writeHead(200, { 'Content-Type': 'text/html' });
res.write(data);
return res.end();
});
})
.listen(8080);

后记

开始我没加入

1
res.writeHead(200, { 'Content-Type': 'text/plain;charset=utf-8' });

这行代码,然后返回的中文是乱码的

然后我查了一下资料加上了这段话就好了。

等一下,还有,这是第一题的具体要求,我只写了简单的http模块,url处理

还有3、4我还没写

  1. http 模块
  2. url 处理
  3. 路由识别, 优先级
  4. 资源识别、响应头设置、压缩、流式输出、缓存

函数实现
next 怎么处理

我的项目中,有个可编辑表单,多次复用了一个组件,但是父组件更新时,总是会更新子组件。然后页面就会有略卡的感觉,我意识到我应该优化一下项目了。

我查了一下 React 提供了 React.memo 方法可以让子组件在 prop 未发生变化的时候,不重新刷新 dom

参见 React.memo

React.memo

1
2
3
4
const MyComponent = React.memo(function MyComponent(props) {
/* 使用 props 渲染 */
});
React.memo 为高阶组件。

如果你的组件在相同 props 的情况下渲染相同的结果,那么你可以通过将其包装在 React.memo 中调用,以此通过记忆组件渲染结果的方式来提高组件的性能表现。这意味着在这种情况下,React 将跳过渲染组件的操作并直接复用最近一次渲染的结果。

React.memo 仅检查 props 变更。如果函数组件被 React.memo 包裹,且其实现中拥有 useStateuseReduceruseContextHook,当 context 发生变化时,它仍会重新渲染。

默认情况下其只会对复杂对象做浅层对比,如果你想要控制对比过程,那么请将自定义的比较函数通过第二个参数传入来实现。

1
2
3
4
5
6
7
8
9
10
11
function MyComponent(props) {
/* 使用 props 渲染 */
}
function areEqual(prevProps, nextProps) {
/*
如果把 nextProps 传入 render 方法的返回结果与
将 prevProps 传入 render 方法的返回结果一致则返回 true,
否则返回 false
*/
}
export default React.memo(MyComponent, areEqual);

此方法仅作为性能优化的方式而存在。但请不要依赖它来“阻止”渲染,因为这会产生 bug。