当前位置: 首页 > news >正文

个人技能点(郎)

个人技能点

    • 1. 熟悉 h5 和 c3 新特性:语义化标签,flex 布局,动画等
      • H5 新特性:
    • 2. 熟悉js作用域、原型、事件轮询机制、闭包等原理;
      • js 作用域
      • 闭包
      • 事件轮询机制
      • 原型
    • 3. 熟悉 ES6 语法标准 promise,async/await 异步方案,箭头函数等
      • `Promise`思路:
      • generator
      • async/await
      • promise 和 async/await 的区别
      • 箭头函数
    • 4. 了解 ajax 前后台数据交互原理,熟练使用原生 ajax 及 ajax 类库,如: axios;并掌握 jsonp、cors、proxy 等跨域解决方案
      • 原生 ajax 写法
      • ajax 状态码
      • ajax 和 http 请求的区别
      • 跨域相关
      • 从输入 url 地址到显示页面都发生了什么
      • http1.0/http1.1/2.0的区别
      • http 和 https 的区别
      • http 2.0/1.x 的新特性
    • 7. 熟练使用 npm、yarn 等包管理工具和 git 版本管理工具
    • 8. 熟悉 json-server/express 服务器搭建、postman 接口测试等工具
      • json-server
    • 9. 熟练使用 vue 开发项目,使用 vuex 实现多组件数据共享;使用vue-router 实现单页面应用
      • vuex
      • vue-router
      • vue-router 原理
        • history 404 问题
      • vue-router 的路由导航钩子
        • 1. 全局前置守卫
        • 2. 全局解析守卫
        • 3. 全局后置守卫
        • 4. 路由独享守卫
        • 5. 组件内的守卫
        • 1. to: Route: 即将要进入的目标 路由对象
        • 2. from: Route: 当前导航正要离开的路由
        • 3. next: Function: 一定要调用该方法将控制权交给下一个守卫,执行效果依赖 next 方法的参数。
        • 永远不要使用两次 next,这会产生一些误会。
        • 导航的全过程
      • 路由拦截
      • 路由传参
    • 10. 熟练使用第三方插件库:element-ui、ant-design、swiper、dayjs 等
    • 11. 了解 Vue 响应式数据原理和双向数据绑定原理
        • Vue的响应式原理
        • 双向数据绑定原理
    • 12. 熟练掌握 vue 组件通信的多种方案:Vuex,props,sync 全局事件总线等以及 vue 的声明周期钩子函数
      • vue组件之间通讯
    • 13. 熟练解决移动端适配:viewport,rem,vw 等
      • 适配方案
    • 14. 熟悉小程序开发,熟悉小程序的 WXML、WXSS、JS 等开发规范
      • 小程序的特点
      • 小程序适配
      • 小程序相关语法
      • 微信小程序登录流程
      • 小程序获取用户唯一标识(openId)
      • 小程序支付流程
      • 面试问题
    • 15. 熟练使用 commonjs 和 es6 模块化规范进行开发
    • 16. 对页面进行懒加载、限制前台页面不必要请求、节流防抖等优化方案
    • 17. 了解 TypeScript 语法,接口,类,泛型等
      • 接口
      • 泛型
    • 18. 了解Vue3新特性(setup,ref,reactive,新组件等)
      • render 函数和 template 有什么区别
    • 19. 了解 webpack 配置基本设置,掌握 tree shaking、代码分割等优化方案
    • 20. 补充
        • 免登录
      • 自定义指令
      • Vue的性能优化
      • 深拷贝
      • 1. 自定义深拷贝
        • 2. 利用json串
      • 取消请求
      • Vue打包优化
      • 权限控制
      • 按钮权限值
        • 1. 方法一:自定义指令
        • 2. 方法二:v-if
      • webpack 优化
        • 1. 配置 webpack
        • 2. 优化
          • 数摇
          • 代码分割
          • 缓存配合:后端如果使用强缓存
          • PWA(Progressive Web App):
          • 多进程打包
      • 项目相关
        • 1. axios 二次封装
        • 2. 路由传参数问题
          • query 和 params 传参数
        • 3. lodash 按需引入
        • 4. 使用 dataset 进行数据的传递
      • 4. swiper
        • 5. 自定义分页器
      • vue后台项目
      • 面试
      • 面试补充
        • 1. ES5 数组方法:
        • 1. ES6 数组方法
        • 2. ES5 字符串方法
        • 2. ES6 字符串方法
        • 3. ES6 对象方法:
      • 自定义组件的步骤
      • 在项目中遇到过什么难点
      • 浏览器,小程序和 node 中的 js 有什么区别
      • 苹果树面试
      • 小鹅通面试
      • 名竹科技
      • 爱德博
      • React
        • 生命周期钩子函数
      • React 路由
      • Redux

1. 熟悉 h5 和 c3 新特性:语义化标签,flex 布局,动画等

H5 新特性:

  • 我所了解到的h5新特性主要有:新的语义化标签,新的表单增强和表单控件,本地存储,音视频API,Geolocation等,其中在开发中所用到的最多的就是
    • 为什么要语义化标签:
      • 语义化标签更具有可读性,便于团队的开发和维护
      • 在没有css的情况下也能更好的展现出页面的结构
      • 关于seo,搜索引擎能够更好的理解页面之间的关系,能够更准确的搜索信息
      • 在写页面的时候,尽量少的使用div+span的布局方式
    • 盒模型:可通过box-sizing来控制盒模型的方式
      • content-box
      • border-box
      • padding-box
      • margin-box(未实现)
    • flex布局
      • 可以通过 display: flex 来开启
      • 亮点:
        • flex-flow:是flex-direction和flex-wrap的缩写
        • flex: flex-grow,flex-shrink和flex-basis的缩写
          • 默认是0 1 auto
          • none: 0 0 auto
          • auto: 1 1 auto
          • 1 :1 1 任意长度+任意单位
    • 动画:animation

2. 熟悉js作用域、原型、事件轮询机制、闭包等原理;

js 作用域

  • 首先,作用域是变量起作用的一个范围。

  • 作用:用来隔绝变量,防止命名冲突。

  • js作用域的分类:

    • 全局作用域:全局代码就是一个全局作用域。
    • 局部作用域:也被称为函数作用域。
    • 块级作用域:es6新增块级作用域就是一个大括号,并且变量要使用 let/const 进行定义才能生效。
  • 作用域产生的条件和销毁

    • 代码定义的时候就会产生。
    • 代码执行完毕销毁的是变量对象而不是作用域。
    • 作用域从代码定义的时候就会产生,除非关闭程序才会销毁。
  • 作用域的实现是变量对象

    • 变量对象存在于执行上下文环境中,只有生成执行上下文的时候,变量对象才会被激活,只有激活变量对象,才能访问当前作用域的属性和方法。
    • 变量对象分为全局变量对象和局部变量对象
      • 全局变量对象:window。
      • 局部变量对象
    • 变量对象:
      • 首先包含形参和实参。
      • 扫描定义的函数,并将函数作为名值对储存在函数变量对象的属性中,如果变量对象中有同名,则直接覆盖。
      • 扫描定义的变量,保存在变量对象中,如果与变量对象中的形参和函数同名, 则直接不会影响到他们。
  • 执行上下文环境

    js代码在正式执行之前 js 引擎会先做一些准备工作:

    1. 创建执行上下文环境。
    2. 创建一个空的对象(执行上下文对象),该对象用于收集当前作用域的:变量,函数,函数的参数。
    3. 确认this 的指向。
    4. 创建当前环境的作用域链。
  • 作用域链

    • 作用域链就是查找变量的一个过程,首先会在自身的作用域中查找,如果有就使用,如果没有,去上级作用域中查找,一直查找到 window,如果还没有找到就会报错 xxx is not defined。

闭包

  • 什么是闭包:
    • 函数嵌套函数,闭包是嵌套的内部函数。
    • 闭包是包含被引用变量的对象,在 chrome 开发者工具中查看,闭包是 closure 属性,他存在于 scope 属性中。
    • 闭包是一个意外存活的变量对象:
      • 证明:两个内部函数同时引入外部函数的同一个变量的时候,他们的闭包是同一个闭包。
  • 闭包的形成条件:
    • 函数嵌套函数。
    • 内部函数引用外部函数的变量。
    • 外部函数调用。
  • 闭包的产生时机:内部函数定义执行。
  • 闭包的作用:
    • 延长局部变量起作用的范围。
    • 外部能够操作内部局部变量。
  • 闭包的缺点
    • 容易造成内存泄漏,甚至造成内存溢出。
    • 解决方法让内部函数 = null
  • 闭包的应用
    • React 的高阶函数。
    • Vue 源码中的数据劫持,watcher 保存 node 节点以及保存更新函数。

事件轮询机制

  • 事件轮询机制一共有两种一个是 js 事件轮询一个是 nodejs 的事件轮询。
  • js 事件轮询机制:
    • js 中的代码分为初始化代码(同步代码)和异步回调代码(异步代码)
      • 初始化代码主要是一些设置定时器,绑定事件,发送 ajax 等。
      • 异步回调代码主要是:定时器的回调函数,事件处理回调函数,ajax 的回调函数。
    • 事件轮询中有个重要模块:
      • 事件管理模块
        1. 定时器管理模块。
        2. dom 时间管理模块。
        3. ajax 管理模块。
        4. MutationsObserver 管理模块。
      • 回调对列:
        • 宏任务:
          • setTimeout,setInterval,ajax,dom事件监听,等
        • 微任务
          • promise,async/await,mutationsobserver等
    • js 代码的执行过程是:
      • 首先会执行同步代码,如果遇到了异步回调代码,会先将异步回调代码交给事件管理模块处理。
      • 当事件管理模块模块中的事件触发,将对应的回调函数注册到回调队列中。
      • 当初始化代码执行完毕的时候,会遍历回调队列中的回调函数执行。
    • 微任务和宏任务
      • 如果不将主线程中的代码视为第一宏任务,那么微任务优先于宏任务。
      • 执行过程是
        • 会优先执行微任务中的所有回调,只有当清空微任务,并且执行完 GUI 渲染线程,才能执行宏任务中的第一个回调函数,每执行完一个宏任务中的回调都会检查微任务中是否有回调,如果有,则必须清空微任务,在继续执行宏任务中的第一个回调。
  • nodejs 中的事件轮询
    • node 中的事件轮询一共分为六个阶段,
      • timers 计时器阶段。
      • I/O callback I/O 事件回调。
      • idle,prepare 准备阶段。
      • poll 轮询阶段。
      • check 检查阶段。
      • close callbacks 关闭阶段。
    • 他们会按照顺序反复执行,每当进入一个阶段的时候,会遍历其中的回调函数依次执行,直到该阶段清空,达到系统最大上限才会进入下一个阶段进行执行。
    • 最重要的有三个阶段:
      • timer 计时器阶段:执行 setTimeout 和 setInterval 回调。
      • poll 轮询阶段,执行 I/O 回调,处理事件轮询中的事件。
        • poll阶段会存在两种情况:

          1. 如果 poll 阶段为空:如果check阶段或者是timer阶段有回调函数,则会进入下一个阶段继续执行。

          2. 如果不为空,则会在此阶段等待回调函数添加。

            如果 poll 中有回调。则遍历执行,只到清空或者达到最大上限。

      • check 阶段,此阶段执行 setImmediate。
  • node 中还有一个特殊的process.nextTick,它不属于以上的所有阶段,在每个阶段完成后,如果存在nextTick 队列,则会清空回调中的所有回调,这个回调又优于所有的微任务。

