0503笔记总结

防抖和节流函数的使用

作用:降低函数的执行频率
良好的插件:lodash.debounce和lodash.throttle

防抖的应用场景

window.onload = function() {
	var div1 = document.getElementById("div1");
	var i = 0;
	var sid;
	div1.onmousemove = function() {
		clearTimeout(sid);
		sid = setTimeout(function() {
			div1.innerHTML = i;
			i ++;
		}, 1000);
	}
}

应用场景:

  • resize
  • 搜索引擎ajax提交
  • 元素拖拽

节流的应用场景

window.onload = function() {
	var div1 = document.getElementById("div1");
	var i = 0;
	var flag = true;
	var sid;
	window.onmousemove = function() {
		if (flag) {
			flag = false;
			sid = setTimeout(function() {
				div1.innerHTML = i;
				i ++;
				flag = true;
			}, 1000);
		}
	}
}

应用场景:

  • 无限下拉加载

webpack性能优化

1、raw-loader实现资源内联:raw-loader会读取文件,并将文件内容作为一个字符串返回,插入到指定位置(项目优化)
(1)代码层面:页面框架初始化脚本,比如移动端flexible.js;CSS内联避免页面闪动;
(2)请求层面:减少http网络请求次数(小图片{url-loader})

2、提取公共资源:(项目优化,打包优化)
(1)html-webpack-externals-plugin实现不将基础库打包进bundle.js中,而在模板文件中使用CDN服务器自动引入
(2)SplitChunksPlugin实现将公共脚本,比如react.js,react-dom.js或者自己封装的公共代码分离出来,打包成单独的js文件,自动引入模板文件中
(3)mini-css-extract-plugin实现将CSS文件从bundle.js中提取出来,打包成单独的CSS文件

3、代码分割及动态import:使用@babel/plugin-syntax-dynamic-import实现将不是页面初始化的js代码,打包成单独的js文件,使用到的时候,进行动态import进行加载(项目优化,打包优化)

4、开启多进程打包:使用thread-loader开启多进程打包(打包优化)

5、对图片进行压缩:image-webpack-loader(项目优化,打包优化)

6、将webpack.config.js文件进行分割,以方便不同环境配置和维护(性能优化,打包优化)

7、.js文件压缩及缓存:terser-webpack-plugin(项目优化,打包优化)

8、css文件进行压缩:optimize-css-assets-webpack-plugin(项目优化,打包优化)

9、热重载(打包优化)

简历好好整

个人技能精悍一点

项目react4/5个,vue1个

antd组件封装,思路,怎么实现的,考虑因素

table封装:
首先考虑一下antd提供的table常见的配置属性有:bordered,column,dataSource,pagination,selectedItem,selectedRowKeys,rowSelection.onRow这些,像前几个可以通过父组件传值在子组件中结构出来,而rowSelection决定表格是什么样式的,像radio单选,checkbox复选框,或者就是一个普通表格,这里我们需要处理一下,如果传过来是radio或者checkbox,就让他显示相应的表格,如果什么这个属性什么也没有穿,就让它等于null;然后onRow里面也需要判断一下这个属性是不是null,如果是,直接return false,否则再往下处理;如果是radio的话,当我们点击换选中的项时,就直接将index赋值给selectedRowKeys,将record赋值给selectedItem,然后通过调用父组件传过来的一个方法将数据传回去,更新一下state中的选中项和选中项的index;如果是checkbox就需要判断一下selectedIds是不是空,如果是空,说明是第一次选中项,将选中项,选中项的index和id添加到selectedItems,selectedRowKeys,selectedIds里面,如果seletedIds不是空,说明已经选中一项了,再点击需要判断是取消还是又选中了一项,然后进行删除或者新增,之后在调用父组件传过来的方法去更新父组件的state

import React, { Component } from 'react';
import { Table } from 'antd';
import Utils from '../../utils/utils';

class ETable extends Component {

