1
17

一些可能会问的面试内容

前端 17 1129 1
发表于: 2022-05-20 20:11:34

简介: 暂不全,会持续更新

模块化

除了esm是es规范化,其余都是约定俗成的一种规范,即本质上都是通过js实现的模块化,大家都根据某一个规范写,逐渐流行起来后才算得上是模块化。

接触过的,esm(es6官方),commonjs(node官方),umd(库打包兼容)

ESM(es6官方)

ECMAScript Module,es6模块化

  1. 使用 import 导入模块;
  2. 使用 export 导出模块;

CommonJS(node官方)

CommonJS 在NodeJS 环境用,不适用于浏览器;

  1. 使用 exports.xx = … 或者 module.exports ={} 暴露模块;
  2. 使用 require() 方法引入一个模块;
  3. require()是同步执行的;

AMD(Require.js)

AMD是"Asynchronous Module Definition"的缩写,意思就是"异步模块定义"。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。

  1. 使用 define(…) 定义一个模块;
  2. 使用require(…) 加载一个模块;

CMD(Sea.js)

CMD(Common Module Definition - 通用模块定义)规范主要是Sea.js推广中形成的,一个文件就是一个模块,可以像Node.js一般书写模块代码。主要在浏览器中运行,当然也可以在Node.js中运行。

它与AMD很类似,不同点在于:AMD 推崇依赖前置、提前执行,CMD推崇依赖就近、延迟执行。

UMD(通用)

全称 Universal Module Definition(万能模块定义),从名字就可以看出 UMD 做的是一统的工作。Webpack 打包代码就有 UMD 这个选项。

主要是兼容commonjs和amd

  1. 判断是否有define以及define.amd,兼容amd模块化
  2. 判断是否有exports和module,或者只有exports,兼容node模块化
  3. 如果都没有则挂载到全局变量里面(window或者global)
  4. 疑问:umd有兼容cmd吗。还是说cmd和amd类似,兼容amd约等于也兼容了cmd了。
if(typeof exports === 'object' && typeof module === 'object')
    // CommonJS规范 node 环境 判断是否支持 module.exports 支持 require 这种方法
		module.exports = factory(require("vue"));
	else if(typeof define === 'function' && define.amd)
    // AMD 如果环境中有define函数,并且define函数具备amd属性,则可以判断当前环境满足AMD规范
		define(["vue"], factory);
	else if(typeof exports === 'object')
    // 不支持 module 但是支持 exports 的情况下使用 exports导出 是CommonJS 规范
		exports["Billd"] = factory(require("vue"));
	else
    // 都不支持则挂载到全局对象
		root["Billd"] = factory(root["Vue"]);

react生命周期

挂载,当组件实例被创建并插入 DOM 中时

componentDidMount

更新,当组件的 props 或 state 发生变化时会触发更新

componentDidUpdate

componentWillUpdate(即将过时)

卸载,当组件从 DOM 中移除时会调用如下方法:

componentWillUnmount

性能优化

防抖节流

防抖:触发高频事件后 n 秒内函数只会执行一次,如果 n 秒内高频事件再次被触发,则重新计算时间,防抖重在定时器清零

function debounce(f, wait) {
  let timer;
  return (...args) => {
    clearTimeout(timer);
    timer = setTimeout(() => {
      f(...args);
    }, wait);
  };
}

节流:高频事件触发,但在 n 秒内只会执行一次,所以节流会稀释函数的执行频率。节流重在加锁 ,也就是重置这个定时器。

function throttle(f, wait) {
  let timer;
  return (...args) => {
    if (timer) {
      return;
    }
    timer = setTimeout(() => {
      f(...args);
      timer = null;
    }, wait);
  };
}

Ahooks

useUpdate

作用是重新渲染。

主要利用了 js 里面的{}不等于{}。使用useState定义一个初始化的空对象,然后返回一个函数,这个函数setSate一个空对象。返回把这个函数返回即可。当执行这个函数的时候,因为两个空对象的引用不一样,因此会重新渲染这个组件。

import { useState } from "react";

const useUpdate = () => {
  const [, setState] = useState({});
  return () => setState({});
};

export default useUpdate;

useLocalStorageState

作用是使用 useState 的时候同时把数据缓存到 localStorage 里。

主要实现就是对 localStorage 进行了一层 useState 包装,然后导出一个 state 和设置 state 回调函数,在调用这个回调函数的时候,同时设置 localStorage.setItem 以及更新内部的 useState。以此达到statte和localStorage同步。