原型

  1. 总:

    • 我们所说的原型,说的是两个属性:
      1. 其实是包括函数的显示原型属性prototype
      2. 另外一个就是对象上的隐式原型属性__proto__。
  2. 分:

    1. 显示原型属性:
      1. 显示原型属性存在于函数中,当然__箭头函数__是没有显示原型对象的。
      2. 显示原型在函数创建的时候就会产生,默认是__指向__的是一个Object实例对象。
      3. 里面有一个constructor属性,指向的是拥有这个显示原型的函数。
    2. 隐式原型属性:
      1. 所有的对象都拥有隐式原型属性__proto__
      2. 这个__proto__指向的就是这个对象的构造函数的显示原型对象。
      3. 所以说构造函数的显示原型对象和这个构造函数的隐式原型对象指向的是同一个对象,这也是他们的联系。
    3. 特殊情况:
      1. 所有的函数都是由Function构造调用得到的函数对象,每一个函数除了拥有显示原型属性之外,也会拥有一个隐式原型属性__proto__

      2. Function的隐式原型属性__proto__会指向的是它本身的prototype属性。这条线是作者自己指定的。

      3. Object 的显示原型对象prototype__proto__为 null。

      4. js中由C语言创建的内容有:

        1. Object
        2. Function
        3. Function.prototype
      5. 由作者自己创建的四条线:

        1. Function.prototype = Function.__proto__

          目的:函数的所有公共方法都存在Function.prototype,所以为了使得Function能访问到这些方法,就必须指这条线。

        2. Object的隐式原型属性和Function的显示原型属性,指向的是同一个对象。

          目的:同上。

        3. Function.prototype = Object.prototype

          目的:为了讲原型对象串联起来。

        4. Object.prototype.__proto__ = null

          目的:为了使得原型链有终点。

    4. 原型链
      1. 作用就是查找对象中的属性的一种规则。
      2. 规则:
        1. 首先在自身上查找属性,如果有则直接返回值。
        2. 没有则沿着隐式远行属性__proto__上查找。
        3. 一直到Object.prototype.__proto__由于他的值是 null,所以会返回 undefined。
    5. 原型的作用:
      1. 被同一个构造函数调用的多个实例对象共有的属性和方法,实现原型链继承。
      2. vue 中的全局事件总线,通过给Vue的显示原型对象添加一个$bus对象,内部包含了$on,$emit,$once,$off等方法,由于组件实例的隐式原型对象的隐式原型对象指向的是Vue的显示原型对象,所以能够在任意的组件中使用$on,$emit,$once,$off方法。
      3. vue 中可以给 vue 原型对象添加方法,所有的组件都能够使用。

3. 熟悉 ES6 语法标准 promise,async/await 异步方案,箭头函数等

Promise思路:

  • 什么是PromisePromise的状态,怎么使用PromisePromise原型方法,Promise的静态方法,Promised的应用

  • Promise是一个异步编程的解决方法,避免了地狱回调的书写方式。

  • Promise是一个构造函数,需要实例化调用:

    • new Promise()后面需要传入一个回调函数,回调函数默认传入两个参数,一个是resolve,另一个是reject
    • new Promise默认会返回一个成功的promise,结果是undefined
    • 如果在回调中调用了resolve,则表示该promise对象是成功状态的,结果是resolve()中传入的参数。
    • 如果在回调中调用了reject,则表示该promise对象是失败状态的,结果reject中的参数。
    • 如果new Promise中抛出了错误,则返回的promise对象也是失败的,失败的原因就是错误的原因。
  • Promise的对象一共有三种状态:

    • pending:无状态,便是promise对象是初始化状态,或者还未完成。
    • resolved/fulfilled:表示promise为已经完成的状态。
    • rejected:表示Promise是失败的状态。
    • promise的状态只能改变一次。
  • Promise上的原型方法

    • then:默认会返回一个 promise 对象。
      • 返回成功的 promise:
        • then 函数返回其他值。
        • then 返回成功的 promise 对象。
      • 返回失败的 promise:
        • 函数出错。
        • 返回失败的 promise 对象。
      • 穿透:返回上一个 promise 的结构和状态。
    • catch
      • 是 then 的一个语法糖,相当于第一个回调没有传入,只传入第二个回调函数。
  • Promise的静态方法

    • all:

      • 传入一个或者多个promise对象。
      • 如果所有的promise都返回成功,则会返回成功,如果有一个返回失败则返回失败。
      • 如果成功,则promise的结果是一个数组,数组中是所有 promise 的结果。
      • 如果失败,则promise的结果是失败的那个promise的原因。
    • allSettled

      • 总是返回成功的promise
      • promise的结果总会是一个数组,数组中是一个个对象,对象中有 status,和 value(成功)/reason(失败)。
    • any

      • 传入一个或者多个 promise 对象。

      • 返回最快成功那个 promise 对象。

      • 如果全部失败,则返回的是一个失败的 promise 对象,结果是一个对象,对象中的 error 是一个数组,数组中保存的是失败的原因。

      • Promise {<pending>}__proto__: Promise[[PromiseState]]: "rejected"[[PromiseResult]]: AggregateError: All promises were rejectederrors: (3) ["p1失败了", "p2失败了", "p3失败了"]message: "All promises were rejected"stack: "AggregateError: All promises were rejected"__proto__: Error
        
    • race

      • 返回最快的那个promise对象,不管是成功还是失败的。
    • resolve

      • 返回一个成功的promise对象。
    • reject

      • 返回一个失败的promise对象。

generator

  • generatorES6引入的语法,是一个可以暂停和继续执行的函数。
  • 可以当作一个iterator 迭代器对象来使用,可以进行遍历操作。
    • Iterator 是一种接口,目的是为不同的数据结构提供统一的数据访问机制。也可以理解为 Iterator 接口主要为 for of 服务的,供for...of进行消费。
  • 也可以当成一个状态机来使用:
    • generator使用function*来进行定义。
    • 函数内部通过yeild来暂停函数的执行,表达式默认返回undefined
    • 然后执行之后返回的一个迭代器对象的next()方法来继续函数的执行,传入的参数是上一次的yeild的返回值。

async/await

  • 是解决回调地狱的终极解决方案,以同步代码方式书写异步代码。
  • generator的语法糖。
  • async对应的是*
  • await对应的是next()
  • async/await自动进行了generator的流程控制。
  • 并且await只会暂停 promise 的操作,其他的异步不会暂时。
  • async/await的返回值问题:
    • async函数的返回值是一个promise对象。
    • 对象的状态由函数状态决定,函数如果执行完毕,则返回一个成功的 promise,否则返回一个失败的promise
    • 这个promise对象的返回值是函数的返回值。
    • 如果出错(await 后面跟着一个失败的 promise 也算是报错),会中断 promise 对象的执行,并且这个返回的 promise 对象是一个失败的 promise,返回值是错误原因。

promise 和 async/await 的区别

  • async/await 相对于 promise 来讲,写法更加优雅。
  • promise 的错误通过 catch 来捕获。
  • async/await 通过 then 来捕获,也可以通过 try/catch 来捕获。

箭头函数

  • ES6 新增了一种函数的定义方式,箭头函数,使用 => 来进行定义,被称为箭头函数。
  • 箭头函数没有自己的 this,它的 this 指向的是上一层作用域的 this。
  • 箭头函数不能当作构造函数。
  • 箭头函数没有 arguments。
  • 箭头函数没有原型对象。

箭头函数不能 new 的原因:

new 的本质是生成一个新对象,将对象的__proto__指向函数的 prototype,再执行call 方法。
普通构造函数通过 new 实例化对象时 this 指向实例对象,而箭头函数没有自己的 this,用 all() 或者 apply() 调用箭头函数时,无法对 this 进行绑定。
箭头函数没有 prototype 属性 ,不能作为构造函数,否则 new 命令在执行时无法将构造函数的 prototype 赋值给
新的对象的 __proto__

4. 了解 ajax 前后台数据交互原理,熟练使用原生 ajax 及 ajax 类库,如: axios;并掌握 jsonp、cors、proxy 等跨域解决方案

原生 ajax 写法

  1. 创建 xhr 对象:

    const xhr = new XMLHttpRequest()

  2. 设置请求首行:定义请求方式和请求地址:

    xhr.open(get/post,url)

  3. 设置请求头:GET 请求不用设置:

    xhr.setRequestHeader('content-type','application/x-www-form-urlencoded')

  4. 发送请求

    xhr.send(data)

  5. 监听状态

    xhr.onreadystatechange = function(){xhr.readyState === 4// 0 1 2 3 4 xhr.status === 200
    }
    

ajax 状态码

  • 2xx:表示成功处理请求
    • 200:表示成功处理请求
    • 201:添加数据成功
  • 3xx:表示需要重定向,浏览器直接跳转
    • 301:永久性重定向
    • 302:暂时性重定向
    • 304:使用缓存
  • 4xx:客户端请求错误
    • 401:没有访问权限
    • 404:访问的资源不存在
  • 5xx:服务器端错误
    • 500:服务器程序运行错误

ajax 和 http 请求的区别

  • 跨域的预检查:不进行预检查的有:

    • 简单请求GET,HEAD,POST(Content-Type 必须是 application/x-www-form-urlencoded, multipart/form-data 或着 text/plain 中的一个值)。
    • 没有自定义 HTTP 头部。
  • ajax 请求是一种特别的 http 请求。

  • 对服务器端来说,没有任何区别,区别在于浏览器端:http 不会发生跨域报错,而 ajax 会发生跨域报错。

  • 只有 ajax 请求或者是 fetch 发出的才是 ajax 请求,其他所有都是非 ajax 请求。

  • 浏览器端接收到响应:

    • 一般请求:浏览器一般会直接接收响应体数据。
    • ajax 请求:不会对界面进行任何的更新操作(不会刷新页面),只是调用监视的回调函数并传入相关数据。

跨域相关

  • 同源策略
    • 只有协议名,域名,端口号三者都相同才能称为符合同源策略。
    • ajax 请求时,浏览器要求当前网页和 server 必须同源(安全),否则会抛出跨域错误。
    • 加载 image/link/script 时不受同源策略的影响,也就是不会发生跨域报错。
  • 同源策略限制的范围:
    • 影响 ajax 请求。

    • 影响 dom 获取:不能获取 iframe 内联框架和 window.open 的 dom。

    • cookie,localStorage,indexedDB。

      indexedDB: IndexedDB 就是浏览器提供的本地数据库,它可以被网页脚本创建和操作。IndexedDB 允许储存大量数据,提供查找接口,还能建立索引。这些都是 localStorage 所不具备的。就数据库类型而言,IndexedDB 不属于关系型数据库(不支持 SQL 查询语句),更接近 NoSQL 数据库。

  • 解决跨域
    • jsonp
      • 原理:利用了 script 标签不受同源策略的影响。
      • 前台
        • 创建一个函数,用于调用接收服务器返回的数据
        • 创建一个 script 标签,src 上输入需要发送请求的地址,并且参数带上定义的函数。
      • 后台
        • 处理请求,产生需要返回的数据。
        • 读取请求参数,获取传入的函数。
        • 将数据作为函数的实参以字符串的形式返回给前台。
      • 前台调用获取数据。
    • 缺点:
      • 只能处理 get 请求。
      • 每一个请求都需要进行处理。
  • cors
    • 原理:设置响应头,让浏览器能够接收跨域的响应。
    • 需要在服务器进行设置,前端不需要进行任何设置。
    • 一般可以设置允许哪些地址进行跨域。
    • 允许哪些请求可以跨域。
    • 指定哪些请求头(Access-Control-Allow-Origin: *)跨域进行跨域。
  • 代理:
    • proxy 正向代理,需要知道目标服务器。
    • 原理:服务器与服务器之间不会发生跨域报错,也就是不受同源策略的影响。
    • 正常情况下,浏览器向目标服务器发送请求会发生跨域问题。
    • 为了解决跨域,可以让浏览器像开发服务器发送请求,然后由开发服务代替浏览器发送请求。
    • 目标服务器向代理服务器返回数据,代理服务器再向客户端返回数据。
  • 反向代理 Nginx:不需要知道目标服务器,负载均衡。

