面试题

react的useEffect监听对象存在的问题
无法监听对象或数组内的成员改变

import { useEffect, useState } from 'react'

function App() {
  const [person, setPerson] = useState({uname: '张三'})

  const setUname = ()=>{
    person.uname = '李四'+new Date().getTime();
    setPerson(person);
    console.log(person);
  }

  useEffect(()=>{
    console.log('person发生改变');
  },[person])

  return (
    <>
      <button onClick={setUname}>测试</button>
      <div>{person.uname}</div>
    </>
  )
}

export default App


可以看到 即便是对象的属性已经真的改变了,但是useEffect的监听仍然未执行,即没有被监听到。
当然数组也一样。

解决办法: 设置的时候新创建一个对象即可 setXXX([...xxx]) 或者setXXX({...xxx})

你平时用fetch多还是axios多 谈谈你做了哪些事情

接口被重复调用,响应时长不同,结果被覆盖的问题
频繁调用接口,前面接口返回的数据把后面的覆盖了?

后端node服务器模拟

import url from 'url';
import http from 'http';


const sleep = (timer)=>{
    return new Promise((resolve)=>{
        setTimeout(()=>{
            resolve()
        },timer)
    })
}

const users = [
    {name:'用户1',age:20, desc:'我就是我'},
    {name:'用户2',age:18}
];

http.createServer(async (request, respones)=>{
    const parseUrl = url.parse(request.url,true);
    const uname = parseUrl.query.name;
    if(uname === '用户1'){
        await sleep(3000)
    }
    respones.writeHead(200,{'Content-type':'application/json'})
    respones.end(JSON.stringify(users.find(it=>it.name===uname)))
}).listen('8080')

axios代码如下

import { useState } from 'react'
import axios from 'axios'

function App() {
  const [info, setInfo] = useState({})


  const syncInfo = async (name) => {
    const { data: infoRes } = await axios.get('http://localhost:8082/info', {
      params: { name }
    });
    setInfo({ ...infoRes })
    console.log(infoRes);
  }


  return (
    <>
      <button onClick={() => { syncInfo('用户1') }}>测试1</button>
      <button onClick={() => { syncInfo('用户2') }}>测试2</button>
      <div>{JSON.stringify(info)}</div>
    </>
  )
}

export default App

取消重复请求,只保留最后一次请求

import { useState } from 'react'
import axios from 'axios'
let cancel;

function App() {
  const [info, setInfo] = useState({})


  const syncInfo = async (name) => {
    if(cancel){ cancel();}  // 请求之前判断 有没有存在的请求 如果有 就取消
    const { data: infoRes } = await axios.get('http://localhost:8082/info', {
      params: { name },
      cancelToken: new axios.CancelToken(c=> {
        cancel = c; // executor 函数接收一个 cancel 函数作为参数     
      })
    });
    setInfo({ ...infoRes })
    console.log(infoRes);
  }


  return (
    <>
      <button onClick={() => { syncInfo('用户1') }}>测试1</button>
      <button onClick={() => { syncInfo('用户2') }}>测试2</button>
      <div>{JSON.stringify(info)}</div>
    </>
  )
}

export default App

参考:https://www.jianshu.com/p/fdd24f062cf5

如果是使用fetch

import { useState } from "react";

let syncInfoOldRequestController = null;
function App() {
  const [info, setInfo] = useState({});

  const syncInfo = async (name) => {
    // 判断是否有老的请求控制器 如果有 终止请求
    if (syncInfoOldRequestController) {
      //  调用中止方法,发出信号,触发回调
      //  可以监听此信号 controller.signal.addEventListener('abort', () => {  console.log(signal.aborted); }); 
      syncInfoOldRequestController.abort();    
      syncInfoOldRequestController = null;
    }

    // 请求要存入一个控制器
    const controller = new AbortController(); // 创建 AbortController 实例
    syncInfoOldRequestController = controller;

    const infoRes = await fetch("http://localhost:8080/info?name=" + name, {
      signal: controller.signal,
    }).then((res) => res.json());
    setInfo({ ...infoRes });
  };

  return (
    <>
      <button onClick={() => { syncInfo('用户1') }}>测试1</button>
      <button onClick={() => { syncInfo('用户2') }}>测试2</button>
      <div>{JSON.stringify(info)}</div>
    </>
}

export default App;

理解

less中如何定义全局变量
vite项目中,可以根据vite提供的配置项修改
vite.config.js

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  css: {
    preprocessorOptions: {
      less: {
        modifyVars:{
          myColor: 'pink'
        },
        javascriptEnabled: true,
      }
    }
  },
})