useDebounce

用来处理防抖值的 Hook。

useThrottle

用来处理节流值的 Hook。

浏览器差异

js兼容性

  1. new Date()构造函数使用,‘2018-07-05’是无法被各个浏览器中,使用new Date(str)来正确生成日期对象的。 正确的用法是’2018/07/05’。

css兼容性

各大浏览器前缀

  • -moz代表firefox浏览器私有属性
  • -ms代表IE浏览器私有属性
  • -webkit代表chrome、safari私有属性
  • -o代表opera私有属性

flex布局

最后一行左对齐

https://www.zhangxinxu.com/wordpress/2019/08/css-flex-last-align/

每一行列数固定

下面案例都是基于一行4个元素。

方法1:模拟space-between和间隙

// 一行4个
.list:not(:nth-child(4n)) {
    margin-right: calc(4% / 3);
}

方法2:根据个数最后一个元素动态margin

/* 如果最后一行是3个元素 */
.list:last-child:nth-child(4n - 1) {
    margin-right: calc(24% + 4% / 3);
}
/* 如果最后一行是2个元素 */
.list:last-child:nth-child(4n - 2) {
    margin-right: calc(48% + 8% / 3);
}

每一行子项宽度不固定

方法一:最后一项margin-right:auto

/* 最后一项margin-right:auto */
.list:last-child {
    margin-right: auto;
}

方法二:创建伪元素并设置flex:auto或flex:1

/* 使用伪元素辅助左对齐 */
.container::after {
    content: '';
    flex: auto;    /* 或者flex: 1 */
}

每一行列数不固定

如果每一行的列数不固定,则上面的这些方法均不适用,需要使用其他技巧来实现最后一行左对齐。

这个方法其实很简单,也很好理解,就是使用足够的空白标签进行填充占位,具体的占位数量是由最多列数的个数决定的,例如这个布局最多7列,那我们可以使用7个空白标签进行填充占位,最多10列,那我们需要使用10个空白标签。

<div class="container">
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
    <div class="list"></div>
    <i></i><i></i><i></i><i></i><i></i>
</div>
/* 和列表一样的宽度和margin值 */
.container > i {
    width: 100px;
    margin-right: 10px;
}

如果列数不固定HTML又不能调整

Grid布局

.container {
    display: grid;
    justify-content: space-between;
    grid-template-columns: repeat(auto-fill, 100px);
    grid-gap: 10px;
}
.list {
    width: 100px; height:100px;
    background-color: skyblue;
    margin-top: 5px;
}

总结

首先最后一行需要左对齐的布局更适合使用CSS grid布局实现,但是,repeat()函数兼容性有些要求,IE浏览器并不支持。如果项目需要兼容IE,则此方法需要斟酌。

然后,适用范围最广的方法是使用空的元素进行占位,此方法不仅适用于列表个数不固定的场景,对于列表个数固定的场景也可以使用这个方法。但是有些人代码洁癖,看不惯这种空的占位的html标签,则可以试试一开始的两个方法,一是动态计算margin,模拟两端对齐,另外一个是根据列表的个数,动态控制最后一个列表元素的margin值实现左对齐。

Redux和Vuex区别

Vuex是和vue强绑定的。
Redux就是一个状态管理库,理论可以在任何地方用。
Redux所有操作都是dispatch触发action,异步操作得借助中间件,redux-thunk,redux-saga等。
Vuex同步操作是commit触发mutation,异步操作是dispatch触发action,action里面在再通过commit触发mutation更新数据

Redux

reducer

reducer名称由来,它和es6的reduce很像,第一个参数是初始化status值,第二个参数是action,reducer里面通过判断action的type来执行不同逻辑返回最新status。reducer要求是一个纯函数。

combineReducers(区分模块)

通过拆分reducer,一个reducer就是一个模块,然后通过redux导入的combineReducers合并所有reducer。这个combineReducers返回值也是一个reducer。

import { combineReducers } from 'redux';

const reducer = combineReducers({
  counterInfo: counterReducer,
  homeInfo: homeReducer
});

connect/Provider

如果是类组件,需要通过react-redux的connect来连接react和redux,通过Provider包裹。

这个connect其实是一个高阶函数,它接收mapStateToProps和mapDispatchToProps,并且返回值也是一个函数。

内部使用了React.createContext,在componentDidMount的时候subscribe监听redux的store变化并且setState。以此触发重新渲染更新组件。最后在componentWillUnmount的时候取消订阅。