从输入 url 地址到显示页面都发生了什么

  • 进行 DNS 解析:
    • 会首先在浏览器的 DNS 缓存中查找域名对应的 web 服务器 IP 地址,如果没有则依次到计算机 DNS 缓存,路由 DNS 缓存,运营商 DNS 缓存,如果没有,就向公共的域名解析服务器查找,这个查找是一个递归的过程,如果查找到,则跳到下一步.
  • 检查浏览器中是否有缓存:
    • 通过 cache-control 和 expires 来检查是否命中强缓存,如果有缓存直接使用缓存进行渲染。
    • 如果没有没有命中强缓存,则会向服务器发送请求(会先进行 TCP 连接),服务器会通过 Etag(资源的唯一标识符)和 last-Modify(最后一次修改的时候)来确定缓存是否失效,也就是进行协商缓存,若无更改,则返回状态码 304,浏览器读取本地缓存。
    • 如果强缓存和协商缓存都没有命中,则返回响应结果。
  • 进行 TCP 连接
    • 通过三次握手进行连接,这三次握手可以简单概述为:
      • 浏览器发送给服务器,告诉服务器我准备好了,即将发送请求。
      • 服务器发送给浏览器,告诉浏览器我准备好了,请你在确认一遍。
      • 浏览器发送给服务器,告诉服务器我确认好了,即将发送请求。
  • 发送请求:请求报文发送给服务器。
  • 接收响应:浏览器接受响应报文。
  • 解析渲染页面
    • 遇到 html 文件,调用 html 解析器,生成 DOM树。

    • 遇到 css 文件,调用 css 解析器,生成 CSSOM 树。

      CSSOM: css 对象模型。CSSOM 是一组允许 JavaScript 操作 CSS 的 API。它非常类似于 DOM,但是用于 CSS而不是 HTML。它允许用户动态读取和修改 CSS 样式。

    • 遇到 js 文件,调用 js 解析器,解析 js 代码:

      • 可能会修改html,再次调用html解析器,修改dom树
      • 可能会修改css,再次调用css解析器,修改cssom树
    • 将 dom 树和 css 进行合并在一次生成 render tree(渲染树)。

    • 进行渲染,将颜色/文字/图片等渲染上去。

  • TCP 四次挥手:
    • 浏览器发送给服务器,告诉服务器请求报文发送完毕。
    • 服务器发送给浏览器,告诉浏览器请求报文接收完毕。
    • 服务器发送给浏览器,告诉浏览器发送响应报文完毕。
    • 浏览器发功给服务器,告诉服务器响应报文接收完毕。
  • 浏览器断开链接,服务器断开连接。

http1.0/http1.1/2.0的区别

  • http1.1 相对于 1.0 引入了更多的缓存策略:
    • 1.0 只能通过 expires 和 pragma 来控制缓存的事件和禁止缓存。
    • 1.1 引入了 Cache-Control 来实现缓存:cache /kæʃ/
      • max-age:对应 expires。
      • no-cache:对应 pragma。
  • 带宽优化及网络连接的使用。
  • 错误处理的通知:
    • http1.1 新增了 49 种新的状态处理。
    • 比如:
      • 409,表示请求的资源与资源的当前状态发生冲突。
      • 410:服务器上的某个资源被与永久删除。
  • Host 头处理:
    • HTTP1.1 的请求消息和响应消息都支持 host 域。
    • HTTP host 头 host 可以是域名,也可以是IP,也可以跟端口号。
  • 长链接:
    • 1.0 支持__长链接__和请求的__流水线处理__,在一个 TCP 连接上可以传送多个 http 请求和响应,减少了建立和关闭连接的消耗和延迟,在 1.1 中默认开启 Connection: keep-alive。

http 和 https 的区别

  • https 协议需要申请 CA 证书。

  • https 传输的内容是加密的。

  • 用的是完全不同的连接方式,端口号也不一样。

    http: 80/8080

    https: 443/tcp

  • https 可以有效的防止运营商的劫持。

    劫持一般分为三类:

    1. DNS 解析劫持:DNS 劫持也可以理解为用户的请求去往了错误的 DNS 服务器进行查询解析,返回来的目的主机 IP 自然不是我们想要达到的资源服务器主机,这往往发生在用户请求的第一步。
    2. 域名 302 劫持:访问的资源暂时性转移,得到新的资源位置,然后重新访问获取资源。
    3. NATip 劫持。

CA 和 CA 证书的区别:

CA: CA 是 Certificate Authority 的缩写,也叫“证书授权中心”。它是负责管理和签发证书的第三方机构,作用是检查证书持有者身份的合法性,并签发证书,以防证书被伪造或篡改。

CA 证书:CA 证书就是 CA 颁发的证书。 CA 证书也就我们常说的数字证书,包含证书拥有者的身份信息,CA 机构的签名,公钥和私钥。身份信息用于证明证书持有者的身份;CA 签名用于保证身份的真实性;公钥和私钥用于通信过程中加解密,从而保证通讯信息的安全性。

http 2.0/1.x 的新特性

  1. 新的二进制格式,解析模式从原本的文本解析,变更为二进制解析。

  2. 多路复用,一个请求可以请求多个资源。

  3. header 压缩,通讯双方都缓存一份 header,后续传输即可省略该部分。

  4. 服务器推送。

7. 熟练使用 npm、yarn 等包管理工具和 git 版本管理工具

8. 熟悉 json-server/express 服务器搭建、postman 接口测试等工具

json-server

Json-server:相当于一个小型的服务器。

express:

// 导入express
const express require('express')
// 创建app
const app = express()
// 路由设置
app.get('/user',(request,response)=>{// 获取传入的数据console.log(request.query)console.log(request.params)// 返回数据response.send()
})
// 分配端口
app.listen(500,(error)=>{console.log('开启成功')
})

9. 熟练使用 vue 开发项目,使用 vuex 实现多组件数据共享;使用vue-router 实现单页面应用

vuex

  • vuex 是专为 vue 开发的状态管理工具。
  • vuex 的使用场景:
    • 多个组件依赖同一个状态。
    • 多个组件的行为需要变更同一个状态时。
  • vuex 有五大管理模块:
    • state:
      • 数据类型是对象。
      • 共享的状态数据,里面的数据是响应式的。
    • getters:
      • 数据类型是函数。
      • 根据 state 中的数据来生成新的数据。
    • actions:
      • 数据类型是函数。
      • 进行一些异步操作,一般用来发送 ajax 等。
    • mutations:
      • 数据类型是函数。
      • 直接修改 state 中的数据,规范要求必须是同步函数。
    • modules:
      • 数据类型是对象。
      • 用来分割 store,实现 vuex 的多模块编程,这样能够使得更具有扩展性。
      • 单模块的问题:
        • 如果管理的状态数据过多,actions 和 mutations 就会过于臃肿,不便于维护。
        • 如果添加新的状态数据,需要修改当前的文件,不断的向已有数据进行添加。
  • 流程:
  • vuex 面试题
    1. vuex 中的 mutations 可以执行异步操作吗?
      • 可以,但是不符合规范。
      • 调试工具只会记录触发的 mutations,如果出现异步函数,调试工具将可能无法正常跟踪 state 的变化,导致调试工具失效。
      • 扩展: 工具如何记录数据变化? ==> 每次 mutation 函数执行完后,立即记录当前的数据 ==> 在mutation 中同步更新 state,才能被记录到,也就是工具只会记录每次 mutations 触发之后同步更新的 state 数据。
    2. vuex 中的状态数据的响应式原理:
      • 创建了一个 vm 实例对象。
      • state 中的数据都是 data 数据(响应式数据)。
      • 组件中读取的数据本质上是 data 中的数据。
      • 一旦更新了 state 中的数据,就会更新使用到 state 数据的视图。
    3. vuex 更新数据丢失的问题:
      • 每一次数据更新都会同步到 sessionStorage 中,也就是在 mutations 中每一次更新的时候都会将数据更新到 sessionStorage 中,然后在初始化的时候再从 sessionStorage 中获取数据。
      • 可以通过beforeunload事件,在页面刷新之前,将 vuex 中的数据保存在 sessionStorage 中,然后在初始化的时候从 sessionStorage 中获取 vuex 中的数据。

vue-router

  • 使用 vue+vue-router 创建单页面十分简单,vue-router 提供的功能是将组件映射到路由,然后渲染出来,所以vue-router 需要满足两个条件:

    • 记录当前页面的状态。
    • 可以使用浏览器的前进和后退的功能(也就是 BOM 的 history 功能)。
  • 而 vue-router 为了满足以上两个功能需要满足以下三个条件:

    • 改变 url 且不让浏览器向服务器发送请求。
    • 监测 url 的改变。
    • 截取 url 解析出需要的信息来匹配路由规则。
  • hash 值的特点

    • hash 值表示的是地址栏中的#号(也被称为锚点),hash虽然会出现在 url 中,但是不会被包含在 http 请求中,因此 hash 值的改变不会重新加载页面,并且 hash 值会触发 hashchange 事件,浏览器的前进后退也能对其进行控制。
    • 特点:
      • 兼容低版本的浏览器,vue 默认使用的就是 hash 模式。
      • 只有 # 之前的内容才会包含在请求中被发送到后端,也就是说就算后端中没有对全路由进行覆盖,也不会产生 404。
      • 会覆盖定位锚点的功能。
      • 不太美观,后面传递复杂的数据的话可能会产生问题。
  • history 的特点

    • 利用了 H5 的新特性:pushState()replaceState()两个 api,通过这两个 api 完成 url 的跳转是不会重新加载页面的。
    • history 提供了类似于 hashchange 事件的 popstate 事件,不同的通过 pushState 和 replaceState 和 a 标签不会触发 popstate 事件,可以拦截pushState/replaceState的调用<a>标签的点击事件来检测 URL 变化。
    • 特点:
      • 兼容性比较差,由于 history API 低浏览器不支持,所以兼容性比较差。
      • pushState() 设置的新 URL 可以是与当前 URL 同源的任意 URL;而 hash 只可修改 # 后面的部分,因此只能设置与当前 URL 同文档的 URL。
      • pushState 就算设置的新 url 与当前的一致,也会添加到历史栈中,而 hash 只有新值与旧值不一样才会被添加到记录栈中。
      • pushState 可以通过 stateObject 参数可以添加任意类型的数据到记录中,而 hash 只能添加字符串到记录中。
      • 在手动输入尤其在用户手动输入 URL 后回车,或者刷新(重启)浏览器的时候。hash 由于只会将 # 之前的 url 发送到服务器,即使没有实现全路由覆盖,也不会报404错误。
      • 而 history 模式下,前端的 url 会完整的被发送到后端,如果后端没有配置相应的路由,就会报404错误,所以需要增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。”

vue-router 原理

  • new Router 的原理:
    • new Router 传入的配置对象,配置对象有 model 和 routes 两个属性,model 是路由的模式。routes 是路由配置数组,将这个 routes 数组进行数据类型优化,遍历原来的 routes 数组,变为一个对象的形式,key是路由地址,value 是对应的组件。
    • 然后将整个 router 实例添加为 Vue 的原型对象上的$ruoter属性,添加一个$route属性在 Vue 的原型对象上。
    • 并且添加 path 和 push 方法在$route中:
      • path 获取的就是 pathname 端口号之后的路由路径,并且将 path 添加为响应式,当他变化,router-view 中也会变为相应的组件。
      • push 方法就是 pushState() 的实现。
  • router-view 的原理
    • router-view 是一个函数式组件。
    • 声明当前组件是一个 router-view。
    • 通过 depth 变量,记录当前是几级路由:
      • (通过 while 循环,从当前组件往上找,看遇到了几个 router-view,直至找到路由根组件为止)
    • 在 render 函数中:
      • 通过 path 获取到当前的路由地址。
      • 通过 router 上的 mapRoutes 对象,配合当前的路由地址,搜索出所有路径相似的路由,获取到对应的组件。
      • 将对应的组件通过 createElement 方法,生成虚拟 DOM。
  • router-link 的原理:
    • 默认生成一个 a 标签,当然可以指定标签。
    • 给当前的 a 标签绑定点击事件。
    • 禁止 a 标签的默认行为,防止它自动跳转。
    • 点击事件内部,调用编程式导航 push 方法。