最后在任意的其它less文件中 使用即可
App.less

button {
  color: @myColor;
}

当然 定义变量的时候也支持 读取一个变量文件 用法一样
vite.config.js

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import {resolve} from "path"

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  css: {
    preprocessorOptions: {
      less: {
        modifyVars: {
          hack: `true; @import (reference) "${resolve('src/var.less')}";`,
        },
        javascriptEnabled: true,
      }
    }
  },
})

var.less

@color: blue;

如果是webpack,则也是需要配置即可,参考less-loader文档和less 全局变量文档

const path = require('path');

module.exports = {
    mode: "development",
    entry: './src/index.js',
    output: {
        filename: 'main.js',
        path: path.resolve(__dirname, 'dist')
    },
    module: {
        rules: [
            {
                test: /\.less$/i,
                use: [
                    'style-loader',
                    'css-loader',
                    {
                        loader: 'less-loader',
                        options: {
                          lessOptions: {
                            globalVars: {
                                myColor: 'red'
                            },
                          },
                        },
                    },
                ],
            },
        ],
    },
};

但是其本身不支持 导入less文件作为全局变量。 所以我们可以自己借助nodejs得fs去读取 然后遍历 拼接到globalVars里。
这里偷懒 找到网上已有得库,代码给扣下来了。

function getLessVariables(file) {
    var themeContent = fs.readFileSync(file, 'utf-8')
    var variables = {}
    themeContent.split('\n').forEach(function(item) {
        if (item.indexOf('//') > -1 || item.indexOf('/*') > -1) {
            return
        }
        var _pair = item.split(':')
        if (_pair.length < 2) return;
        var key = _pair[0].replace('\r', '').replace('@', '')
        if (!key) return;
        var value = _pair[1].replace(';', '').replace('\r', '').replace(/^\s+|\s+$/g, '')
        variables[key] = value
    })
    return variables
}

// webpack配置
globalVars: getLessVariables('./src/var.less')

如何将多为数组打散
es2022个数组的实例方法上加了个flat。作用为扁平化数组,即将嵌套的数组分离出来变成一维数组。

// 用法 Array.flat(层级);
[1,2,[3,4]].flat(0);//不变
[1,2,[3,4]].flat(1);//变成  一维数组,这个1表示往外提取一层,即二维变成1维  默认为1
[1,2,[3,4]].flat(Infinity); // 不管几维数组 全给你提出来


// 示例
const arr = [1,[2,3],[[4],5]];
arr.flat(Infinity); // [1, 2, 3, 4, 5]

不过显然,如果面试问你这道题,你不能像上边那样回答,人家基本是让你自己实现的

const myFlat = (arr) => {
  const res = [];
  const handel = (param) => {
    param.forEach(element => {
      if(Array.isArray(element)){
        handel(element)
      }else{
        res.push(element)
      }
    });
  };
  handel(arr);
  return res;
};

const r = myFlat([1, [2, 3], [[4], 5]]);
console.log(r);

手写一个sleep函数
这个简单

const sleep = (timer)=>{
    return new Promise((resolve)=>{
        setTimeout(()=>{
            resolve()
        },timer)
    })
}

react16.8中发生了什么大变化导致可以用hooks

css如何写出10号字体
大部分浏览器都得以最小字体设置在12px,我们可以通过设置浏览器来支持更小的字体。
如果要设置 更小字体 这可不是好办法,因为你无法修改用户浏览器设置。

css缩放

div{
    font-size: 20px;
    zoom: 0.5;
}
/** 首先自定义字号为12像素,因为浏览器支持的最小就是12像素,之后通过缩放来实现想要的字号:
** 10px = 10/12=0.8333333333333333
**/
div{
  font-size: 12px;
  transform: scale(0.83,0.83) ;
}

乾坤js遇到什么问题过吗

实现一个布局 左侧300px 右侧自适应

解释下flex:1代表什么意思

如何实现垂直居中 当align-item:center 什么轴

不同环境下 webpack或rollup等插件怎么按需加载 从而优化打包或启动速度

react如何实现vue那样的路由钩子 并监听后退,修改系统弹窗提示等

posted @ 2023-09-04 16:38  丁少华  阅读(33)  评论(0编辑  收藏  举报