HTML + CSS
什么是边界塌陷?
父 div 中包含子 div,如果给子 div 设置 margin-top,而实际展示效果是给父子元素增加了 margin-top
- 解决方式 1:给父元素添加 border: 1px solid #000000;
- 解决方式 2:给父元素设置 overflow: hidden;
什么是 margin 纵向重叠?
两个兄弟关系 div,上面的设置 margin-bottom,下面的设置 margin-top,两个 div 之间的值由 margin 比较大的决定。
- 解决方式 1:给下面的设置 display: inline-block;
- 解决方式 2:给上面的设置 display: table-caption;
padding 和 margin 有什么不同?
padding 是内边距,margin 是外边距。内外边距的作用对象不同。内边距作用于自身,而外边距作用于外部对象。
什么是 BFC?
在浏览器中创建一块独立区域,让这块区域的子元素不会影响到外面的布局。
作用:防止 margin 重叠、清除浮动
如何触发 BFC:
overflow:hidden | scroll | auto; float:left | right; display:inline-block | flex | table-caption; position:absolute | fixed;
position 值的区别?
static
默认值,就是没有定位。
relative
相对定位,给元素设置相对于自己原本位置的定位,元素并不脱离文档流,因此元素原本的位置会被保留,其他的元素位置不会受到影响。
absolute
是绝对定位,是的指让元素相对于 static 定位之外的第一个父元素进行定位;
- 如果此元素有祖先素设置了 position 属性为 relative 或者 absolute,那么就根据此元素定位。如果没有祖先元素设置,那就根据 body 进行定位。
fixed
是一种特殊的绝对定位,也会脱离文档流,只不过 fixed 的元素是固定相对与 body 来定位的。
line-height 继承问题?
- 具体数值,如果子元素未设置行高,会自动继承父元素的行高
- 按比例,子元素未设置行高,父元素行高为 1.5,子元素的行高为 font-size x 1.5
水平垂直居中一个 div?
- 方法 1:给要居中的 div 的父元素设置
display: flex; justify-content: center; align-items: center;
- 方法 2:给要居中的 div 设置
width: 300px; height: 300px; transform: translate(-50%, -50%); position: absolute; top: 50%; left: 50%;
- 方法 3:快速
要居中的盒子设置 margin:auto; 该盒子的父盒子 display:flex;
清除浮动的方法?
- 方法 1:
clear: both;
- 方法 2:伪元素
.box::after { content:""; display:block; height:0; visibility:hidden; clear:both; }
盒模型?
盒模型的组成为:
content
、padding
、margin
、border
- 普通盒模型:宽度指的就是内容的宽度,即 content
- ie 盒模型:宽度指的是内容的宽加上外边距加上边框,即:content+padding+border
注:可以通过 box-sizing 改变盒模型类型
如何实现一个三角形?
思路:给 box 四条边框设置宽度和颜色,再给其余三条设置颜色为透明
.box{ width:0; border:100px solid green; border-top(left、right):100px solid transparent; }
css 长度单位有什么?
px
绝对单位。
em
相对单位,会继承父元素的 font-size。
rem
相对单位,相对于 html 根元素。如果 html 根元素设置了 font-size:100px,那么 1rem=100px。
vw
视口宽度的 1/100。如果屏幕的宽为 375px,那么 1vw = 3.75px。
vw 和百分比区别?
百分比继承于父级
vw 针对于设备屏幕
link 和@import 的区别?
link
属于 html 标签,而@import
是 css 提供的。
link
在页面加载时会被同时加载,而@import
引用的 css 会等到页面加载结束后加载。
link
是 html 标签,因此没有兼容性,而@import
只有 IE5 以上才能识别。
link
除了引用样式文件,还可以引用图片等资源文件,而@import
只引用样式文件。
link
支持使用 Javascript 控制 DOM 去改变样式;而@import
不支持。
怎么理解回流跟重绘?
回流:布局引擎会根据各种样式计算每个盒子在页面上的大小与位置。
重绘:当计算好盒模型的位置、大小及其他属性后,浏览器根据每个盒子特性进行绘制。
注:触发回流一定会触发重绘
JavaScript
JavaScript 中的数据类型?
原始数据类型
striung
、number
、boolean
、undefined
、null
、symbol
引用数据类型
Object
他们的区别:
- 存储位置不同:
- 原始值:存储在栈(stack)中,它们的值直接存储在变量访问的位置。
- 引用值:存储在堆(heap)中的对象,存储在变量处的值是一个指针(point),指向存储对象的内存地址。
- 比较方式不同:
- 原始值:直接比较变量的值。
- 引用值:比较引用,简单来说引用值的比较就是看是不是指向同一块堆内存)
- 传参方式不同:
- 原始类型作为参数,函数内的操作不影响实参的值。引用类型作为参数,函数内的操作会影响实参的值。
== 和 === 的区别?
== 比较的是值,会通过 valueOf()隐式转换。
=== 比较的是类型,不会隐式转换。
JS 中数组的方法?
方法名 功能 map 美化数组,有返回值 forEach 遍历数组,没有返回值 filter 遍历数组,只有满足条件的才返回 find 遍历数组,返回满足条件的第一个 Array.from 将伪数组转成真数组 includes 数组中是否包含某个值,包含则返回 true push 向数组最后添加一位 splice 从数组中删除元素,并返回被删除的结果
JS中的内置对象?
Date Array Boolean Number Map Set Math Promise RegExp
遍历对象的方法有哪些?
for...in
遍历对象的所有属性,包括对象本身的和对象继承来的属性let obj = { name:'张三', age: 28, } for(key in obj){ console.log(key) }
Object.keys()
可以遍历到所有对象本身的属性,但是其返回值为数组console.log(Object.keys(obj))
Object.values()
同 Object.keys(),但返回的是属性值的的数组console.log(Object.values(obj))
冻结Object的方法?
let obj = { namne: "zs", age: 18, }; Object.freeze(obj); // Object.freeze()方法可将对象冻结,也就是变为只读 Object.seal(obj); // Object.seal()方法可将对象密封,可以修改,但是不能增加,删除,劫持 Object.preventExtensions(obj); // Object.preventExtensions()方法可将对象转为不可扩展,也就是可以删除,修改,劫持,但是不能新增
JS 判断数据类型的方法?
console.log(typeof null) // object console.log(Object.prototype.toString.call("123")) // [object String] console.log([1, 2, 3].constructor) // Array() { [native code] }
null 和 undefined 的区别?
undefined
表示"缺少值",表示此处应该有值但是还没有定义。typeof 返回的是 undefined。场景:
- 变量声明但未赋值,就是 undefined
- 没有找到对象中的指定属性,也是 undefined
- 函数没有返回值,也是 undefined
null
表示"没有对象",也就是说此处不应该有值。typeof 返回的是 object注:undefined 和 null 不能调用 toString(),因为他俩没有原型(
__proto__
)
call、apply、bind 的区别?
call
和apply
可以调用函数,改变 this 指向。call 和 apply 的区别是他们的传参方式不同, call 的将所有参数以逗号分隔开依次传入;apply 是将所有参数放到一个数组里传入。
bind
不会调用函数,他可以作为一个返回值返回一个函数,然后才能用。它的传参方式和 call 一样。
强制类型转换和隐式类型转换有哪些?
强制:
- 转换成字符串:
toString()
、String()
- 转换成数字:
Number()
、parseInt()
、parseFloat()
- 转换成布尔类型:
Boolean()
隐式:
- 拼接字符串:
let str = 1 + "";
事件冒泡、事件委托、事件捕获?
事件冒泡(由内到外):简单来说就是在一个元素上绑定了事件,如果此元素本身有就会直接被触发。如果此元素上没有,就会一层一层向上找,直到 document。
事件委托:利用事件冒泡处理动态元素事件绑定的方法,就叫做事件委托。简单来说给父元素绑定事件,委托给子元素来处理。(动态增加 dom,可以使用事件委托)
事件捕获(由外向内):当前元素触发事件后,会从当前元素的最上层祖先元素开始向当前元素进行事件的查找,到目标元素就即截止。
什么是原型?
原型
是对象
的一个属性
。他是构造函数构造出对象的祖先。通过构造函数构造出来的对象可以继承他的属性和方法。利用原型特点和概念,可以提取共有属性。
// 将demo中的name和方法提取出来_ function Car(color) { this.color = color } Car.prototype.name = "宝马" Car.prototype.run = function () { console.log("i can run") } var car = new Car("绿色") console.log(car.color) // 绿色 onsole.log(car.name) // 宝马 // 访问属性和方法时,如果构造函数中有就不会去找他的祖先。 car.constructor === function Car(){}
什么是原型链?
把原型连成链子,一层一层往上找,就是原型链。
注:绝大多数的对象最终都会继承自 Object.prototype
什么是闭包?
定义:闭包是指 在 A 函数(父函数)中定义的函数,并且可以访问父函数作用域中的变量的函数。他可以访问三个作用域的变量
全局
、父函数
、自己
作用:可以读取函数内部的变量,让这些变量的值始终保持在内存中。
优点:隐藏变量,避免全局污染。
缺点:由于一直保存在内存中,会出现内存泄露。
闭包的触发场景
- 把一个函数(方法)当做返回值返回
function fn() { const a = 1; return function () { console.log(a); // 1 } } const a = 100; const callback = fn() callback()
- 自执行匿名函数(立即执行函数)
(function (index) { console.log(index); // 666 })(666)
- 设置私有变量
let car = (function () { let _width = Symbol(); class Car { constructor(wid) { this[_width] = wid } foo() { console.log(this[_width]) } } return Car })(); let che = new car(2000); che.foo(); console.log(che[_width])
什么情况会导致内存泄露?
内存泄漏:一般是指系统进程不再用到的内存,没有及时释放,造成内存资源浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
造成内存泄漏的原因有?
全局变量。
在局部作用域中,函数执行完毕后,变量就没有存在的必要了,垃圾回收机制很快的做出判断并回收;但是对于全局变量,很难判断什么时候不用这些变量,无法正常回收。解决办法:
① 尽量少使用全局变量;
② 使用严格模式,在 js 文件头部或者函数的顶部加上 use strict。
闭包引起的内存泄露。
闭包可以读取函数内部的变量,然后让这些变量始终保存在内存中,如果在使用结束后没有将局部变量清除,就可能导致内存泄露。解决办法:将事件处理函数定义在外部,解除闭包。
被遗忘的定时器。
定时器 setInterval 或者 setTimeout 不再需要使用时,且没有被清除,导致定时器的回调函数及其内部依赖的变量都不能被回收,就会造成内存泄漏。解决办法:当不需要定时器的时候,调用 clearInterval 或者 clearTimeout 手动清除。
事件监听。
垃圾回收机制不好判断事件是否需要被解除,导致 callback 不能被释放,此时需要手动解除绑定。解决办法:及时使用 removeEventListener 移除事件监听。
元素引用没有清理。
解决办法:移除元素后,手动设置元素的引用为 null。
console。
传递给 console.log 的对象是不能被垃圾回收,可能会存在内存泄漏。解决办法:清除不必要的 console。
普通函数的 this ?
function fn (){ console.log( this ) } let obj = {name:'张三‘,fun:fn} obj.fn() // 这种有点的情况 this 就是 obj
- 函数执行,函数前面如果有“点”,那么
this
就是这个“点”。如果没有“点”,this 就指向的是 window,严格模式下是 undefined。- 给元素的某个事件行为绑定方法,当事件行为触发,方法中的 this 是当前元素本身 (排除 attachEvent)。
例如:给 body 绑定点击事件,打印 this 就是<body></body>
)- 构造函数体中的 this 是调用该构造函数创建的实例对象。
- 普通函数可以通过 call、apply、bind 改变 this 指向。
箭头函数的 this ?
箭头函数没有自己的 this ,他的 this 由他的外层作用域决定。
深拷贝和浅拷贝?
let arr = [{name:”孙悟空”},{name:”猪八戒”} ]
浅拷贝:浅拷贝只是复制了堆内存中的对象本身,而对象中的属性或元素不会进行复制。
例:
arr.clice()
深拷贝:不仅复制对象本身,也要将对象的属性或元素也复制。简单来说就是所有的东西都重新复制了,包括属性等内容。因为性能问题通常不太使用深拷贝。
例:
structuredClone(arr)
Map、Set 和 Object 的区别?
Object 中的属性名只能是字符串或符号。
Map 中任何类型的值都可以成为数据的 key。
map 操作:let map = new Map() map.set(‘name’:’张三’) map.get(‘name’)
Set 用来创建一个集合,它的功能和数组有些类似,不同的是 Set 中不能存储重复的数据。
let set = new Set() set.add(10) // 向数组中添加一个数
localStorage、sessionStorage 和 Cookie 区别?
localStorage
:除非手动清除,否则永久保存。一般为 5MB。尽在浏览器中保存,不和服务器通信。
sessionStorage
:仅在当前会话下生效,关闭页面或浏览器后被清除。一般为 5MB。尽在浏览器中保存,不和服务器通信。
Cookie
:一般由服务器生成,可设置失效时间。如果在浏览器端生成 Cookie,默认是关闭浏览器后失效。4KB 左右。每次都会携带在 HTTP 头中,发送给服务端。但是使用 cookie 保存过多数据会带来性能问题。
ES6 的新特性?
let
:定义块级作用域的变量,不能重复声明变量,不存在变量提升。
const
:定义块级作用域的常量。常量不可以修改。
function=()=>{}
:箭头函数,函数体内的 this 对象,就是定义时所在的对象,不是使用时所在的对象,不可以通过 call,apply 修改 this。
...
:展开运算符:实参是形参相对应,如果实参多了,可通过...args 把剩余参数收集起来。
map
、foreach
、filter
等数组操作方法
模板字符串
:${name}
>解构赋值
:可以处理数据的多级嵌套,而且允许设置默认值。
说说 promise?
promise
就是解决异步编程的一种方案。本身是一个构造函数,需要传入两个参数 resolve 和 reject,resolve 表示成功,reject 表示失败。可以通过.then 响应成功的回调,catch 响应失败的回调。
链式调用:就是下一个
.then
带着上一个.then
的执行成功结果执行下一步。
Promise.all()
将多个 Promise 实例包装成一个 Promise 实例,参数一般是一个数组。它的状态是由 all 里面的参数决定的,只有参数里面都为成功,Promise.all()的状态才为成功,否则就是失败。
JS 的运行机制?
JS是单线程的,也就是一个任务完成之后再执行下一个任务。
执行顺序如下:
同步程序按顺序执行
异步程序,先执行一部分,等待结果或者时间到了,再执行
同步程序执行完之后再执行异步程序
宏任务包含:setTimeout、setInterval、ajax 读取文件
微任务包含:Promise.then 等
执行顺序:同步方法 -> nextTick(同步之后异步之前执行) -> 异步(先微任务,后宏任务) -> setImmediate(异步之后执行)
JS中的事件循环?
1.同步程序按顺序执行
2.异步程序,先执行一部分,等待结果或者时间到了,再执行
3.同步程序执行完之后执行异步程序
async / await 的理解和用法?
是基于 promise 的解决异步的方案。
async
是加在函数前的修饰符,被 async 定义的函数会默认返回一个 promise 对象的 resolve 的值。因此 async 可以直接用.then()。
await
也是修饰符,指定房贷 async 定义的函数内,可以理解为等待。await 修饰的如果是 promise 对象,那么可以获取 promise 中返回的 resolve 或 reject 对象,且取到值后才能往下执行。如果不是 promise 对象,就把这个东西当做 await 表达式的结果。
从输入 URL 到页面展示都发生了什么?
域名解析。判断输入的是一个合法的 URL 还是一个待搜索的关键词。
DNS 解析。把域名翻译成 IP 地址,根据域名 端口 路径 找到对应资源。
建立 TCP 链接。(三次握手:发送响应->响应->接收响应)。
发动请求。
服务器返回数据。
浏览器解析并渲染页面。
断开 TCP 链接(四次挥手)。
什么是跨域?如何解决跨域问题?
跨域:违反同源策略。
同源策略:是指协议、域名、端口相同。
解决跨域:本地开发使用 proxy 代理,生产或者测试环境由后端统一配置。
React
React 的生命周期?
reat 生命周期分为三个阶段,挂载、更新、卸载
挂载
constructor()
: 在 React 组件挂载之前,会调用它的构造函数。
getDerivedStateFromProps()
: 在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。
- 作用: 从更新后的 props 中获取 State,若 props 的值发生变化时对 state 赋值,不变化则直接 return null,不必对 state 做任何操作。
render()
:render() 方法是 class 组件中唯一必须实现的方法。
componentDidMount()
:在组件挂载后(插入 DOM 树中)立即调用
- 作用:一般在这里发送 ajax 请求,或者获取父组件传递的参数。
更新
shouldComponentUpdate()
:当 props 或 state 发生变化时,shouldComponentUpdate() 会在渲染执行之前被调用。
getSnapshotBeforeUpdate()
: 在最近一次渲染输出(提交到 DOM 节点)之前调用。
componentDidUpdate()
:在更新后会被立即调用。卸载
componentWillUnmount()
:在组件卸载及销毁之前直接调用。
- 作用:一般在这里关闭定时器,取消订阅消息等
父子组件生命周期执行顺序?
遵循深度优先原则,父组件在操作中遇到子组件,一定是把子组件处理完,再处理父组件
- 初始化时:
父 constructor 父 getDerivedStateFromProps 父 render 子 constructor 子 getDerivedStateFromProps 子 render 子 componentDidUpdate 父 componentDidUpdate
react diff 的理解?
tree
diff:把树形结构按照层级分解,只比较同级元素,忽略掉跨层级的操作。
component
diff:在对比两个组件时,首先会判断它们两个的类型是否相同,如果不同则不会进一步向下比较,会直接销毁组件,创建新的组件插入。
element
diff:对于同一层级的一组节点,会使用具有唯一性的 key 来区分是否需要创建,删除,或者是移动。注:可以通过重写 shouldComponentUpdate 提高 diff 的性能。
什么是虚拟 DOM?
虚拟 DOM 就是用 JS 对象来表示真实 DOM。利用 diff 算法减少了没有必要的 DOM 操作,从而提高性能。
什么是静态组件和动态组件?
函数组件是静态组件;函数组件在第一次渲染完后,组件中的内容不会根据组件内的某些操作再进行更新,除非在父组件中重新调用这个子组件。
类组件是动态组件;render函数在渲染的时候,如果type是:
- 字符串:创建一个标签
- 普通函数:把函数执行,并且把props传递给函数
- 构造函数:把构造函数基于new执行,也就是创建一个实例,也会把解析出来的props传递过去
PureComponent和Component的区别?
- PureComponent会给类组件默认增加一个shouldComponentUpdate生命周期函数。在此生命周期函数中,它对新老的属性和状态会做一个浅比较,如果经过浅比较发现属性和状态并没有改变,则返回false不继续更新,反之会更新(浅比较:只会比较对象的第一级)
React 中 Refs 的作用是什么?
refs 可以用于获取一个 DOM 节点,在需要做焦点管理的时候可以使用。(例:搜索页,默认进来 input 是焦点选中状态)
React 中 keys 的作用是什么?
key 是 React 中用于追踪哪些列表中元素被修改、删除或者被添加的辅助标识。在 diff 算法中,key 用来判断该元素节点是被移动过来的还是新创建的元素,减少不必要的元素重复渲染
setState 是同步的还是异步的?
React16:在周期函数、合成事件里,setState是异步的,但是在定时器中将变为同步(立即更新状态和让视图渲染)。
React18:不论在什么地方执行,都是异步的(都是基于updater更新队列机制实现批处理)
目的:
实现状态的批处理
有效减少更新次数,降低性能消耗
有效管理代码执行的逻辑顺序
原理:
在当前相同时间段内,遇到setState会立即放到更新队列中
此时状态还未更新
当所有代码操作结束,会通知更新队列中的任务执行,把所有的setState合并到一起执行,只触发一次视图更新
// react-dom中的flushSync可以刷新"updater更新队列",也就是让修改状态任务立即处理一次 flushSync(()=>{ })
state 和 props 区别是什么?
props 和 state 是普通的 JS 对象,它们都是用来保存信息的。
state
是组件自己管理数据,控制自己的状态,可以修改。
props
是外部传入的数据参数,不可修改。没有 state 的叫做无状态组件,有 state 的叫做有状态组件。
注:多用 props,少用 state,也就是多写无状态组件
React 父子组件通讯?
父传子:
- 父组件基于属性,把数据和修改数据的方法传给子组件,子组件通过
props
接收/使用即可【子组件中可通过prop-types做数据的规则校验】- 父组件基于属性中的
children
(插槽),可以把HTML
结构传给子组件祖先传子孙:
创建一个React.createContext()上下文对象
const ThemeContext = React.createContext()
祖先组件通过React.createContext()创建的上下文对象中的Provider包裹,并传递value属性,值为要传递的数据
<ThemeContext.Provider value={{count,...}}> 父组件原本html结构 </ThemeContext.Provider>`
子孙组件通过this.context可以拿到传递的数据(类组件)
static contextType = ThemeContext console.log(this.context)
子孙组件通过React.useContext(ThemeContext)可以拿到传递的数据(函数组件)
import React, {useContext} from "react" const {XX , OO} = useContext(ThemeContext)
子传父:子组件向父组件传值
- 第一步:父组件通过 props 方法向子组件传入一个方法
- 第二步:子组件通过调用该方法将数据以参数的形式传给父组件
- 第三步:父组件可以再该方法中对传入的数据进行处理
Dva 是什么?
Dva 是基于 redux、redux-saga 并且集成了 react-router 和 fetch 的轻量级框架。
如果是同步行为可以通过 models 中的 reducers 改变 state。
如果是异步行为,会先触发 effects(中的方法),通过 put,推向 reducers,最终改变 state。
Dva 是怎么改变数据的?
- 数据是存储在 models 中 state 里面的,通过 namespace 来区分。
- 用户点击按钮之后
- 触发唯一更新 state 的方法 dispatch,
- dispatch 有两个参数
dispatch({type:'',payload:{}})
- 第一个是 type,就相当于给这个 action 起一个描述性的名字
- 第二个是 payload,在异步的行为中用于传递异步请求的参数。
- models 中的 state 发生变化之后,通过 connect 方法拿到 model 中的数据从而改变页面。
connect 的原理是什么?
注:首先 connect 是一个高阶函数
在原组件上包裹一层 provider,使原来的应用成为 provider 的子组件。 接收 state 作为 props,通过 context 对象传递给子孙组件上的 connect。
什么是高阶组件(HOC)?
高阶组件是接收一个组件作为参数,并返回一个新的组件。
简单来说:就是利用js中的闭包[柯理化函数],实现的组件代理。
作用:可以在代理组件中,经过业务处理一些数据,最后基于属性等方法传给真实要渲染的组件
import React from 'react' const Demo = function Demo(props) { return ( <div> <p>{props.x}</p> <p>{props.y}</p> </div> ) } // HOC:higher-order-components // 接收一个组件 const ProxyHoc = function ProxyHoc(Component) { const status = 1; return function HOC(props){ return <Component {...props} status={status}/> } } export default ProxyHoc(Demo)
受控组件和非受控组件区别?
页面中所有输入类的 DOM 如果是现用现取(通过 ref 取值)的称为非受控组件
通过 setState 将输入的值维护到了 state 中,需要时再从 state 中取出,这里的数据就受到了 state 的控制,称为受控组件。
TypeScript
类型断言和 any 的区别?
声明变量为 any 后,该变量可以是任意类型的数据。
类型断言是判断(或者说猜测)该变量应该是什么类型。
type 和 interface 的区别?
相同点:
都可以用来定义对象或函数、 都可以继承,但语法不同。
不同点:
type 在声明类型别名之后实际上是一个赋值操作,它需要将别名与类型关联起来。也就是说类型别名不会创建出一种新的类型,它只是给已有类型命名并直接进行引用。interface 是定义了一个接口类型。
type 能够表示非对象类型,而interface则只能表示对象类型。
interface 可以继承其他的接口、类等对象类型, type 不支持继承。
移动端开发相关问题
如何实现一像素边框?
.border-1px { position: relative; width: 200px; } .border-1px:before { content: " "; position: absolute; left: 0; top: 0; width: 100%; height: 1px; background: blue; -webkit-transform-origin: 0 0; transform-origin: 0 0; -webkit-transform: scaleY(0.5); transform: scaleY(0.5); }
如何实现自适应布局?
使用媒体查询,针对不同的屏幕实现不同样式。pc 和移动端使用同一套代码,方法简单,但代码量大。
flex 布局。纯 css 布局,简单清晰。
rem + viewport 缩放。
如何解决移动端 click 事件 300ms 延迟问题?
- 利用 touchstart、touchend 取代 click 事件。
- 利用 meta 标签禁止用户缩放。
设置了 overflow:scroll / auto;时,ios 上会卡顿?
- 解决:-webkit-overflow-scrolling:touch;
在安卓环境下 placeholder 文字设置行高会偏上的问题?
- 解决:input 有 placeholder 的时候不要设置行高
禁止 ios 识别长数字为电话?
- 解决:添加 meta 属性
<meta name="format-detection" content="telephone=no" />
禁止安卓手机识别邮箱?
- 解决:添加 meta 属性
<metacontent="email=no" name="format-detection" />
安卓端加载单页面应用的 webview 时,会加载多次,iOS 则不会
- 解决:增加变量控制。
ios 中对 2022-2-2 12:12 这种格式的日期不能够正常解析
- 需要将减号转换成斜线,也就是转成 2022/2/2 12:12
算法题
去重的几种方法?
let array = [12, 23, 12, 15, 25, 23, 25, 14, 16];
- 利用 set 方法
let arr = Array.from(new Set(array));
- 利用数组的 indexOf 方法
function removeDuplicate(arr) { const newArr = [] arr.forEach(item => { if (newArr.indexOf(item) === -1) { newArr.push(item) } }) return newArr // 返回一个新数组 } let result = removeDuplicate(array)
- 利用 for 循环
for (let i = 0; i < array.length; i++) { const index = array.indexOf(array[i], i + 1); if (index !== -1) { array.splice(index, 1) i-- } } console.log(array);
递归?
- 实现阶乘
function factorial(num){ if(num===1){ return 1 } return factorial(num-1) * num } console.log(factorial(100))
- 实现 1+2+3...+n
function add(num){ if(num===1){ return 1 } return add(num-1) + num } console.log(add(100))
性能优化
减少请求
强缓存:设置过期时间,在这个时间内缓存有效。
协商缓存:强缓存过期后,协商缓存向服务器发送请求。如果资源发生了修改,服务器就返回新的资源和资源表示,状态码为 200。如果没有发生修改,则返回 304,告诉浏览器可以使用本地缓存,响应时就无需携带资源。
雪碧图
避免 src 为空:可以不加这个属性,否则即使为空也会发送请求。
使用字体图标
图片懒加载
降低 css 选择器的复杂度
- 减少嵌套。
- 避免使用通配符。
- 合理利用继承。
- 减少重绘和回流。(例如:visibility 引起重绘,display 引起回流)
给 js 资源增加 defer 或者 async,延迟 js 的执行
增加防抖或者节流函数,避免多次点击发送多次请求
减少文件大小
- webpack 压缩图片、html 代码和 css 代码`
利用 CDN
- 将本地大文件存储到服务器上,代码中只引入链接
uni-app
- 页面生命周期
onLoad onShow onReady onHide onReachBottom …
- 组件生命周期
created mounted beforUpdate …
uni-app 页面定义:
pages 目录下的.vue 文件 ,支持页面生命周期,同时也支持组件生命周期;
部分生命周期作用:
onLoad
第一次进入页面触发 1.接收页面传递过来的参数 2.请求接口【展示类】
onShow
每一次进入页面都触发
onReady
页面渲染完成,可以获取 dom
onHide
每次页面隐藏触发组件定义:不在 pages 目录下的.vue 文件,一般让放在 components 目录中
路由和组件跳转
组件
<navigator url="" >
跳转到新页面</navigator>
api 方法
const OBJECT = { url:"", success:function(){}, fail:function(){}, } 保留当前页面,跳转到应用内的某个页面 uni.navigateTo(OBJECT) 关闭当前页面,跳转到应用内的某个页面 uni.redirectTo(OBJECT) 关闭所有页面,跳转到应用内的某个页面 uni.reLaunch(OBJECT) 跳转到 tabbar 页面,并关闭其他所有非 tabbar 页面 uni.switchTab(OBJECT) 关闭当前页面,返回上一页面或多页面 uni.navigateBack(OBJECT)