  onRowClick = (record, index) => {
    let { rowSelection } = this.props;
    if (rowSelection === 'radio') {
      let rowSelectedKeys = [index];
      let selectedItem = record;
      this.props.updateSelectedItem(rowSelectedKeys, selectedItem);
    } else if (rowSelection === "checkbox"){
      let selectedRowKeys = this.props.selectedRowKeys;
      let selectedItem = this.props.selectedItem;
      let selectedIds = this.props.selectedIds;
      if (selectedIds) {
        const i = selectedIds.indexOf(record.id);
        if (i === -1) {
          selectedIds.push(record.id);
          selectedRowKeys.push(index);
          selectedItem.push(record);
        } else {
          selectedIds.splice(i, 1);
          selectedRowKeys.splice(i, 1);
          selectedItem.splice(i, 1);
        }
      } else {
        selectedIds = [record.id];
        selectedRowKeys = [index];
        selectedItem = [record];
      }
      this.props.updateSelectedItem(selectedRowKeys, selectedItem, selectedIds);
    }
  }

  tableInit = () => {
    let row_selection = this.props.rowSelection;
    let selectedRowKeys = this.props.selectedRowKeys;
    const rowSelection = {
      type: "checkbox",
      selectedRowKeys,
      onChange: this.onSelectChange
    }
    if (row_selection === false || row_selection === undefined) {
      row_selection = false;
    } else if (row_selection === 'radio') {
      rowSelection.type = 'radio';
    }
    return <Table
      bordered
      {...this.props}
      rowSelection={row_selection?rowSelection:null}
      onRow={(record,index) => {
        if (!row_selection) {
          return ;
        }
        return {
          onChange: () => {this.onRowClick(record, index)},
          onClick: () => {this.onRowClick(record, index)},
        };
      }}
    />
  }
  render() {
    return (
      <div>
        {this.tableInit()}
      </div>
    );
  }
}

export default ETable;

form封装:
首先form封装我们想把它做成配置式的,通过一个数组将要渲染的表单元素传给form组件,里面应该有我们要渲染的表单元素的信息,比方说type类型、field、label、list、placeholder、width等,表单类型不一样,首先需要判断一下type类型,然后进行不同的处理,之后把它放进一个数组当中;之后返回这个数组,render出来.

import React, { Component } from 'react';
import { Input, Select, Form, Button, Checkbox, Radio, DatePicker } from 'antd';
import Utils from '../../utils/utils';
const Option = Select.Option;
const FormItem = Form.Item;

class FilterForm extends Component {

  handleFilterSubmit = () => {
    let fieldsValue = this.props.form.getFieldsValue();
    this.props.filterSubmit(fieldsValue);
  }

  initialFormList = () => {
    const { getFieldDecorator } = this.props.form;
    const { formList } = this.props;
    const formItemList = [];
    if (formList && formList.length > 0) {
      formList.forEach((item, i) => {
        let { label, field, placeholder, width, list, type } = item;
        let initialValue = item.initialValue || '';
        if (type === "时间查询") {
          const begin_time = <FormItem label="订单时间">
            {
              getFieldDecorator("begin_time")(
                <DatePicker showTime={true} format="YYYY-MM-DD HH:mm:ss" placeholder="请选择时间"></DatePicker>
              )
            }
          </FormItem>
          formItemList.push(begin_time);
          const end_time = <FormItem label="~" colon={false}>
            {
              getFieldDecorator("end_time")(
                <DatePicker showTime={true} format="YYYY-MM-DD HH:mm:ss" placeholder="请选择时间"></DatePicker>
              )
            }
          </FormItem>
          formItemList.push(end_time);
        }else if (type === "SELECT") {
          const SELECT = <FormItem label={label} key={item.field}>
            {
              getFieldDecorator([field],{
                initialValue
              })(
                <Select
                  placeholder={placeholder}
                  style={{width}}
                >
                  { Utils.getOptionList(list) }
                </Select>
              )
            }
          </FormItem>
          formItemList.push(SELECT);
        } else if (type === 'INPUT') {
          const INPUT = <FormItem label={label}>
            {
              getFieldDecorator([field],{
                initialValue
              })(
                <Input type="text" placeholder={placeholder} style={{width: width}} />
              )
            }
          </FormItem>
          formItemList.push(INPUT);
        } else if (type === 'CHECKBOX') {
          const CHECKBOX = <FormItem label={label}>
            {
              getFieldDecorator([field],{
                valuePropName: 'checked',
                initialValue
              })(
                <Checkbox>{label}</Checkbox>
              )
            }
          </FormItem>
          formItemList.push(CHECKBOX);
        }
      })
    }
    return formItemList;
  }