history 404 问题

  • 这个问题主要存在刷新的时候会产生,因为 history 在刷新的时候会将整个地址栏发送到后端进行请求,后端没有相应对应的请求,所以会返回 404。
  • hash模式没有该问题,主要是因为 hash 值#后面不会进行发送请求。

vue-router 的路由导航钩子

1. 全局前置守卫

router.beforeEach((to,from,next)=>{})

2. 全局解析守卫

beforeResolve

3. 全局后置守卫

router.afterEach

4. 路由独享守卫

beforeEnter

5. 组件内的守卫

beforeRouteEnter
beforeRouteUpdate // 组件复用的时候调用
beforeRouteLeave // 导航离开该组件的时候调用

1. to: Route: 即将要进入的目标 路由对象

2. from: Route: 当前导航正要离开的路由

3. next: Function: 一定要调用该方法将控制权交给下一个守卫,执行效果依赖 next 方法的参数。

  • next():进入下一个守卫。如果全部守卫执行完了。则导航的状态就是 confirmed (确认的)。

  • next(false):中断当前的导航(把小明腿打断了)。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。

  • next(’/’) 或者 next({ path: ‘/’ }):跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航(小明被打断腿并且送回家了)。你可以向 next 传递任意位置对象,且允许设置诸如 replace: true、name: ‘home’ 之类的选项以及任何用在 router-link 的 to prop 或 router.push 中的选项。

  • next(error):(2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。

    永远不要使用两次 next,这会产生一些误会。

导航的全过程

导航被触发。

在准备离开的组件里调用 beforeRouteLeave 守卫。

调用全局的 beforeEach 守卫。

在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。(如果你的组件是重用的)

在路由配置里调用 beforeEnter。

解析即将抵达的组件。

在即将抵达的组件里调用 beforeRouteEnter。

调用全局的 beforeResolve 守卫 (2.5+)。

导航被确认。

调用全局的 afterEach 钩子。

触发 DOM 更新。

用创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数。

路由拦截

需求:项目中发现未登录也能进入主页,这样是不行的。需要在用户进入主页的时候,判断是否有登录。没有,返回登录页面,有,则可以浏览任意页面。

路由拦截:

  1. 加上meta。如:meta:{requireAuth:true}
  2. router.beforeEach函数加上判断即可。

博客地址

路由传参

  • query
  • parmas

10. 熟练使用第三方插件库:element-ui、ant-design、swiper、dayjs 等

11. 了解 Vue 响应式数据原理和双向数据绑定原理

Vue的响应式原理

  • 首先 vue 的响应式原理的核心是Object.defineProperty()这个 api。

  • 这个 api 可以设置一些额外的隐藏属性:

    • value:这个属性的属性值。
    • writable:这个属性是否可写,一般默认值为 true。
    • enumerable:这个定时属性是否可被枚举。
    • configurable:是否可以被重新设置。
    • get:默认为 undefined,当然 get/set 不能和 value 和 writable 共存。
    • set:默认为 undefined。
  • vue 的响应式原理主要包括三个部分,一个就是数据代理,数据劫持,模板解析。

  • 数据的代理

    • 将 data 数据通过 Objec.defineProperty 代理到 vm 实例上,然后为其添加 get/set 方法。
    • 每次通过实例访问 data 数据的时候,会触发代理属性的 get 方法,实际上是去操作的是 data 中的属性。
    • 每次通过实例修改 data 数据的时候,会触发代理属性的 get 方法,实际上是去更新的是 data 中的属性。
  • 数据劫持

    • 对象的劫持:
      • 数据劫持中,主要是通过 observer 来进行,第一次将 data 整个对象传入 observer 函数中。
      • 首先 observer 会判断传入的参数是否是一个对象,如果不是则会直接返回。
      • 会遍历每一个 data 对象中的 key 属性。
      • 每一个 key 属性都会调用 defineReactive 这个方法,这个方法会将 key 的 value 值和新创建出来的 dep对西那个使用闭包的方式保存下来,这个 dep 会在模版解析的时候使用上。
      • 然后再次隐式调用 observer 实现深度劫持。
      • 调用 defineProperty 给重写 data 中的每一个属性,并添加上 get/set 方法。
      • 在 getter 中收集依赖,在 setter 中触发依赖。
      • set 方法会调用 dep.depend() 方法,同时返回 val。
      • set 会再次调用 observer 进行劫持,并且调用 notify 通知视图更新。
    • 数组的响应式:
      • 会改写,push,pop,shift,unshift,splice,sort,reserver 这七个数组方法。
  • 模板解析:

    • 将 el 中的所有子节点都添加到 fragment 中。
    • 遍历 fragment 中的所有的子节点。
    • 判断子节点的类型 nodeType:
      • 如果是元素节点 nodeType === 1。
      • 获取所有的属性节点,判断属性是否以 v- 开头
        • 如果是 v-on 则是事件指令则绑定原生事件。
        • 如果是普通指令属性:
          • 根据普通指令属性的类型调用相应的 update 方法更新界面。
          • 生成一个 watcher,缓存 node 和 update 方法,并且建立 watcher 和 dep 之间的关系。
      • 如果是文本节点 nodeType === 3 并且有插值语法。
      • 直接调用 textUpdate 方法更新界面。
      • 也会生成一个 watcher。
    • 然后将 fragment 插入到 el 中生效。
  • 当更新 data 的时候,会触发代理属性的 set 方法。

  • 然后接着会触发 data 中对应的 set 方法,更新闭包中的 val 值,然后再调用 observer 函数,紧接着触发dep.notify 通知所有的 watcher 进行页面的更新。

双向数据绑定原理

  • vue 是通过 v-model 来实现双向数据绑定的。
  • 将指定变量的值通过强制绑定的方式绑定给 input 的 value。
  • 然后给 input 绑定上 input 事件,然后当 input 事件触发的时候将指定变量的值进行修改。

12. 熟练掌握 vue 组件通信的多种方案:Vuex,props,sync 全局事件总线等以及 vue 的声明周期钩子函数

vue组件之间通讯

  1. vuex:

    • 任意组件之间的通信。
    • 统一管理多个组件之间的共享状态数据。
  2. props:

    • 可以实现父子间的组件通讯。
    • 通过在父组件中的子组件标签中以标签属性的方式传入子组件。
    • 将更新父组件的函数传入子组件,在子组件中调用函数并且传入实参,即可实现子组件传递给父组件。
  3. 自定义事件:

    • 可以实现子组件向父组件通信。

    • 在父组件中给通过标签属性的方法给子组件绑定事件。

    • 然后在子组件中通过组件实例的$emit来分发指令,然后调用事件的回调函数并且传递实惨实现子传父。

  4. 全局事件总线:

    • 可以实现任意组件之间的通信。

    • 全局事件总线是在自定义事件基础之上,通过在 Vue 的原型对象上添加 $bus 为 vm 实例对象。

    • 组件实例的隐式原型对象是 vue 实录对象,所以组件实例也可以访问到$bus这个对象,所以在任意组件都可以调用$on, $emit, $once, $off这几个属性。

    • 在组件中可以直接通过this.$bus.on绑定事件。

    • 可以通过this.$bus.$emit来分发事件。

  5. v-model

    • 可以实现父子组件通信。
    • 相当于通过 props 传递了一个 value 属性。
    • 绑定了一个 input 自定义指令用来跟新父组件中的数据。
  6. .sync

    • 通过 props 传递一个属性。
    • 再通过自定义事件传入update:props属性的自定义事件。
  7. $attrs/$listeners

    • $attrs 可以获取到不通过 props 接受的 props 参数。
    • $listeners 可以获取到绑定给该组件的自定义。
  8. $refs/$parent/$children

    • 可以直接获取到父组件的实例或者是子组件的实例
  9. provide/inject

    • 祖孙之间的组件通信。
    • 通过 provide 定义数据。
    • 然后 inject 直接接受数据。
    • 注意:provide 传递的不是响应式数据,祖先组件修改,孙子组件不会修改。
  10. 插槽

    • 向子组件传递标签内容
    • 默认插槽
      • v-slot
      • 子:<slot/>
    • 命名插槽
      • 通过 template 标签,添加v-slot:slotName标签属性指定名字。
    • 作用域插槽

13. 熟练解决移动端适配:viewport,rem,vw 等

适配方案

  • 在终端不设置布局适口的时候,布局视口的宽度是980px,此时页面的内容非常小,如果方法显示,就会比较小,并且会出现横向的滚动条,为了让页面的宽度为视窗的宽度,页面没有横向滚动条,需要进行移动端适配。

  • 先通过viewport将布局视口的宽度设置为设备独立像素的宽度。

  • 适配方案

    1. rem:

      • 设置rem,编写样式时统一使用 rem 为单位,在不同设备上动态调整根字体大小。
      • 方法一:通过js动态获取到设备的设备独立像素(布局视口)(DP),然后将跟标签的font-size设置为dp/设计稿宽度*100 + ‘px’,然后在使用的时候,直接将样式设置为:设计稿尺寸/100rem
      • 方法二:通过js动态获取到设备独立像素(布局视口),然后将跟标签的font-size设置为:dp/10+'px',然后将样式直接设置为:设计稿尺寸/设计稿总宽度*10 rem
      • 工具:使用postcss-pxtorem插件来进行适配。
      • 优缺点:
        • 优点:能够实现在不同大小的屏幕上显示的比例一致。
        • 在大屏设备上会造成显示的内容超大。
        • 解决:
          • 限制rem的最大值。
          • 通过媒体查询来限制内容的最大宽度。
    2. vm适配:

      • vwvh是两个相对单位:
        • 1vw = 等于布局视口宽度的1%
        • 1vh = 等于布局视口高度的1%
      • 在设置样式的时候,计算出样式比例然后直接添加上。
      • 工具:使用postcss-px-to-viewport来进行适配。
      • 优点:vw、vh布局能良好的实现在不同尺寸的屏幕横向填满屏幕。
      • 缺点:大屏幕显示过大,兼容性问题。
    3. 百分比:

      • 可以使用百分比来进行布局,得到在不同的屏幕尺寸下都比例一致,但是因为百分比相对的是父级,所以当嵌套过深的时候会发生问题,或者是需要固定的尺寸时会产生问题。
    4. 媒体查询

      • 通过媒体查询,可以针对不同的屏幕进行单独设置,但是针对所有的屏幕尺寸做适配显然是不合理的,但是可以用来处理极端情况(例如 IPad 大屏设备)或做简单的适配(隐藏元素或改变元素位置)。
    5. px 为主,搭配 vw/vh、媒体查询与 flex 进行布局:

      • 我们从页面编写的角度出发,页面中更多的是文本和布局,关于文本,我们应该使用 px 作为单位,来实现在大屏设备显示更多的内容,而不是更大的文本;关于布局,我们可以使用 flex 实现弹性布局,当实现特定宽高元素时,可以适当的使用 vw/vh,当特定的值使用 vw/vh 计算复杂或存在误差时,也可以使用 rem。
  • 一像素问题

    • 通过媒体查询,当设备像素比为2的时候,将边框写为0.5px,在设备像素比为3的时候,将边框设置为0.33px
    • 直接设置viewport
      • 使用window.deivcePixelRatio获取到设备的像素比。
      • 然后进行判断(也就是将布局适口的宽度设置为和设备物理像素一致的宽度)
        • 当设备像素比为1的时候,inital-scale = 1
        • 当设备像素比为2的时候,inital-scale = 0.5
        • 当设备像素比为3的时候,inital-sclae = 0.33
      • 使用document.docuemntElement.clientWidth获取到布局视口,然后进行rem适配。
      • 然后边框在进行样式设置的时候使用px不使用rem,就保证了每一个边框都是1px

rem 适配

viewport 适配

百分比适配

flex 在某种场景下也能适配

14. 熟悉小程序开发,熟悉小程序的 WXML、WXSS、JS 等开发规范

小程序的特点

  • 体积小,压缩包的体积不能大于 2M。
  • 没有 DOM 对象。
  • 基于组件化开发。
  • 小程序环境不同于浏览器环境:
    • 浏览器的全局对象是 window。
    • 小程序的全局对象是 wx。
    • 小程序环境中没有 window 对象。

小程序适配

  • 小程序适配单位是 rpx 响应式单位。
  • 小程序中规定的所有机型中页面宽度都是 750px。
  • 底层已经做了 viewport 适配。

小程序相关语法

  1. 数据绑定:
    • 单项数据流:model --> view。
    • 修改状态数据:this.setDate(),同步修改。
    • 页面中的数据均来自于 data。
  2. 事件绑定:
    • 事件类型:冒泡事件 || 非冒泡事件
    • 绑定事件:bind+事件名称|catch+事件名
  3. 路由跳转:
    • wx.navigateTo() || wx.redirectTo()
  4. 本地存储:
    • 语法:
      • wx.setStorage()||wx.setStorageSync():异步设置 || 同步设置
      • wx.getStorage()|| wx.getStorageSync():异步获取 || 同步设置
    • 储存
      • 单个 key 上限是 1MB。
      • 整体上限是 10MB。
  5. 全局传参:
    • app.js 中可定义全局参数 globalData。

微信小程序登录流程

  • wx.getUserProfile 实现用户授权:
    • 注意:
      • 必须绑定在tap事件中的回调才能生效。
      • 调用一次该api,就会产生一个弹窗。
  • wx.getUserInfo 二次免登录授权:必须在授权之后才能使用。

小程序获取用户唯一标识(openId)

  1. 客户端先通过 wx.login(获取 code)。
  2. wx.request() 发送 code 给服务器。
  3. 服务器端发送请求携带参数(code, appSecret(开发密钥), appId)给微信服务器获取 openId。
  4. 微信返回 openId 给服务器后,服务器进行加密再返回给前端。
  5. 前端进行本地储存,下次发送请求时携带参数。

小程序支付流程

  1. 用户在小程序客服端下单(包含用户及商品信息)。
  2. 小程序客户端发送下单支付请求给商家服务器。
  3. 商家服务器同微信服务器对接获取唯一标识 openID。
  4. 商家服务器根据 openId 生成商户订单(包含商户信息)。
  5. 商家服务器发送请求调用统一下单 API 获取预支付订单信息。
  6. 商家对预支付信息签名加密后返回给小程序客户端。
  7. 用户确认支付(鉴权调起支付)。
  8. 微信服务器返回支付结果给小程序客户端。
  9. 微信服务器推送支付结果给商家服务器端。

面试问题

  • Iphone6 的 dpr 为多少?Iphone6Plus 比 Iphone6 显示图像清晰吗?

    视网膜屏幕是分辨率超过人眼识别极限的高分辨率屏幕,Iphone4 的 dpr = 2; 人类肉眼分辨的极限。

  • 生命周期函数实际测试和官网描述有差。

  • wx.setStorage(),单个 key 允许存储的最大数据长度为 1MB,所有数据存储上限为 10MB。

  • 性能优化:一个页面一次只有一个 video 标签,其余的使用 image 代替。

  • 请求相关:

    1. 小程序为了安全起见只支持 Https 请求。

    2. wx.request 最大并发限制 10 个(浏览器最大并发数是6个)。

  • 如何使用组件:

    1. 先创建组件,在对应的 json 文件下设置 component: true。

    2. 到使用组件页面的 json 文件中,注册组件填写相应的路径。

  • 使用 npm 包:下载后,勾选使用 npm 模块,再构建 npm,会将 node_modules 中的包打包到 miniprogram_npm中。

  • 分包相关:

    分包后可解决 2M 限制,并且能分包加载内容,提高性能。

    分包后单个包的体积不能大于 2M,所有包的体积不能大于 16M。

    1. 常规分包:

      • 加载小程序的时候先加载主包,当需要访问分包的页面时候才加载分包内容。

      • 分包的页面可以访问主包的文件,数据,图片等资源。

    2. 独立分包:

      • 独立分包可单独访问分包的内容,不需要下载主包。

      • 独立分包不能依赖主包或者其他包的内容。

      • 通常某些页面和当前小程序的其他页面关联不大的时候可进行独立分包,如:临时加的广告页 || 活动页。

    3. 分包预下载:

      • 在加载当前包的时候可以设置预下载其他的包。

      • 缩短用户等待时间,提高用户体验。

15. 熟练使用 commonjs 和 es6 模块化规范进行开发

16. 对页面进行懒加载、限制前台页面不必要请求、节流防抖等优化方案

17. 了解 TypeScript 语法,接口,类,泛型等

接口

接口是对象的状态(属性)和行为(方法)的抽象(描述)。

类类型:类的类型,通过接口来实现。

泛型

在定义函数,接口或者类的时候,不预先指定具体的类型,而在使用的时候再指定具体的类型。

18. 了解Vue3新特性(setup,ref,reactive,新组件等)

render 函数和 template 有什么区别

  • 相同点:都叫类编译器
  • render 是 template 的下一步
    • render(h)=>h 相当于creareElement

19. 了解 webpack 配置基本设置,掌握 tree shaking、代码分割等优化方案

20. 补充

免登录

  1. 第一次登录的时候,前端调后端的登陆接口,发送用户名和密码。

  2. 后端收到请求,验证用户名和密码,验证成功,就给前端返回一个 token。

  3. 前端拿到token,将token存储到localStoragevuex中,并跳转路由页面。

  4. 前端每次跳转路由,定义一个全局前置守卫,判断 localStorage 中有无 token ,没有就跳转到登录页面,有则跳转到对应路由页面。

  5. 每次调后端接口,都要在请求头中加 token。

  6. 后端判断请求头中有无 token,有 token,就拿到 token 并验证 token,验证成功就返回数据,验证失败(例如:token 过期)就返回 401,请求头中没有 token 也返回 401。

  7. 如果前端拿到状态码为 401,就清除 token 信息并跳转到登录页面。

  8. 调取登录接口成功,会在回调函数中将 token 存储到 localStorage 和 vuex 中。

自定义指令

bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。

  • 触发情况:一般只在内存中就触发了。

inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。

update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 。

componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。

unbind:只调用一次,指令与元素解绑时调用。

简化写法同时触发了bind和update钩子函数,也就是直接写函数的情况下

el:绑定当前元素的dom

binding:是一个对象,内部保存很多关于指令的属性

  • value:指令绑定的值
  • expression:原样输出
  • oldvalue:仅在update和componentUpdate中生效

vnode

oldVnode

Vue的性能优化

  1. 对象层级不要过深,否则性能就会差。

  2. 不需要响应式的数据不要放到 data 中(可以用 Object.freeze() 冻结数据)。

  3. v-if 和 v-show 区分使用场景。

  4. computed 和 watch 区分使用场景。

  5. v-for 遍历必须加 key,key 最好是 id 值,且避免同时使用 v-if。

  6. 大数据列表和表格性能优化-虚拟列表/虚拟表格。

  7. 防止内部泄漏,组件销毁后把全局变量和事件销毁。

  8. 图片懒加载。

  9. 路由懒加载。

  10. 第三方插件的按需引入。

  11. 适当采用 keep-alive 缓存组件。

  12. 防抖、节流运用。

  13. 服务端渲染 SSR or 预渲染。

深拷贝

1. 自定义深拷贝

// 首先定义一个数据类型的检测
function checkType(arg){return Object.prototype.toString.call(arg).slice(8,-1).toLowerCase()
}
// 定义一个深拷贝的函数
function deepClone(obj){// 首先判断是否是一个对象if(checkType(obj) === 'object'){// 新建一个对象var newObj = {}}else if(Array.isArray(obj)){// 新建一个数组var newObj = []       }else{// 如果是其他的数据类型,则直接返回return obj}// 进行拷贝for(let key in obj){newObj[key] = deepClone(obj[key])}// 返回对象return newObj
}

2. 利用json串

JSON.parse(JSON.stringify(obj))
  • 缺点:方法/函数会丢失

取消请求

在 axios 中,可以通过 axios 内部提供的 cancelToken 来取消请求。

实现:

  • 在当前页面发送请求的时候,在 axios 发送请求的时候,在配置项 cancelToken 中:new axios.cancelToken(©=>{}),回调函数中会自动传入一个当前请求的标识C,以数组的形式将当前请求保存到 vuex 中。
  • 然后在跳转页面的时候,通过全局前置路由来判断是否跳转了路由,如果发生了跳转页面,则遍历数组中的请求,直接进行C()调用即可取消请求。

Vue打包优化

权限控制

总:

  • 首先权限控制主要就是解决两个问题

    • 获取到用户有哪些权限:在用户登录的时候,会返回用户的权限路由。

    • 让用户不能访问没有权限的页面:

      让用户的菜单页面只能显示用户权限路由中的页面。

      这里一般会有两种方法(主要用第二种):

      1. 注册所有的路由,然后在显示的时候只显示用户权限路由相关的页面,为了防止用户自己在地址栏输入地址进入没有权限的路由,在全局前置守卫中进行判断。
      2. 另外一种方法是:刚开始只定义一个常量路由,然后通过 addRoutes 动态注册用户的权限路由。

思路:

  • 在定义路由的时候,会首先创建一个常量路由,一般会包含登录/注册/首页/404,还有一个异步路由(包含所有的权限路由)

    • 登录成功,在后台返回的数据中,会包含该用户的路由权限,路由权限是一个数组,数组中每一项都是该用户拥有的路由权限的名称。
    • 然后通过权限路由名称过滤异步路由。
  • 首先判断异步路由中的一级路由是否包含在权限路由中,如果包含在权限路由中:

    • 再判断该路由是否拥有子路由,如果没有自路由则直接将该路由返回:
      • 如果有子路由,在对子路由进行递归过滤。
      • 过滤完,如果该路由没有权限子路由,则该路由也将会被过滤掉。
  • 过滤之后得到用户自己的权限路由表。

  • 然后将常量路由表和过滤后的用户路由进行合并并且保存在 state.routes 中,有什么用?,用于遍历生成菜单,并且判断是否有 hidden 为 true,有 hidden 为 true 则不会被显示出来。

    • 用于遍历生成路由菜单,判断是否拥有 child 属性或者只有一个 child 属性。
    • el-menu:最外面的菜单容器。
    • el-menu-item:生成一级菜单。
    • el-submenu:生成二级菜单。
  • 然后调用 router.addRoutes 将权限路由添加到路由器。

按钮权限值

1. 方法一:自定义指令

定义一个全局自定义指令 permission,在 inserted 中判断当前呢只定义指令的 value 值是否在用户的按钮权限中,如果在,则将该按钮移除,然后在按钮中添加该自定义指令,并且传入该按钮的权限值。

2. 方法二:v-if

定义一个方法,该方法定义一个形参,使用数组的 includes 方法判断传入该函数的按钮是否在用户的按钮权限中,将该函数添加为 Vue 的原型上的方法,然后在按钮是使用v-if判断该函数的返回值。

webpack 优化

1. 配置 webpack

  1. 初始化webpack

    npm add init -y

  2. 下载依赖,开发依赖

    yarn add webpack@4 webpack-cli@3 -D

  3. 配置文件

    webpack.config.js

  4. 五大核心概念

    1. entry:入口文件
    2. output:出口文件
    3. lodaer:加载器
    4. plugins:插件
    5. mode:

2. 优化

数摇
  • 将环境设置为开发模式,然后使用 es6 模块化导入模块,就能减少打包的代码体积。
代码分割
  • 问题:如果多个文件共同依赖于一个文件,该文件内容会被两个同时打包,最终导致项目 js 文件体积过大,影响首次渲染速度。
  • 实现:
    • 多入口配置:
      • 在 webpack.config.js 中,配置 optimization.splitChunk.chunks = all。
      • 问题,miniSize 默认值为:30000(30KB),自定义 miniSize。
    • 单入口配置:
      • 在 webpack 中使用 import 函数引入的文件会被单独切割为一个 js 文件,等浏览器执行到 import 函数。的时候才会发送请求获取当前js文件。
      • 使用场景:组件懒加载,可以减小 index.js 的文件大小,提高首屏渲染速度。
      • 懒加载的使用:相对于没有使用懒加载之前,懒加载之后,后续页面的渲染速度会变慢。
缓存配合:后端如果使用强缓存

缓存的时候使用 contentHash。

强缓存:通过 cache-control: maxAge:指定缓存的时间。

协商缓存:每一次都会发送 Etag,last-modify 发送给服务器,如果请求对比的:

  • hash 模式,每一次打包编译,所有文件都会被重新打包。
  • chunkHash:每一个入口重新打包编译都会创建一个唯一值。
  • contentHash:每一个文件重新打包会创建一个唯一值。
PWA(Progressive Web App):
  • 离线缓存。
  • 使用 workbox-webpack-plugin 进行离线缓存。
  • 在入口文件中注册 Service Worker。
  • 然后就会把整个网页缓存到 cache-storage 中。

PWA 定义:是一种理念,使用多种技术来增强web app的功能,可以让网站的体验变得更好,能够模拟一些原生功能,比如通知推送。

多进程打包
  • webpack 默认单进程打包。
  • 使用 thread-loader 配置多进程打包。
  • 多耗费 600ms。
  • 进程与进程之间通信也会耗费时间。

项目相关

1. axios 二次封装

  • 原生的 axios 请求会存在一下问题

    1. 请求地址每次都需要重新完整的输入。
    2. 每个公共的参数也需要手动输入。
    3. 不能直接得到返回的数据,需要 res.data 才能拿到需要的数据。
    4. 响应返回的状态码只能代表响应成功,不能代表功能成功。
    5. 错误提示不够友好。
    6. 没有进度条显示:NProgress.start/NProgress.end
  • 解决:进行 axios 的二次封装

    1. 定义公共的请求路径

      const request = axios.create({
      // 公共的请求路径baseUrl:"",
      // 定义超时时间timeout:10000, // 默认为60000ms
      })
      
    2. 定义请求的公共参数:在请求拦截器中进行发送。

      在请求拦截器中定义响应头的公共参数。

      1. 发送用户的唯一 id。
      2. 发送用户的 token。
      // 定义响应拦截器
      request.interceptors.request.use(// 成功的回调函数(config)=>{// 定义唯一id 需要使用 uuid生成唯一id config.headers.userTempId = "xxx";config.headers.token = "xxx";}// 失败的回调函数一般不需要指定
      )
      
    3. 直接返回数据:

      1. 定义响应拦截器。
      2. 只有状态码为 200 才能算是成功。
      3. 成功之后直接返回响应的数据。
      4. 定义更好的错误提示:
        1. 响应失败的错误提示码在 error.response.status 中。
        2. 请求失败的错误提示码在 error.message 中,可以利用字符串的 includes 进行判断是否存在。
      request.interceptors.response.use(// 成功响应的回调函数response=>{// 判断后台返回的数据是否是200if(response.data.code === 200){// 返回成功数据return response.data.data}// 返回失败的数据return Promise.reject(response.data.message)},error=>{// 判断是否是响应失败,响应失败在response中,如果没有数据,说明不是响应失败if(error.response){// 失败的结果,定义一个错误状态码对应的错误情况return Promise.reject(errorObj[error.response.status]||"未知错误")}// 如果不是响应失败,可能是请求失败,请求失败的结果会在error.message中,数据类型是字符串if(error.message.includes("newwork")){return Promise.reject("网络错误")}return Promise.reject("未知错误")}
      )
      

2. 路由传参数问题

query 和 params 传参数
  1. 都可以通过在路由中传递参数。

  2. query 传参:

    1. 问号后面的可以被称为 query 参数。
    2. query参数可以直接在路由的后面进行传递参数。
    3. 编程式导航也可以传递。
    4. 声明式导航也可以。
    5. 即可以使用 name 的方式,也可以使用 path 的方式进行传递。
  3. params 传参:

    1. 作为路由的一部分的参数叫做 params 参数。
    2. 原则上 params 参数需要在路由指定占位符:
      1. 占位符:…/:id:表示必须传入一个 id 的 params 参数。
      2. 占位符:…/:id?:表示传入的 params 参数 id 是可选的。
    3. 编程式导航可以指定。
    4. 声明式导航也可以。
    5. 在以对象的形式传递参数的时候,必须只能使用 name 的方式,而不能使用 path。
  4. 也可以传递 props 参数:

    需要在路由中定义函数,并且返回一个对象,该对象就可以被添加到 props 中:

    props($route)=>({...$route.query,...$route.params})
    
  5. 问题:

    1. 当如果传递 params 参数的时候,如果参数是一个""的时候,回跳转到/,

      1. 解决:不指定该参数,或者指定一个 undefined。
    2. 当通过编程式导航跳转到当前路由(参数不变的情况下),会抛出 NavigationDuplicated 的警告错误:

      1. 问题:vue-router3.1.0 之后,push() 引入了 promise 的语法,如果没有通过参数指定回调函数就返回一个 promise 来指定成功/失败的回调,并且内部会判断如果要跳转的路由路径与当前路径一样,就会抛出一个失败的 promise。

      2. 解决:

        1. 在 push 的时候,传入回调函数来进行处理:第一个为成功的回调函数,第二个为失败的回调函数。

        2. 在 push 的时候使用 catch 来处理错误。

        3. 高级方法:重写 push/replace 方法,在定义 vue-router 的地方进行重写:

          // 导入vue-router
          import VueRouter from "vue-router"
          // 缓存push函数
          const originPush = VueRouter.prototype.push
          // 重写push方式
          VueRouter.protype.push = function(location,onComplete,onAbort){// 如果传递了回调if(onComplete || onAbort){// 调用push方法originPush.call(this,location,onComplete,onAbort)}else{return originPush.call(this,location).catch(()=>{console.log("error callback")})}
          }
          

3. lodash 按需引入

防抖节流的使用:

  • 防抖:如果同一个事件在指定间隔的时间内多次触发,则只执行最后一次。
  • 节流:如果同一个事件在一段时间内多次触发,指定时间触发的间隔。

4. 使用 dataset 进行数据的传递

  • dataset 是 H5 新增的自定义属性方式。
  • 在标签上使用 data- 作为前缀。
  • 在 js 中通过 dataset 获取到自定义属性。

4. swiper

  • swiper 对象,必须在列表数据生成 dom 对象之后才能创建—>在 mounted 上进行创建。
  • 原则:就是依赖的数据以及 swiper 结构生成 dom 节点的时候创建:
    • 解决:
      • 在 swiper 的 html 结构中使用 v-if,当获取到数据的时候再返回 true。
      • 在 mounted 上创建。
      • 使用 watch+nextTick 进行创建。
      • 使用 watch+nextTick+deep 进行创建。
  • new Swiper 如果传入的是一个类选择器的话,多个 new Swiper 只会生成一个数组,每一个 Swiper 是数组中的一个对象,所以在进行处理的时候最好就是使用 refs。

5. 自定义分页器

  • 自定义分页器的时候,首先肯定需要接收一个 totals,pageSize,pageSizes,currentPage,pageCount:显示的按钮数量。
  • 思路:一般情况下,显示的按钮书否是奇数,为了对称:
    • 按钮显示的时候,会显示第一页,最后一页,中间的页数会以当前页作为中间对称显示。
    • 已知的肯定是当前页,需要根据当前页来动态的显示中间部分的第一个按钮和最后一个按钮。
    • 计算公式:start = currentPage - (pageCount-3)/2;end = start +(pageCount-3)。
    • 特殊情况:当start小于2的时候,必须强行指定为2,当 end 大于最大页面-1强制指定为最大页面-1。
    • 当总页面小于指定的页面的时候
      • 当页面大于 2 的时候
      • 页面等于2
      • 页面小于2

vue后台项目

  • 用户权限管理

  • 按钮权限管理

  • 实现element-ui的按需引入

  • 使用深度选择器修改element-ui的样式

  • 动态显示输入框自动获取焦点

  • el-table在获取该行的数据的时候,使用到插槽,

面试

面试补充

1. ES5 数组方法:

改变原数组:

push(), pop(), shift(), unshift(), reverse(), sort(), splice()

不改变原数组:

concat(), join(), slice(),map(), filter(), forEach(), some(), every(), reduce()

1. ES6 数组方法

  • arr.find:需要传入一个回调。

  • arr.findIndex:需要传入一个回调。

  • arr.fill: value,start,end。

  • arr.includes:方法返回一个布尔值,表示某个数组是否包含给定的值。

    该方法主要用来替代indexOf(),因为indexOf()全等运算,而NaNNaN也不相等。Array.flat: 拉平数组。

  • Array.from:将伪数组转换为真数组。

  • Array.of:用于将一组值转换为数组。返回新数组。

不改变原数组:
some、every 返回 true、false。
map、filter 返回一个新数组。
forEach 无返回值。

2. ES5 字符串方法

  • charAt(),根据传入的位置取得其所在的字符。
  • charCodeAt(),根据传入的位置取得其所在的字符编码(unicode码)。(不常用)
  • String.fromCharCode(),根据传入的 unicode 码,转换为相应的字符。返回转化后的字符。

  • concat(),将一或多个字符串拼接起来返回拼接得到的新字符串。

  • indexOf(searchValue[,offset]),从一个字符串中向后搜索给定的子字符串,然后返回子字符串的位置(如果没有找到该子字符串,则返回-1)。第二个参数可以指定从哪开始(默认从0位置开始查找)。(常用)

  • replace()方法,替换子字符串。(其他功能讲正则的时候说)将某个字符串置换成某个字符串。

  • slice(beginSlice[,endSlice]),提取一个字符串的一部分,返回一个新的字符串。beginSlice 从 0 开始,endSlice 可以省略,如果省略 endSlice 会一直提取到字符串末尾。(beginSlice 是开启的位置,endSlice 是结束的下标的----但结果不会包含结束的下标)—用的较多。(按下标取字符串)

  • valueOf(),返回对象的字符串、数值或布尔值表示。如果是包装类型返回包装类型的值,如果是对象则返回对象本身。

    该方法没有参数

    返回值:如果是包装对象,返回的是包装对象中的基本值;如果不是包装对象类型,返回的是对象本身。

    toString(),返回对象的字符串表示。

    该方法没有参数

    返回值:如果是包装对象,返回的是包装对象中的基本值转换为字符串;如果不是包装对象类型,根据对象类型的不同返回值也不同。

  • toLowerCase(),将字符串转换为小写。

  • toUpperCase(),将字符串转换为大写。

2. ES6 字符串方法

  • str.startWidth(): 判断开头有没有包含某个字符串。
  • str.endsWith(): 判断结尾有没有包含某个字符串。
  • str.includes(): 判断字符串是否包含某个字符串。
  • str.repeat(): 重复当前的字符串,可以规定次数。
  • str.trim(): 删除字符串两端的空白符。
  • trimStart() 去除首部的空格。
  • trimEnd() 去除尾部的空格。

3. ES6 对象方法:

  • Object.is(): 比较两个值是否相等

    Object.is('foo', 'foo')
    // true
    Object.is({}, {})
    // false
    
  • Object.assign(): 用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。

    const target = { a: 1 };const source1 = { b: 2 };
    const source2 = { c: 3 };Object.assign(target, source1, source2);
    target // {a:1, b:2, c:3}
    

    注意,如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。

自定义组件的步骤

  • 实现静态组件: 模板/样式写好。
  • 设计从外部接收的数据: props。
  • 设计内部的数据: data。
  • 设计基于 props 和 data 的计算属性数据: computed。
  • 根据 props 和 data 数据和 computed 进行动态显示。
  • 更新数据,更新界面,通知父组件(watch + 自定义事件)。

在项目中遇到过什么难点

  • 在搜索页面的时候,如果传入一个空的 params 参数会直接跳转到/
  • swiper 问题
  • push 到相同地址的问题 NavigationDuplicated 的问题。
  • 二级路由刷行reset失效的问题
    • 修改为绝对路径
    • 但是history模式下,以/开头的嵌套路径会被当作根路径,所以使用“./”引入文件,就会找不到文件了,因为文件本身就是在项目根目录下的,并不在嵌套路径这个目录下。
  • axios 二次封装
  • 当从搜索页跳转到详情页的时候,详情页的滚动条位置会和在搜索页的位置一样
    • scrollBehavior
  • 渲染多级别数据的时候会抛出错误:比如 a.b.c,三级数据
    • 方法:v-if
    • 进行初始化
    • 计算属性进行判断

浏览器,小程序和 node 中的 js 有什么区别

  • 浏览器中JavaScript的实现由以下三个部分组成:
    • 核心(ECMAScript)。
    • 文档对象模型(DOM)。
    • 浏览器对象模型(BOM)。
  • **NodeJS 中 JavaScript **的实现由以下三个部分组成:
    • 核心(ECMAScript)。
    • NPM:包管理系统。
    • Native: node 原生模块,做一些 js 做不了的事情,比如文件的操作,数据库等等等。
  • **微信小程序中 JavaScript **的实现由以下三个部分组成
    • 核心(ECMAScript)。
    • 小程序框架:
    • 小程序 API: app,wx 等。

苹果树面试

common.js 和 ES6 模块化语法的区别
答案参考

为什么需要用 ts 而不用 JS(ts的好处是什么)
扁平化数组转树形结构数组:

  1. 递归:

    • 计算量大
    • 不会改变原有数据
  2. 用对象方法:

    • 计算量小
    • 不使用深拷贝则会改变原始数据

    将扁平化的数组处理为树结构数据,我们可以利用对象来处理,对象的复制是浅拷贝,指向相同的内存地址。

博客地址

小鹅通面试

  • 一上来就问请介绍你觉得做的做好的项目

  • 跨域报错是怎么报错的

    答案参考

名竹科技

  • 设计模式需要了解
  • promise 用的什么设计模式:
    • 以前的异步回调是使用 回调函数,容易造成内存泄漏,并且代码不容易维护。
    • promise 的设计使用的链式调用,看起来容易维护,并且解决了内存泄露的问题。
    • 并且使用了 .catch 来捕捉错误,可以每一个 .then 都准备一个处理错误的函数。也可以统一用 .catch 来处理。
  • vue 生命周期的触发顺序

爱德博

  • map 手写。
  • vue 中哪些地方用到了发布订阅模式。

React

生命周期钩子函数

  • 挂载阶段(初始化阶段)
    • constructor
    • componentWillMount
    • render
    • componentDidMount
  • 更新阶段:父组件render的时候会触发
    • componentWillReceiveProps:接收props
    • shouldComponentUpdate:组件自身this.setState会触发,这个钩子返回true,则才回触发更新
    • componentWillUpdate:当触发forceUpdate的时候会触发这个钩子
    • render
    • componentDidUpdate
  • 卸载阶段
    • componentWillUnmount
  • 用的最多的就是componentDidMount和componentWillUnmount
  • 即将废弃:
    • componentWillMount
    • componentWillReceiveProps
    • componentWillUpdate
  • 新增的钩子
    • getDerivedStateFromProps
      • 必须是类组件的静态方法
      • 取代componentWillMount、componetnWillUpdate
      • 接收的参数
        • 第一个:props
        • 第二个:改变之后的state状态
      • 返回值:
        • 返回的是一个对象或者是null
        • 返回的对象中的内容会被添加到state中
    • getSnapshotBeforeUpdate
      • 在render()和componentDidUpdate之间进行操作
      • return的值会在componentDidUpdate中接收

React 路由

  • 路由组件

    • BrowserRouter:包住 Route 和 Link/NavLink,一般只需要包住整个项目。
    • Link:用于匹配路由。
    • NavLink:用于匹配路由。
    • Route:用于匹配路由组件。
      • 普通组件和路由组件的区别:
        • 路由组件的三大特性:
          • history:操作历史记录的方法。
          • location: pathname:路由地址,search:传递的查询字符串,state:编程式导航传入的第二个参数 state。
          • match:匹配信息,path,params。
    • Switch:匹配到一个 Route 便终止匹配。
    • Redirect: to,重定向。
  • 路由懒加载的话,需要 Suspense 来定义 loading:

    <Suspense fallback={<div>Loading...</div>}></Suspense

  • 路由传参数

    • 声明式导航:
      • NavLink to={path:,state} => 接受:location.state
      • NavLink to="/home/id" => Route配合:Route path="/home/:id" => 接受:match.params
      • NavLink to="/home?key1=val1&key2=val2" => 接受:location.search
    • 编程式导航

Redux

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.exyb.cn/news/show-35336.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

【Android 11】使用Android Studio调试系统应用五):编译Settings 模块、解决编译错误