import { connect } from 'react-redux';

export default connect(mapStateToProps, mapDispatchToProps)(Home);

如果是函数式组件,则不需要connect,通过react-redux的useSelector这个hooks来实现。

import { useSelector, shallowEqual } from 'react-redux';

const { banners, recommends, counter } = useSelector(state => ({
  banners: state.banners,
  recommends: state.recommends,
  counter: state.counter
}), shallowEqual);

applyMiddleware

https://redux.js.org/tutorials/fundamentals/part-4-store#middleware

import { createStore, applyMiddleware } from 'redux'
import rootReducer from './reducer'
import { print1, print2, print3 } from './exampleAddons/middleware'

const middlewareEnhancer = applyMiddleware(print1, print2, print3)

// Pass enhancer as the second arg, since there's no preloadedState
const store = createStore(rootReducer, middlewareEnhancer)

export default store

中间件作用

Redux 使用一种称为中间件的特殊插件来让我们自定义dispatch功能。

中间件在发出action和执行reducer之间添加了一些功能。

其实中间件是一个高阶函数,这个函数嵌套返回了两个函数。在这两个函数里面可以做一些操作。

自定义中间件

// Middleware written as ES5 functions

// Outer function:
function exampleMiddleware(storeAPI) {
  return function wrapDispatch(next) {
    return function handleAction(action) {
      // Do anything here: pass the action onwards with next(action),
      // or restart the pipeline with storeAPI.dispatch(action)
      // Can also use storeAPI.getState() here

      return next(action)
    }
  }
}

redux-thunk

redux的操作都是通过dispatch,默认的dispatch的reducer一般都是一个对象,因此很难做到异步,thunk这个中间件将

源码只有14行(js版本的时候就是14行,后面换成ts后多了类型和注释也只有53行)。

解释:根据自定义中间件的范式,仅仅是对action做了一个判断

  1. 如果action是函数类型,则调用action,把storeAPI,storeAPI即dispatch和getState,和额外参数extraArgument传给action并执行。
  2. 如果不是函数类型,则直接next(action)。
function createThunkMiddleware(extraArgument) {
  return ({ dispatch, getState }) => next => action => {
    if (typeof action === 'function') {
      return action(dispatch, getState, extraArgument);
    }

    return next(action);
  };
}

const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;

export default thunk;

Es6新增

  1. symbol类型
  2. let/const
  3. filter、map、reduce、some、every、find、findIndex
  4. set和map
  5. Proxy代理
  6. Class类
  7. 迭代器和生成器
  8. 装饰器(还没有定案)
  9. 扩展运算符
  10. promise
  11. async/await
  12. Module模块化

Webpack

解析各种资源,样式,图片,js/jsx/ts/tsx

Eslint

热更新

CompressionPlugin===>gzip压缩

babel===》plugin-syntax-dynamic-import,路由懒加载

Externals+HtmlWebpackTagsPlugin,cdn加载第三方库

Treeshaking,移除没有引用的代码

optimization—》splitChunks,优化bundle大小

TerserPlugin,压缩js

PreloadPlugin,预加载js

Billd-UI

项目目录

|-- README.md // 说明文件
|-- babel.config.js // babel配置,当使用webpack构建umd版本时会使用该配置
|-- index.js // 所有组件的入口文件,当使用webpack构建umd版本时会使用该入口
|-- package.json
|-- postcss.config.js // postcss配置,当使用webpack构建umd版本时会使用该配置
|-- tsconfig.json
|-- build-tools // 构建目录
|   |-- getBabelCommonConfig.js // babel配置,当使用gulp构建es和lib版本时会使用该配置
|   |-- getPostcssConfig.js // postcss配置,当使用gulp构建es和lib版本时会使用该配置
|   |-- gulpfile.js // gulp配置文件
|   |-- webpack.common.js // webpack通用配置
|   |-- webpack.dev.js // webpack开发环境配置
|   |-- webpack.prod.js // webpack生产环境配置,当使用webpack构建umd版本时会使用该配置
|   |-- webpack.prod.min.js // webpack生产环境配置,当使用webpack构建umd版本的压缩版本时会使用该配置
|   |-- svgo // svgo配置
|   |   |-- svgOptions.js // svg优化选项
|   |   |-- template // svg模板
|   |       |-- icon.ejs
|   |-- utils // 常用方法
|       |-- chalkTip.js // 自定义console
|       |-- paths.js // 处理路径
|       |-- transformLess.js // 编译less
|-- components // 组件目录
|   |-- index.js // 所有组件的入口文件,当使用gulp构建es和lib版本时会使用该入口
|   |-- modal
|   |   |-- foot.jsx
|   |   |-- index.jsx // modal组件入口文件
|   |   |-- style	// modal组件样式目录
|   |       |-- index.js // modal组件样式的入口文件
|   |       |-- index.less // modal组件样式
|   |-- switch
|   |   |-- index.jsx // switch组件入口文件
|   |   |-- style // switch组件样式目录
|   |       |-- index.js // switch组件样式的入口文件
|   |       |-- index.less // switch组件样式
|-- src // 本地开发调试
|-- es // 构建好的es版本
|-- lib // 构建好的lib版本
|-- dist // 构建好的umd版本