  render() {
    return (
      <Form layout="inline">
        {this.initialFormList()}
        <FormItem>
          <Button type="primary" onClick={this.handleFilterSubmit}>查询</Button>
          <Button onClick={this.reset}>重置</Button>
        </FormItem>
      </Form>
    );
  }

  reset = () => {
    this.props.form.resetFields();
  }
}

export default Form.create({})(FilterForm);

公共组件封装

时间格式化组件封装

formateDate(time) {
    if (!time) return;
    let date = new Date(time);
    let hours = date.getHours() < 10 ? "0"+date.getHours() : date.getHours();
    let minutes = date.getMinutes() < 10 ? "0"+date.getMinutes():date.getMinutes();
    let seconds = date.getSeconds()<10?"0"+date.getSeconds():date.getSeconds();
    return date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate() + ' ' + hours  + ':' + minutes + ':' + seconds; 
  },

table中的pagination

pagination(data, callback) {
    return {
      onChange: (current) => {
        callback(current);
      },
      current: data.result.page,
      pageSize: data.result.page_size,
      total: data.result.total,
      showTotal: () => {
        return `共${data.result.total}条数据`
      },
      showQuickJumper: true
    }
  },

form中下拉菜单的封装

getOptionList(data) {
    if (!data) {
      return [];
    }
    let options = [<Option value="0" key="all_key">全部</Option>];
    data.map(item => {
      options.push(<Option value={item.id} key={item.id}>{item.name}</Option>);
    });
    return options;
  },

axios封装

static ajax(options) {
    return new Promise((resolve, reject) => {
      axios({
        url: options.url,
        method: 'get',
        timeout: 5000,
        params: (options.data && options.data.params) || ''
      }).then((response) => {
        console.log(response);
        if (response.status === 200) {
          resolve(response.data);
        } else {
          reject(response.data);
        }
      })
    })
  }

跨域封装

static jsonp(options) {
      return new Promise((resolve, reject) => {
          JsonP(options.url, {
              param: 'callback'
          }, function (err, response) {
            console.log(response);
            console.log(err);
              if (response.status === 'success') {
                  resolve(response);
              } else {
                  reject(response.messsage);
              }
          })
      })
  }

自我介绍2分钟:年龄,毕业学校,工作年限,前一家公司规模和开发模式,开发中的问题,不要说基础问题,前后端交互问题,什么公司说明白(建站/外包/外派)

问项目的话挑一个比较熟的,(项目目的,负责版块,用到的技术,遇到的问题)

数据类型分类、区别

基本数据类型是保存在栈内存中的简短数据段,数据大小是确定的,内存可以分配,我们操作、拷贝的是变量的值
引用数据类型在栈内存中保存的是数据在堆内存的地址,数据保存在堆内存中,我们操作、拷贝的是变量的地址

栈内存和堆内存的区别:栈内存和堆内存都是存储数据的地方;栈内存由操作系统自动分配和释放,速度快,使用方便,无法手动控制,内存空间有限;堆内存需要手动申请和释放,一般通过new关键字来分配,分配的速度慢,地址不连续,容易碎片话化,内存空间几乎没有限制,当我们使用new关键字来申请一块堆内存时,系统会遍历一个记录空闲内存地址的链表,寻找第一个空间大于所申请空间的堆节点,将这个节点从空间内存地址链表中移除,并将该节点的地址分配给程序,由于需要手动销毁,容易造成内存泄漏;