文章目录 1. 篇头语2. 系列文章3. 关联Git4. 完善Settings的依赖4. 1 Android.bp回顾4.2 提取出所需androndx支持库4.2.1 依赖列表(android.bp)4.2.2 转换后的列表(build.gradle)4.2 提取出所需aar库4.3 提取出依赖的本地jar包4.3.1 查找本地jar包的位置4.3.2 所需jar列表(ando…...

1.5 异常

什么是异常 异常就是在程序运行期间&#xff0c;因为某些原因导致程序出现了错误的情况。 异常封装了三个重要信息: 类型&#xff0c;信息&#xff0c;行号 异常的简单继承结构 Throwable |- Error 系统级别的错误&#xff0c;无法处理&#xff0c;只能停止运行 |- Excepti…...

[HCIP] 10 - IGMP 协议

一、IGMP 介绍 二、组播组管理协议工作机制&#xff1a;...

海大09-10.3题:编程计算并输出1*2+3*4+5*6+...+(n-1)*n的值,其中,n的值由键盘输入。(8分)

题目 本题是中国海洋大学《C语言程序设计》2009-2010年第一学期编程题第3题。 题目&#xff1a; 编程计算并输出12345*6…&#xff08;n-1&#xff09;*n的值&#xff0c;其中&#xff0c;n的值由键盘输入。&#xff08;8分&#xff09; 以下是本篇文章正文内容&#xff0c;欢…...

DEDE织梦如何做中英文多语言站

说道中英文站&#xff0c;是很多用户想用dedecms织梦程序做多语言站&#xff0c;下面网分享下做中英文多语言版本的站点如何操作&#xff0c;希望能帮助到大家。 一、首先在后台建栏目&#xff0c;有三点需要注意 1.需要做几种语言就加几个大的栏目。 2.栏目“常规选项”的文…...

2021-08-23 linux的部分基本命令与vi/vim的部分命令

linux的基本命令 文章目录linux的基本命令前言一、APT(Advanced Packing Tool)1.工作原理2.修改源3.几个常用的命令二、vi/vim一. vi/vim 模式1.vi有两种工作模式二. vi/vim 命令1.vim:退出命令2.vim删除与修改命令3.vim拷贝与粘贴命令4.vim 撤销命令5.vim 搜索命令6.vim 替换命…...

题解报告:m10

找abc(add) 问题描述&#xff1a; 有两个正整数集合{An},{Bm}&#xff0c;其中整数值均不超过106。输出正整数x&#xff0c;判断是否存在A中的一个数a与B中的一个数b的和为x。 输入格式&#xff1a; 第一行为正整数t(≤5)&#xff0c;表示数据组数&#xff1b;每组数据中&a…...

VISSIM二次开发(Python)大作业总结2

VISSIM二次开发&#xff08;Python&#xff09;&大作业总结2 写在前面 前一小节已经概括了基本所有这次使用的二次开发的知识&#xff0c;在这一小节&#xff0c;我们主要介绍本文对.att文件的读取和绘图以及分析的工作。 在这一部分我们将展开对这一部分的介绍&#xf…...

sql中grant授权语句revoke撤销语句

MySQL 赋予用户权限命令的简单格式可概括为&#xff1a; grant 权限 on 数据库对象 to 用户 一、grant 普通数据用户&#xff0c;查询、插入、更新、删除 数据库中所有表数据的权利 grant select on testdb.*to common_user%; grant insert on testdb.*to common_user%; gran…...

QT如何设置小程序不被重复启动多个该程序

添加互斥锁 判断 如果进程有该程序&#xff0c;则return不运行 #if defined Q_OS_WIN32 //for win #include <windows.h> bool checkOnly() {// 创建互斥量HANDLE m_hMutex CreateMutex(NULL, FALSE, L"fortest_abc123" );// 检查错误代码if (GetLas…...

jquery--动画效果

show() : 显示隐藏的匹配元素。 这个就是 show( speed, [callback] ) 无动画的版本。如果选择的元素是可见的&#xff0c;这个方法将不会改变任何东西。无论这个元素是通过hide()方法隐藏的还是在CSS里设置了display:none;&#xff0c;这个方法都将有效。 hide()&#xff1a…...

SVN错误:Previous operation has not finished;run “cleanup“ if it was interrupted.

问题分析&#xff1a; SVN报错以上错误&#xff0c;可能是修改本地的文件之前没有update&#xff0c;导致commit的时候产生冲突&#xff0c;致使SVN崩溃&#xff0c;陷入clean up 死循环。 svn 的 operation是存放在 "work queue" 里的。而 "work queue"…...

【力扣1044. 最长重复子串】二分查找+Rabin-Karp 字符串编码、后缀数组(Python3)

题目描述 https://leetcode-cn.com/problems/longest-duplicate-substring/ 思路题解 方法一&#xff1a;二分查找Rabin-Karp 字符串编码 https://leetcode-cn.com/problems/longest-duplicate-substring/solution/zui-chang-zhong-fu-zi-chuan-by-leetcode/ class Solut…...

政产学研各界推动软件和信息技术服务业增速发展

​日前&#xff0c;工业和信息化部发布的最新数据显示&#xff0c;上半年&#xff0c;我国软件和信息技术服务业业务收入呈加快增长态势&#xff0c;完成软件业务收入44198亿元&#xff0c;同比增长23.2%&#xff0c;近两年复合增长率为14.7%。 从利润水平来看&#xff0c;上半…...

java16语言新特性

新语言特性 JEP 394&#xff0c;适用于 instanceof 的模式匹配模式匹配&#xff08;Pattern Matching&#xff09;最早在 Java 14 中作为预览特性引入&#xff0c;在 Java 15 中还是预览特性。模式匹配通过对 instacneof 运算符进行模式匹配来增强 Java 编程语言。模式匹配使程…...

JavaScript-DOM、BOM对象

DOM对象 功能&#xff1a;控制html文档的内容 1、获取页面标签(元素)对象&#xff1a;Element 方法&#xff1a;document.getElementById(“id值”)&#xff1a;通过元素id获取元素对象、 2、操作Element对象&#xff1a; 1&#xff09;. 修改属性值&#xff1a; 明确获取的对…...

Vue 路由导航

...

Java学习五阶段-RabbitMQ-SpringBoot整合

文章目录 新建项目pom.xmlapplication.yml主程序 简单模式主程序生产者消费者测试类 工作模式主程序生产者消费者测试类 ack模式设置 ack 模式手动执行确认操作 抓取数量发布和订阅模式主程序生产者消费者测试类 路由模式主程序生产者消费者测试类 主题模式主程序生产者消费者测…...

flink 小技巧记录

一、背景 flink做etl、大宽表、统计过程中有些小细节可以尝试优化&#xff0c;这里简单记录下&#xff1a; 二、场景 2.1 允许延迟的数据同步。比如线上订单库binlog同步到查询库&#xff0c;或者简单处理进入分析库&#xff0c;让分析师直接查询明细. 如果吞吐要求大一点&…...

带你了解DDoS攻击的原理,让你轻松学会DDoS攻击原理及防护措施

DDoS攻击原理是什么? 随着网络时代的到来&#xff0c;网络安全变得越来越重要。在互联网的安全领域&#xff0c;DDoS(Distributed DenialofService)攻击技术因为它的隐蔽性&#xff0c;高效性一直是网络攻击者最青睐的攻击方式&#xff0c;它严重威胁着互联网的安全。接下来的…...

微信小程序从云开发到上线

文章目录一、创建项目二、云函数三、静默登录四、获取用户信息五、使用缓存六、同页面数据操作七、不同页面数据传递八、页面跳转九、检查版本更新十、上线​ 前段时间自己做了一个云开发微信小程序&#xff0c;发现并不复杂&#xff0c;有前端基础的可以试一下。这里主要简单说…...

P4173 残缺的字符串

P4173 残缺的字符串 题意&#xff1a; 有A&#xff0c;B两个串&#xff0c;每个串都有通配符&#xff0c;问A为模板串&#xff0c;对于 B 的每一个位置 i&#xff0c;从这个位置开始连续 m 个字符形成的子串是否可能与 A 串完全匹配&#xff1f; 题解&#xff1a; 我们定义…...

祥云杯部分pwn的wp

lemon 主要问题是2.26版本下, 未控制好指针导致任意写 数据结构如下: lemon_name: lemon_content: 主要可利用的函数是color: 里的buf是指lemon_name结构, 所以可以控制指针lemon_addr的指向了, 因为只能用一次所以想控制整个tcache结构 其它一点可利用的函数: 开头的一次…...

OverScroll介绍

OverScroll OverScroll作用 首先&#xff0c;OverScroll虽然内置了很多看起来像执行滑动效果的方法名&#xff0c;比如startScroll(int, int, int, int),springBack(int, int, int, int, int, int)等等&#xff0c;但是他们并不实际执行滑动效果&#xff0c;只是用于辅助计算…...

TensorFlow项目1——鸢尾花识别(来源:北大曹健老师tensorflow学习视频)

项目1.鸢尾花识别 1.完整代码 import matplotlib.pyplot as plt from sklearn import datasets from pandas import DataFrame import pandas as pd import numpy as np import tensorflow as tf# 数据处理 #1.读取iris数据&#xff08;sklearn已有&#xff09; #2.随机打乱&…...

1.5 异常

什么是异常 异常就是在程序运行期间&#xff0c;因为某些原因导致程序出现了错误的情况。 异常封装了三个重要信息: 类型&#xff0c;信息&#xff0c;行号 异常的简单继承结构 Throwable |- Error 系统级别的错误&#xff0c;无法处理&#xff0c;只能停止运行 |- Excepti…...

使用朴素贝叶斯过滤垃圾邮件

示例&#xff1a;使用朴素贝叶斯对电子邮件进行分类(1) 收集数据&#xff1a;提供文本文件。(2) 准备数据&#xff1a;将文本文件解析成词条向量。 (3) 分析数据&#xff1a;检查词条确保解析的正确性。(4) 训练算法&#xff1a;使用我们之前建立的trainNB0()函数。(5) 测试算法…...

链表反转。

举个例子来分析一下如何实现链表的反转。 链表示例&#xff1a;9—>6—>8—>7—>1—>null。 1&#xff09;首先定义两个指针cur、pre分别指向链表头和链表尾。 2&#xff09;定义一个临时指针&#xff0c;指向cur.next。 3&#xff09;修改cur指针的指向&#x…...

day01_java常识丶环境搭建丶入门程序

Java语言发展历史 Java诞生于SUN&#xff08;Stanford University Network&#xff09;&#xff0c;09年SUN被Oracle&#xff08;甲骨文&#xff09;收购。Java之父是詹姆斯.高斯林(James Gosling)。1996年发布JDK1.0版。 目前最使用最多的版本是Java8。 ​ Java技术体系平台 …...

C++类的讲解(一)(超详细)

C类的讲解 1、面向对象和类的介绍 1&#xff09;面向对象 C语言使用面向过程的编程方式&#xff0c;而C则增加了面向对象的编程方式。 面向过程&#xff1a;分析出解决问题所需要的步骤&#xff0c;然后用函数把这些步骤一步一步实现&#xff0c;使用的时候一个一个依次调用就…...

html如何添加阿里图标,CSS引入阿里iconfont图标步骤

CSS引入阿里iconfont图标步骤第一步选择图标&#xff0c;选择添加入库第二步没有项目就新建一个项目下载项目文件&#xff0c;复制粘贴到你的WEB项目目录中回到网页&#xff0c;点击查看在线链接复制代码到你的index.html定义使用iconfont的样式.iconfont{font-family:"ic…...

MySQL进阶

文章目录数据库约束NULL约束UNIQUE&#xff1a;唯一约束DEFAULT&#xff1a;默认值约束PRIMARY KEY&#xff1a;主键约束FOREIGN KEY&#xff1a;外键约束表的设计——一对一、一对多、多对多增删改查进阶聚合函数Group by分组having:分组后的条件过滤联合查询内连接外连接自连…...

基于Halcon学习的一维码识别【十三】ean13.hdev

读取EAN-13型条形码 总代码&#xff1a; *创建模板 create_bar_code_model ([], [], BarCodeHandle) CodeType : EAN-13 * dev_close_window () dev_open_window (0, 0, 544, 496, black, WindowHandle) set_display_font (WindowHandle, 16, mono, true, false) dev_set_col…...

php ean13,php生成EAN_13标准条形码实例_php实例

function EAN_13($code) {//一个单元的宽度$lw 2;//条码高$hi 100;// the guide code is no coding,is used to show the left part coding type//// Array guide is used to record the EAN_13 is left part coding type//$Guide array(1>AAAAAA,AABABB,AABBAB,ABAABB,A…...

条码规范——EAN13

EAN-13 BACKGROUND INFORMATION EAN-13, based upon the UPC-A standard, was implemented by the International Article Numbering Association (EAN) in Europe. This standard was implemented mostly because the UPC-A standard was not well designed for internation...

php ean13,php生成EAN_13标准条形码实例_PHP教程

function EAN_13($code) {//一个单元的宽度$lw 2;//条码高$hi 100;// the guide code is no coding,is used to show the left part coding type//// Array guide is used to record the EAN_13 is left part coding type//$Guide array(1>AAAAAA,AABABB,AABBAB,ABAABB,A…...

一维码EAN 13简介及其解码实现(zxing-cpp)

一维码EAN 13&#xff1a;属于国际标准条码, 由13个数字组成&#xff0c;为EAN的标准编码型式(EAN标准码)。依结构的不同&#xff0c;EAN条码可区分为&#xff1a;1&#xff0e; EAN 13码: 由13个数字组成&#xff0c;为EAN的标准编码型式(EAN标准码)。2&#xff0e; EAN 8码…...

vs2019_qt6.2.4_dcmtk3.6.7_vtk9.2.2_itk5.3_opencv4.6.0编译记录

目录 1 dcmtk3.6.7编译 2 vtk9.2.2编译 3 itk5.3编译 4 opencv4.6.0 5 参考链接 编译顺序&#xff0c;qt6.2.4下载----->dcmtk3.6.7----->vtk9.2.2----->itk5.3----->opencv4.6.0 opencv4.6需要使用到vtk9.2.2&#xff0c;需要在最后编译。 opencv遇到…...

流程图怎样绘制?绘制流程图使用什么工具好?

流程图的也是图表的一种展现格式&#xff0c;其中可能介绍的是某件事情的操作流程&#xff0c;可能是某件事情的解决方法&#xff0c;总之使用流程图都可以进行很好地解决&#xff0c;那流程图要怎样绘制&#xff0c;使用什么软件进行操作呢&#xff1f; 现在随着网络技术的发…...

Android入门第41天-Android中的Service(bindService)

介绍 在前一天我们介绍了Android中有两种启动Service的方法。并擅述了startService和bindService的区别。同时我们着重讲了startService。 因此今天我们就来讲bindService。bindService大家可以认为它是和Android的一个共生体。即这个service所属的activity如果消亡那么bindS…...

png图片转base64

<img idiii load"abc" src"../aseets/bottom.png" > <canvas id"canvas"></canvas>abc(){var canvasdocument.getElementById(canvas)var imgdocument.getElementById(iii)var ctxcanvas.getContext("2d")var he...

unity sprite保存成PNG图片

图集拆分后可以将子图单独保存成png图片&#xff0c;使用如下代码&#xff0c; var sprites Resources.LoadAll<Sprite>("main"); Debug.Log("拆分的图片如下:"); var path "D:/Splite/"; if (!Directory.Exists(path)) {Directory.Crea…...

【Qt记录】Windows 窗口层级(Z-order)

功能&#xff1a;软件有一个提示弹窗&#xff0c;希望让他永远在最上面&#xff0c;保证该窗口在任何情况下不会被遮挡。 由上面的问题就查找对应的api找到了SetWindowPos()。 在说这个函数之前&#xff0c;先了解以下概念&#xff1a; Z-order&#xff08;Z顺序&#xff09…...

c语言星空程序,C语言C 编程学习程序员大神!绘制神奇代码之星空动态

CC语言C 编程学习程序员大神&#xff01;绘制神奇代码之星空动态C语言是面向过程的&#xff0c;而C&#xff0b;&#xff0b;是面向对象的C和C的区别&#xff1a;C是一个结构化语言&#xff0c;它的重点在于算法和数据结构。C程序的设计首要考虑的是如何通过一个过程&#xff0…...

HTML+js实现美丽的动态星空

程序如下&#xff1a; <!doctype html> <html> <head><meta charset"utf-8"><title>旋转的星空</title><style type"text/css">body{background: black;padding: 0;margin: 0; overflow:hidden}.header{margin…...

MATLAB 作动态图

MATLAB 作动态图MATLAB 作动态图动态线图生成数据作动态图方法一方法二动态点图确定参数生成数据并创建函数句柄迭代以形成动态效果实际应用输出效果MATLAB 作动态图 本文谨记录笔者探索MATLAB作动态图后的心得&#xff0c;希望能帮到大家 动态线图 生成数据 首先打开MATLA…...

fiash星空动画制作_Flash8实现动态星空的通用方法

推荐&#xff1a;Flash8制作图片由模糊到清楚效果以前记得是在哪个网站看到这个效果&#xff0c;但是怎么找也找不到了&#xff01;所以给大家讲解一下如何制作。主要是讲解Flash8的blur滤镜&#xff0c;利用Actonscript调用blur滤镜实现由模糊你想做星空吗&#xff1f;只需要把…...

C语言不用graphics的星空,c语言实现动态星空.docx

集团文件版本号&#xff1a;(M928-T898-M248-WU2669-I2896-DQ586-M1988)集团文件版本号&#xff1a;(M928-T898-M248-WU2669-I2896-DQ586-M1988)C语言实现动态星空// 编译环境&#xff1a;Visual C 6.0&#xff0c;EasyX 2014冬至版// e a s y x . c n//#include #include #inc…...

php星空背景动态,纯CSS3炫酷3D星空动画特效

简要教程这是一款使用纯CSS3制作的炫酷3D星空动画特效。该特效中&#xff0c;以飞船向前快速移动为视角&#xff0c;所有的星星都快速的变大并向后移动&#xff0c;效果非常逼真。使用方法HTML结构该3D星空特效只使用一个元素作为容器即可。CSS样式该3D星空特效中的星星使用sta…...

vue实现动态星空效果

B站地址&#xff1a;https://www.bilibili.com/video/BV1XJ411a7Mf/?spm_id_from333.788.videocard.18 在此之前&#xff0c;要先安装 less less-loader webpack.base.conf.js {test: /\.less$/,use: [{loader: "style-loader"}, {loader: "css-loader"…...