Gulp

基于stream流的自动化构建工具

task

  • 公开任务(Public tasks) 从 gulpfile 中被导出(export),可以通过 gulp 命令直接调用。
  • 私有任务(Private tasks) 被设计为在内部使用,通常作为 series()parallel() 组合的组成部分。

gulp.src

通过glob匹配文件流

gulp.pipe

管道,传输文件流

gulp.dest

创建/输出文件流

gulp.parallel

并行执行任务

gulp.series

连续执行任务

http状态码

200,请求已经成功

201,成功,并且创建了资源(比如数据库新增了一条记录)

301,永久重定向(比如http永久重定向到https)

server {
    listen 80;
    server_name hsslive.cn;

    location / {
        # 把当前域名的请求,跳转到新域名上,域名变化但路径不变
        # permanent:返回301永久重定向,浏览器地址栏会显示跳转后的URL地址
        rewrite ^/(.*) https://hsslive.cn/$1 permanent;
    }
}

302,临时重定向

304,Not Modified,资源没改变,缓存

400,参数错误

401,未授权

403,权限不足

404,not found,没找到

429,频繁请求

431,请求中的首部字段的值过大,服务器拒绝接受客户端的请求。一般是post数据太多,或者是上传base64之类的。解决:nginx设置

http {
		#....
    client_header_buffer_size 10240k;
    large_client_header_buffers 6 10240k; 
  
  server {
     # ...
  }
}

500,服务器错误

502,网关错误

504,网关超时

移动端适配

Koa和express区别

相同点

两个框架都对http进行了封装。相关的api都差不多,同一批人所写。

不同点

express内置了许多中间件可供使用,而koa没有。

express包含路由,视图渲染等特性,而koa只有http模块。

express的中间件模型为线型,而koa的中间件模型洋葱模型构造中间件。

express通过回调实现异步函数,在多个回调、多个中间件中写起来容易逻辑混乱。

// express写法
app.get('/test', function (req, res) {
    fs.readFile('/file1', function (err, data) {
        if (err) {
            res.status(500).send('read file1 error');
        }
        fs.readFile('/file2', function (err, data) {
            if (err) {
                res.status(500).send('read file2 error');
            }
            res.type('text/plain');
            res.send(data);
        });
    });
});

koa通过generator 和 async/await 使用同步的写法来处理异步,明显好于 callback 和 promise。

app.use(async (ctx, next) => {
    await next();
    var data = await doReadFile();
    ctx.response.type = 'text/plain';
    ctx.response.body = data;
});

总结

Express
优点:线性逻辑,通过中间件形式把业务逻辑细分、简化,一个请求进来经过一系列中间件处理后再响应给用户,清晰明了。
缺点:基于 callback 组合业务逻辑,业务逻辑复杂时嵌套过多,异常捕获困难。

Koa
优点:首先,借助 co 和 generator,很好地解决了异步流程控制和异常捕获问题。其次,Koa 把 Express 中内置的 router、view 等功能都移除了,使得框架本身更轻量。
缺点:社区相对较小。

Vue

优先级

2.x 版本中在一个元素上同时使用 v-ifv-for 时,v-for 会优先作用。

3.x 版本中 v-if 总是优先于 v-for 生效。

props>methods>data>computed>watch

keepalive

activated:在首次挂载,以及每次从缓存中被重新插入的时候调用

deactivated:在从 DOM 上移除、以及组件卸载时调用

create=>mounted=>activated=>deactivated=>destroyed

几类Watcher

常见的场景有下面这几个:

  • 数据变 → 使用数据的视图变
  • 数据变 → 使用数据的计算属性变 → 使用计算属性的视图变
  • 数据变 → 开发者主动注册的watch回调函数执行