垃圾回收机制

浏览器会每隔一段时间查找一次那些不再使用的变量占用的内存,将其回收。
两种方法:标记清除和引用计数。

造成内存泄漏的场景

指一块被分配的内存既不被使用,又没有回收,直接进程结束才销毁的内存
1.意外的全局变量会会造成内存泄漏,比方说没有使用var,let,const关键字创建的变量
2.对象的互相引用
3.遗忘的定时器:setTimeout和setInterval是由浏览器专门线程来维护他的生命周期,当某个页面使用了定时器,当页面关闭时,并且没有手动关闭,这些定时器还是存在的,当定时器内部使用了回调函数,且回调函数调用了DOM元素,即使页面销毁了,这些东西还保存在内存中,造成内存泄漏。
4.使用不当的闭包。当一个函数内部返回另一个函数时,并且这个函数内部引用了外部函数词法环境中的变量,而返回的函数又被其他生命和周期的东西所占有,就会导致外部函数虽然执行完了,但还是无法被回收,滥用闭包就会造成内存泄漏。
5.遗漏的DOM元素
6.网络回调

常见的闭包场景、闭包实现是为了干什么、实现的方式有哪些(redux是闭包吗)

概念:一个函数内部的能够读取自己所有变量和方法的函数
场景:

  1. 定时器中的使用setTimeout:用闭包可以实现给function函数传值
  2. 匿名自执行函数
  3. 封装,实现面向对象

作用:

  1. 避免全局变量的污染
  2. 使某个变量或者函数长期驻扎在内存中,不被立即回收机制回收

JS中保存状态的方式

JS中检测对象是否反生改变的方法(proxy,Object中的一个方法,自己封装函数)

1.VueJS 则使用 ES5 提供的 Object.defineProperty(obj,key,{get(){},set(){}}) 方法
2. Proxy拦截器
3. 自己写函数

检测数据类型的方法

  1. typeof
  2. Object.prototype.toString.call()
  3. instanceOf()

弹性布局,简单说一下弹性盒子

是CSS3一种新的布局方式,以适应不同的屏幕大小及设备类型

5. rem用过吗?之前的项目是你自己封装的还是?你担任什么职位?你开发的整项目还是几个页面?给你几个业务面开发的话,你自己的页面开发完了如何和其他人的合并到一起?(开发模式,很重要)(项目基础配置都有了,但是我也了解)

6. 整个项目的开发的时候你会注意哪些问题?(看一下项目构建用到的包,react版本等,版本一般向下兼容,低版本的访问不了高版本的;可能自己用到的包项目里没有;尽量不要动别人的代码,否则别人提交时会报错:本地和远程不同步;看公共机制,利用utils封装好的公共机制可以简化自己代码,提高开发效率;自己组件的性能优化)

7. react性能优化从哪几方面着手?低版本不支持pureComponent和react.memo怎么办?

  1. pureComponent、react.memo
  2. react hooks
  3. key
  4. bind(this)指向写在constructor里面

什么会造成页面刷新?

  • state和props的改变
  • 父组件重新render
  • 调用了setState后无论数据是否改变都会引起重新render

setState是同步还是异步?为什么是异步?

异步的,可以提高页面的渲染性能

ES6新增的API

  • let const 关键字
  • 箭头函数
  • 字符串模板
  • 结构
  • 不定参数
  • 拓展参数
  • for of遍历
  • Set
  • Map数据结构
  • 数据结构默认的iterator接口
  • generator函数
  • 严格模式
  • Module
  • Proxy
  • Symbol
  • 模板字符串
  • Promise

diff算法和虚拟DOM,key值是必须的嘛?不加会怎么样?你会用什么绑定key值?他俩实现了什么?为什么使用他俩?