三个场景,对应三种watcher:

  • 负责敦促视图更新的render-watcher
  • 执行敦促计算属性更新的computed-watcher
  • 用户注册的普通watcher(watch-api或watch属性)

作者:晒了个太阳
链接:https://juejin.cn/post/6844904128435470350
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

new Vue做了什么

  1. 执行了this._init
  2. _init里面做了:合并配置,初始化生命周期,初始化事件中心,初始化渲染,初始化 data、props、computed、watcher 等等。

响应式

Vue采用数据劫持(Object.defineProperty)结合发布者-订阅者模式的方式来实现数据的响应式

  1. 初始化数据,执行了observer,调用walk,这个walk,这个walk对数据遍历调用defineReactive,而defineReactive内部主要使用了Object.defineProperty,它对初始化的数据进行了

Observer

  1. 通过defineReactive定义响应式,递归遍历,将每一个数据分别定义响应式,分别监听

Compile解析器

解析模板,将模板里面的变量替换成数据,将变量替换成数据的这个过程其实就给节点

Watcher订阅者

Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁 ,主要的任务是订阅 Observer 中的属性值变化的消息,当收到属性值变化的消息时,触发解析器 Compile 中对应的更新函数。

Dep订阅器收集依赖

数据代理

循环遍历的对options.data进行一层Object.defineProperty代理,方便的将this.xxx代理到this.$data.xxx,简洁方便。

diff算法

如何比较

同层比较,新旧节点(新旧节点都是指虚拟dom对象)的比较是同层级的比较,不会跨层比较。

  1. 先判断oldNode是普通dom节点还是虚拟dom节点
  2. 如果是是普通dom节点,包装成虚拟dom节点
  3. 判断新旧节点是不是同一个节点,不是同一个节点,则暴力删除旧的,插入新的。
  4. 如果新旧节点是同一个节点,开始精细化比较
  5. 精细化比较如果是同一个引用,什么都不做
  6. 精细化比较如果是不同一个引用
    1. 这个新节点是文本(即类似一个p标签里面的文字),新节点的文本和旧文本节点的文本一样,啥都不干;新节点的文本和旧文本节点的文本不一样,直接innerText。
    2. 这个新节点不是文本(即类似ul下面没有文字,只有li或者其他标签节点),判断旧的节点是不是文本
      1. 如果是文本的话,就直接innerText设置空字符串,然后遍历创建新节点,并追加到旧的节点里面。
      2. 如果不是文本,即节点和节点之间的比较,这个就很复杂了,还没看。

节点复用

1, 两个节点相同,但不在相同层级上,无法复用

2,两个节点相同,在同一层级,但父节点不同,无法复用

3,同层同父节点,可以复用

我的业务

换肤hook/获取活动配置

我这里的换肤指的不是在客户端预制了几套样式在线换,而是在页面mounted的时候,通过请求获取数据,然后设置对应样式,对于用户来说无感。

  1. 判断缓存,先读取地址栏的活动模块名version,判断是否需要重新请求数据
  2. 请求的数据是key-value的形式,通过遍历累加成一个字符串,然后再将字符串结果拼在:root{}里面,再把最终的结果作为textContent,设置在新建的style元素里面,最后将这个style通过appendChild追加到head标签最后。这样来实现换肤。

分页hooks

接收url以及option参数(limit,actId,page)

在hooks里面使用axios发送请求获取数据

返回ReqStatus(当前请求状态,loading/loaded),hasMore(是否还能加载下一页,Boolean),loadMore(加载下一页),List(当前的数据),Refresh(刷新)。

billd-ui

组件设计

  1. 所有组件都在components目录里面,里面的每个文件夹都是一个单独的组件。
  2. components目录里有一个index.js入口文件,这个入口文件导入了所有组件,默认导出了install函数(调用这个install函数就会注册所有组件),方便全局导入所有组件。而且还单独导出了每一个组件,方便按需导入。
  3. 每个组件都有一个index.jsx文件作为入口文件。
  4. 每个组件的样式都在style文件夹里面,style文件夹里面又有index.js作为入口文件,里面引入了所有的该组件需要的less文件。
  5. 项目的根目录有一个index.js文件作为入口文件,当使用webpack构建umd版本时会使用该入口,它通过require.context导入components里面所有的组件样式,以及默认导出了component目录的index.js入口文件。因此这样就可以将组件的所有样式以及文件都构建到一个文件里面。