虚拟DOM就是js对象,具有批处理和高效的diff算法,他可以确保我们只对界面上真正变化的部分进行实际的DOM操作;
diff算法:在页面刚开始render的时候,会创建一棵DOM树,当我们的state或者props发生改变的时候会重新render一棵DOM树,而react基于两点假设,相同的组件产生相同的DOM结构,不同的组件产生不同的DOM结构,同一层次的节点可以通过唯一的key值进行区分

重绘和回流?那些问题会造成重绘?(CSS问题,很重要)

当页面上的元素改变但是不影响页面布局时,就会引发重绘,这时只需要ui层面的重新绘制,性能损耗较小,如字体颜色、背景色等改变;而当元素的几何属性发生变化,例如大小尺寸、位置等,或者浏览器窗口大小和DOM树结构发生变化会引发重排,又称回流。
重排优化:减少页面上的DOM操作

  • 多次DOM元素的样式操作一次完成
  • 批量添加DOM元素一次插入
  • 将position设置成absolute或者fixed,或者display设置成none,使其脱离文档流或者先不渲染
  • 尽量在内存中操作节点

节流和防抖(setState做了防抖)

  • .

异步对象(Promise,Generator,回调函数:ajax,setTimeout,setInterval,async,await,发布订阅模式,事件监听)

ajax放在哪?为什么放在componentDidMount()里边?props在哪里可以访问?(render,setState,mapStateToProps,mapDispatchToProps)

15.6之前有getDefaultProps和getInitialState,新版本没有,ES6中删除

说一下路由;你配置路由怎么做;防止重复匹配的方法;路由传递的3个属性:match、history、location;

this.props.match.params
new URLSearchParams(this.props.location.search)

- 什么是高阶组件?(把组件当做参数传递进去,进行处理,再return出来)

  • 对redux的理解;怎么做异步;说一下saga是怎么做的;redux怎么保存状态的;创建redux的时候,redux是怎么做状态保存的(initialState怎么保存下来的?闭包,createStore返回一个对象,对象里的getState是什么?就是initialState)
  • ts必问问题:类型断言、类型检测、类型逐步接、类型推断、接口和泛型(重点)
  • 从我们输入url到页面呈现发生了什么?(越详细越好)dns域名解析,进行客户端和服务器的连接:发生三次握手(发送报文,响应报文,客户端再次发送报文,连接),服务器发送html文档,里面有DOM,特殊标签link的href和src,单独隔离出来,添加到tastquery队列,再去请求这些资源,请求回来以后,首先创建一个CSSrenderTree,js回来直接执行,CSSTREE和DOMTREE结合,形成一个renderTree,期间,js回来可能会在link之前,但是js直接执行,这时候会发生css阻塞(会问,浏览器有很多线程,jui线程,ajax请求线程,计时器线程,清除计时器线程,js线程优先级最高,jui排在后面,所以会发生阻塞);断开连接,4次挥手
  • 说一下什么是dva?状态用model管理;effects管理一部,用generator实现
  • 介绍一下umi:umi是云谦前辈对dva再次封装,他是可插拔式的一个应用,比如说我们相拥dva,只需要在创建项目的时候选择启用就行了,包括antd;他的路由比较特殊,他是配置式路由
  • vue和react的区别:vue就是一个模板,react开发更倾向于原生
  • v-model使用思路:用proxy代理实现双向绑定
  • vue性能优化:去哪网的keep-alive文件
  • 自己搭建过一个项目吗?webpack配置项
  • modules和plugins的区别
  • loder的配置规范
  • 优化在那个配置项里面做
  • 项目优化有哪些优化?页面优化?不要搞混了
  • 项目优化你怎么做?(公共机制,基础库代码单独分离出来,资源内联)页面优化是开发的优化,项目优化是webpack里面的优化
  • 怎么解决bundlejs文件过大的问题(loable-able插件,代码分割和动态加载,html-webpack-externals-plugin,SplitThunksPlugin)
  • 简述一下git,为什么要用git
  • es6新增的特性
  • Promise
  • es6中的set使用:利用Set去重得到的不是数组结构,需用Array.from()进行处理;其内部使用sameValueZero Equality算法实现
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值