主要内容

  1. transformLess方法,主要读取components里面的所有样式文件,使用less以及postcss进行处理,最终生成css。
  2. compile任务,主要使用babel对项目的js/jsx文件进行解析编译,编译出es以及lib版本;同时将components里面所有组件的style文件的样式的入口index.js都复制一份然后重新生成一个css.js,并且将css.js里面的import的xxx.less文件都替换成css后缀(这是配合babel-plugin-import这个按需加载插件做的额外处理)。
  3. dist任务,使用webpack的 multicompiler 编译组件,打包出通用的umd版本以及对应的压缩版本。

billd-icons

作用就是替代图片,因为组件库使用图片这种静态资源的话,除非打成base64,不然如果是生成单独的图片的话,会有路径问题,因此使用了icons替代一些图片。这个库的目的就是解析svg文件里面的dom节点并且把解析好的svg节点数据输出到js里面。还有根据这个svg节点数据,进一步的构建成vue组件。

1,icons-svg-asn任务,将svg文件解析为Abstract Node,生成icons-svg的asn。

  1. 匹配svg资源目录里面的svg,因为匹配到的都是流,所以用了through2这个库来操作流,使用这个库将文件(或者说文件流)内容进行toString拿到字符串,然后用svgo这个插件对svg内容进行优化,删掉一些没用的属性,最终得到精简版的字符串后,再用一个parseXML这个库解析里面的dom结构,把这个dom结构保存起来就是asn里。总结来说就是将svg文件转换成解析好并且优化过的抽象节点保存在js文件里面。

2,封装icons-vue-icons任务,根据icons-svg的asn生成icons-vue的icons以及对应的入口文件。

  1. 有了svg的节点数据之后,就很好办了,因为是用jsx写的组件,就可以再render函数里面自己新建一个svg标签元素,然后将解析好的svg节点里面的path节点以及他的节点属性给遍历的渲染出来。总结来说就是将asn转换成jsx组件。

3,封装replaceLib方法(babel插件),将构建出来的es包里面所有导入的lib路径全部替换为es。

  1. 因为最终生成vue组件不止一个svg组件,是上百个组件,而且其实这上百个组件其实都是同一个模板,只是引用的svg路径不一样,因此,所有的vue组件的jsx代码,其实是根据一个模板然后批量生成的,但是因为最终构建了es和lib两个版本,但是模板只有一个,所以es版本里面组件也引用的是lib里面的路径,因此用了这个方法对es版本的所以组件jsx进行替换。
  2. 他其实是一个babel插件,Babel 插件本质上就是编写各种 visitor 去访问 AST 上的节点。当遇到对应类型的节点,visitor 就会做出相应的处理,从而将原本的代码 transform 成最终的代码。我这里就是添加了ImportDeclaration(ˌdekləˈreɪʃn)和ExportNamedDeclaration两个方法,即当解析到import或者export的时候,我用正则匹配将这个lib给替换成es。
  3. 总结来说就是对jsx组件的es版本进行特殊处理,把里面的import的lib路径替换成对应的es。

7,封装svgo模块,用于处理以及优化组件里的svg资源,将svg文件解析成dom对象,并通过render函数将dom对象渲染成icon-vue组件。

职业规划

  1. 技术方面:保持学习,与时俱进。这个还是比较重要的。
  2. 业务方面:暂时来说比较倾向做一些通用的业务,而不是一些针对性很强的业务,比如游戏(cocos、egret等)、地图(gis、three等)、图表(echart)等。
JavaScript vue React webpack 计算机网络 性能优化
最近他们赞了该文章:

最后更新于:2022-05-27 22:15:31

欢迎评论留言~
0/200
支持markdown
Comments | 17 条留言
按时间
按热度
A1onely VIP用户
2 年前

22222222

0 点赞
回复
江苏省 - 南京市 Mac OS 10.15.7
A1onely
2 年前

2342342342342342

0 点赞
回复
江苏省 - 南京市 Mac OS 10.15.7
A1onely
2 年前

2223213412423423

0 点赞
回复
江苏省 - 南京市 Mac OS 10.15.7
共9条回复
A1onely VIP用户
2 年前

标题

111

1 点赞
回复
Mac OS 10.15.7
A1onely 回复 A1onely
2 年前

回复666666666

回复55555555555

1 取消点赞
回复
江苏省 - 南京市 Mac OS 10.15.7
A1onely 回复 A1onely
2 年前

回复55555555555

回复3333333333

1 取消点赞
回复
江苏省 - 南京市 Mac OS 10.15.7
共6条回复
已加载所有留言~