Skip to the content.

超级面试宝典🌻

加油/坚持/效率/输出(一些说明)

导航大纲


html小分队🌳

html的元素有哪些

常用块级元素

常用行内元素

h5系列

👉Return Top👆

页面导入样式的时候使用link和import有什么区别

  1. link是HTML标签,@import是css提供的。
  2. link引入的样式页面加载时同时加载,@import引入的样式需等页面加载完成后再加载。
  3. link没有兼容性问题,@import不兼容ie5以下。
  4. link可以通过js操作DOM动态改变样式,而@import不可以。

👉Return Top👆

在页面上隐藏元素的方法有哪些

👉Return Top👆

页面渲染html的过程

  1. 解析HTML文件,创建DOM树
  2. 解析CSS,形成CSS对象模型
  3. 将CSS与DOM合并,构建渲染树
  4. 布局和绘制

👉Return Top👆

如何让a标签鼠标悬停变色

a:hover {
  color: pink;
}

👉Return Top👆

元素的alt和title有什么异同

alt作为图片的替代文字出现,title作为图片的解释文字出现

👉Return Top👆


css小分队🍉

文本超出显示省略号

/* 多行显示省略号 */
.more_line {
	overflow: hidden; /* 超出隐藏 */
	text-overflow: ellipsis; /* 用省略号表示被截断的文本 */
	display: -webkit-box; /* 设置弹性伸缩盒子 */
	-webkit-box-orient: vertical; /* 设置伸缩盒子的子元素排列方式(从上到下垂直排列) */
	-webkit-line-clamp: 2; /* 第几行开始显示省略号 */
}

/* 单行显示省略号 */
.one_line {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap; /* 合并元素内的空白 */
}

👉Return Top👆

说一下圣杯布局和双飞翼布局的理解和区别

作用

圣杯布局和双飞翼布局解决的问题是一样的

就是两边顶宽 中间自适应的三栏布局

中间栏要在 放在文档流前面 以优先渲染

区别

为了中间div内容不被遮挡

将中间div设置了左右padding-left/padding-right

将左右两个div用相对布局position: relative并分别配合right和left属性

以便左右两栏div移动后不遮挡中间div

为了中间div内容不被遮挡

直接在中间div内部创建子div用于放置内容

在该子div里用margin-left/margin-right为左右两栏div留出位置

👉Return Top👆

css3有哪些新增的特性

  1. 边框圆角
  2. 盒子阴影
  3. 文字阴影
  4. 2/3d变换
  5. 弹性盒子
  6. 过渡及自定义动画

具体说一下

👉Return Top👆

position属性的作用

  1. static(默认值 标准文档流)
  2. relative(相对定位)
  3. absolute(绝对定位)
  4. fixed(固定定位)
  5. sticky(动态固定 relative/fixed的结合)
  6. inherit(继承父元素的position属性)

👉Return Top👆

如何取消li的默认样式

.demo {
  list-style: none;
}

👉Return Top👆

清除浮动的方式及优缺点

👉Return Top👆

说一下盒子模型的理解

css有两种盒子模型 分别是标准盒子模型和怪异盒子模型

.demo {
  /* 标准盒子模型 */
  box-sizing: content-box;
  /* 怪异盒子模型 */
  box-sizing: border-box;
}

👉Return Top👆

使用flex实现一个上下左右居中的布局

.demo {
	display: flex;
	justify-content: center; /* 水平居中 */
	align-items: center; /* 垂直居中 */
}

👉Return Top👆

css有哪些选择器

👉Return Top👆

css样式的优先级

!important > 内联样式 > ID 选择器 > 类选择器 = 属性选择器 = 伪类选择器 > 标签选择器 = 伪元素选择器 > 通配符选择器 > 继承 > 浏览器默认属性

👉Return Top👆

常见的自适应布局

圣杯/双飞翼都是用float实现的

👉Return Top👆

css常用的布局方式有哪些

  1. 流式布局 最基本的布局,就是顺着html像流水一样流下来
  2. 绝对定位 利用position: absolute进行绝对定位的布局
  3. float布局 最初用来解决多栏布局的问题。比如圣杯/双飞翼的布局都可以用float来实现
  4. 珊格布局 bootstrap用的布局,把页面分为24份,通过row和col进行布局
  5. flex布局 css3的布局可以非常灵活地进行布局和排版
  6. grid布局 网格布局

👉Return Top👆

style标签写在body前和body后的区别是什么

放在body前会跟HTML同时渲染

放在body后,浏览器会先渲染HTML,再渲染CSS

则会导致一开始出现一个没有样式的界面,再跳到有样式的界面

👉Return Top👆

简述下你理解的优雅降级和渐进增强

👉Return Top👆

css可以继承的属性

👉Return Top👆


js小分队🐎

var/let/const的区别

let和const是es6新增的

变量提升方面 只有var可以

作用域方面 var是函数作用域 let和const是块级作用域 不支持外部访问

初始值和重复声明方面 const在定义变量的时候需要赋值 且不可以重复声明 但是可以对数组元素或者对象属性进行修改 这个不算是重复声明

然后const不能用来定义for循环的迭代变量 因为它违反了const不能重复声明这条限制

👉Return Top👆

JavaScript的参数是以什么方式进行传递的

👉Return Top👆

说一下js的继承

原型继承

通过改造原型链 继承父级构造函数原型上的方法

Student.prototype = new Person()

组合继承

指的是将原型链和call()方法进行结合

通过原型链实现对原型上的属性和方法进行继承

然后通过call()方法对实例的属性进行继承

这样原型上定义的方法得到了函数复用 又能保证每个实例都有自己的属性

寄生组合继承

student实例上有的属性 原型__proto__上不再需要这些属性

这时候可以通过Object.create(参数对象)进行改装

它会创建一个新的对象 它的__proto__会指向传入的参数对象

👉Return Top👆

说一下es6新增的特性

👉Return Top👆

async/await是什么

async test() {
	let res = await login()
}

async/await是es8新增的 是基于promise的

async用于声明一个异步函数 它会将一个常规函数转为promise 返回值也是一个promise对象

await用于等待异步的功能执行完毕 会强制async函数中的代码等待 直到promise完成并返回结果

相对于promise async/await的优势

👉Return Top👆

说一下promise

const promise = new Promise((resolve, reject) => {
  // some code
})

通过Promise构造函数创建一个promise实例

这个实例接受一个函数作为参数 其中这个函数的两个参数分别为resolve和reject函数

resolve函数是将promise的状态从未完成变为成功

reject函数是将promise的状态从未完成变为失败

然后我们可以通过.then方法分别指向resolved和rejected的回调函数

promise.then((value) => {
  // success
}, (err) => {
  // fail
})

Promise对象有两个特点

  1. 对象的状态不受外界影响
  2. 一旦状态改变就不会再变 任何时候都可以得到这个结果

Promise也有一些缺点

  1. 无法取消promise 一旦新建就会立刻执行 无法中途取消
  2. 如果不设置回调 内部抛出的错误 不会反应到外部

👉Return Top👆

说一下promise的all方法

Promise.all()方法用于将多个promise实例包装成一个新的promise实例

// 接受一个数组作为参数
const p = Promise.all([p1, p2, p3])

p的状态由数组中的promise实例决定的 分为两种情况

resolved情况

只有数组中的promise实例都为resolved p的状态才是resolved

此时数组中的promise实例的返回值会组成一个数组 传递给p的回调函数

rejected情况

如果数组中的promise实例有一个被rejected了 p的状态就为rejected

此时第一个被rejected的实例的返回值 会传递给p的回调函数

👉Return Top👆

浏览器存储方式的应用场景

👉Return Top👆

浏览器存储方式的区别

是否发送给服务器

cookie数据始终在同源的http请求中携带(即使不需要) 也就是cookie在浏览器和服务器间来回传递

sessionStorage和localStorage不会自动把数据发送给服务器 仅在本地保存

存储大小限制

cookie数据不能超过4K

sessionStorage和localStorage可以达到5M

数据有效期

cookie只在设置的过期时间之前有效 即使窗口或者浏览器关闭

sessionStorage只在当前浏览器窗口关闭之前有效

localStorage始终有效 即使窗口或浏览器关闭也一直保存 可以做数据持久化

作用域

localstorage和cookie在所有同源窗口中都是共享的

sessionStorage不在不同的窗口中共享 即使是同一个页面

👉Return Top👆

jq中each和js中forEach的区别

遍历数组

    let arr = [1, 8, 5, 6, 9]
    let res = arr.forEach((ele, index) => {
      console.log(ele, index);
    })
    console.log(res); /* undefined 没有返回值 */
    let arr = [1, 8, 5, 6, 9]
    let res = $.each(arr, (index, ele) => {
      console.log(index, ele);
    })
    console.log(res); /* 被遍历的数组 */

原生回调参数是(ele, index) jq是(index, ele)

原生没有返回值 jq是被遍历的数组

遍历对象

    let obj = {name: 'demo', age: 18, gender: 'male'}
    for(let key in obj) {
      console.log(key, obj[key]);
    }
    let obj = {name: 'demo', age: 18, gender: 'male'}
    $.each(obj, (key, value) => {
      console.log(key, value);
    })

原生通过for-in遍历对象 jq可以通过each遍历对象

👉Return Top👆

说一下你对this的理解

this是一个在运行时才会进行绑定的引用,在不同的情况下它可能会被绑定不同的对象

  1. 函数调用模式fn()
  2. 方法调用模式obj.fn()
  3. 上下文调用模式(想让this指向谁就指向谁)
  4. 构造函数模式(使用new创建对象时也会进行this绑定)
  5. 箭头函数的this(不能被new给调用)

函数调用模式fn()

默认被绑定到全局对象中 也就是window

如果是nodejs就是global对象

如果开启严格模式的话 this为undefined

方法调用模式obj.fn()

谁调用绑定谁 比如如果函数是对象发起的 这个this就绑定为对象

上下文调用模式

想让this指向谁就指向谁

有三种方式

call()方法第一个参数为this 其他为实参列表

非严格模式下 指定null/undefined的话 会替换为全局对象window 原始值会被包装

apply()方法和call()方法差不多 它们的区别是

call()方法接受的是一个参数列表 而apply()方法接受的是一个包含多个参数的数组(也可以是伪数组)

bind()方法不调用函数 它会创建并返回一个新的函数

新的函数和借用的函数是一模一样的

但是新函数内的this已经被改变成了bind的参数

构造函数模式

当使用new调用构造函数的时候 会创建一个新的对象

这个新的对象的this就指向构造函数

箭头函数的this

箭头函数不同于传统函数,它没有自己的this

它的this是捕获外层上下文的this值作为自己的this值

并且由于箭头函数没有属于自己的this,它是不能被new调用的

👉Return Top👆

用递归实现数组长度为5且元素的随机数在2-32间不重复的值

let arr = new Array(5);
let num = randomNumber();
let i = 0;
// 执行函数
randomArr(arr, num);

// 获取随机数组
function randomArr(arr, num) {
  // 如果这个元素不存在 就存进数组中
	if (arr.indexOf(num) < 0) {
		arr[i] = num;
		i++;
	} else {
    // 再次获取随机数
		num = randomNumber();
	}
  // 如果达到数组的长度了 就输出数组 return掉
	if (i >= arr.length) {
		console.log(arr);
		return;
	} else {
    // 再次获取随机数组
		randomArr(arr, num);
	}
}

// 获取随机数
function randomNumber() {
  // +2 从2开始找元素 向下取整避免跑出32
	return Math.floor(Math.random() * 31 + 2);
}

👉Return Top👆

如何去掉字符串中的空格

let str = ' 1 2 345 6    ';
console.log(str.split(' ').join('')); /* 123456 */

👉Return Top👆

删除字符串中最后一个字符

function trim(str) {
	if (typeof str === 'string') {
		let trimStr = str.substring(0, str.length - 1);
		return trimStr;
	}
}

console.log(trim('essdgdg')); /* essdgd */

👉Return Top👆

写一个方法把下划线命名转成驼峰命名

function toCamelCase(str) {
	if (typeof str !== 'string') {
		return str;
	}
	const demo = str
		.split('_')
		.map((item) => item[0].toUpperCase() + item.substr(1))
		.join('');
	return demo[0].toLowerCase() + demo.substr(1);
}

let testStr = 'if_you_are_my_world';
console.log(toCamelCase(testStr)); /* ifYouAreMyWorld */

👉Return Top👆

JavaScript的回收机制

JS中内存的分配和回收都是自动完成的 在内存不使用的时候会被垃圾回收器自动回收

被分配的内存 一般有如下的生命周期

  1. 内存分配: 当我们声明变量/函数/对象的时候 系统会自动分配内存
  2. 内存使用: 即读写内存 也就是使用变量/函数等等
  3. 内存回收: 系统会自动回收不再使用的内存 全局变量一般不会被回收

👉Return Top👆

造成内存泄漏的操作有哪些

  1. 闭包
  2. 递归
  3. 死循环
  4. 没有使用的全局变量
  5. setInterval(定时器)没有被清除

👉Return Top👆

子函数在作用域内会不会被释放

不会 这是闭包的缺点 会造成内存泄漏

👉Return Top👆

window对象和document对象有什么区别

window对象

代表浏览器中的一个打开的窗口或者框架

window对象会在每次出现的时候被自动创建

所有的表达式都在当前的环境中计算,要引用当前窗口不需要特殊的语法,可以把当前窗口属性作为全局变量使用,例如

可以只写document,而不必写window.document

同样可以把窗口对象的方法当做函数来使用,如:只写alert(),而不必写window.alert

window对象实现了核心JavaScript所定义的全局属性和方法

document对象

代表整个HTML文档,可以用来访问页面中的所有元素

每一个载入浏览器的HTML文档都会解析为document对象

document对象可以让我们通过js对HTML页面中的所有元素进行访问

document对象是window对象的一部分 可以通过window.document属性对其进行访问

👉Return Top👆

写一个获取数组的最大最小值的方法

let demo = [25, 62, 91, 78, 34, 62];
let max_res = Math.max.apply(this, demo);
let min_res = Math.min.apply(this, demo);
console.log(max_res); /* 91 */
console.log(min_res); /* 25 */
// 用this和Array都是全等的
console.log(Math.min.apply(this, demo) === Math.min.apply(Array, demo)); /* true */

👉Return Top👆

如何删除对象的a属性

let obj = { a: 0, b: 1 };
delete obj.a;
console.log(obj);

👉Return Top👆

说一下常用的数组方法

  1. push(更新数组)
  2. map(返回每个元素调用函数后的返回值)
  3. sort(排序数组)
  4. splice(指定索引添加/删除元素)
  5. forEach(遍历数组)
  6. shift(删除第一个元素)
  7. pop(删除最后一个元素)
  8. includes(判断是否存在指定值)
  9. indexOf(返回指定值的第一个索引 不存在返回-1)

👉Return Top👆

typeof的返回值

一共七种

  1. number
  2. string
  3. boolean
  4. undefined
  5. symbol
  6. object
  7. function

一些细节

👉Return Top👆

说一下null和undefined的区别

null只有一个值 就是null 它表示空值

null的典型用法

  1. 作为函数的参数,表示该函数的参数不是对象
  2. 作为对象原型链的终点

undefined也是只有一个值 就是undefined 它表示已经定义但未赋值

undefined的典型用法

  1. 调用函数时,应该提供的参数没有提供,该参数等于undefined
  2. 变量被声明了,但没有赋值时,就等于undefined
  3. 对象没有赋值的属性,该属性的值为undefined
  4. 函数没有返回值时,默认返回undefined

👉Return Top👆

说一下js的数据类型

六种基本类型 三种引用类型 其中symbol属于es6的

基本类型

  1. number
  2. string
  3. boolean
  4. undefined
  5. null
  6. symbol

引用类型

  1. object
  2. function
  3. array

👉Return Top👆

浅拷贝和深拷贝的区别及如何实现深拷贝

区别在于是否开辟了一个新的地址

公用一个地址就是浅拷贝 否则就是深拷贝

可以通过浅拷贝+递归实现深拷贝

浅拷贝时判断属性值是否是对象

如果是对象就进行递归操作

这样就实现了深拷贝

👉Return Top👆

请用一行代码实现深拷贝

let demo = JSON.parse(JSON.stringify(obj))

👉Return Top👆

适合用事件委托的事件有哪些

👉Return Top👆

什么是事件委托

事件委托是利用事件的冒泡原理来实现的

优点

缺点

👉Return Top👆

什么是冒泡事件

在一个按钮中绑定一个click事件 它会依次在父元素中被触发

👉Return Top👆

如何取消默认事件

通过e.preventDefault()

👉Return Top👆

如何防止冒泡和捕获事件

通过e.stopPropagation()

👉Return Top👆

说一下js有哪些内置对象

👉Return Top👆

说一下原型对象

每个函数都有一个prototype属性 指向它的原型对象

基于构造函数创建的实例 可以访问它的原型对象上的方法

比如toString是Object原型对象上的方法 可以被任何实例作为自己的方法进行调用

实例在调用属性和方法的时候 优先调用自己的

如果自己没有就找原型的 原型没有就找原型的原型 直到原型顶端Object.protototype(原型链的顶端)

hasOwnProperty就是用来判断某个属性是不是自己的

👉Return Top👆

说一下原型链

每个对象都有一个__proto__属性 指向它的构造函数的原型

对象可以通过__proto__属性和构造函数的原型对象进行连接

然后构造函数的原型对象也有__proto__属性

这样就形成了链式结构 我们称之为原型链

👉Return Top👆

说一下作用域链

函数内部可以访问到外部变量

外部函数可以访问到全局变量

这样形成的变量作用域链式结构 被称为作用域链

👉Return Top👆

toString和valueOf的区别

对象的两个方法 Object.protototype

toString() 返回对象的字符串表示 valueOf() 返回对象的字符串/数值或布尔值表示(其实就是返回自身)

toString()在对象的时候 就变成”[object Object]”

表示数组的时候 就变成数组内容以逗号连接的字符串 相当于Array.join(‘,’)

let arr = [1, 2, 3].toString();
let obj = { a: 1 }.toString();
console.log(arr); /* 1,2,3 */
console.log(obj); /* [object Object] */

valueOf的优先级比toString高

👉Return Top👆

Object是在堆还是栈里面

堆里面

栈内存主要用于存储各种基本类型的变量 比如Boolean/Number/String/Undefined/Null

堆内存主要负责像对象Object这种变量类型的存储

👉Return Top👆

垃圾回收的两种方法

垃圾回收

核心思想就是如何判断内存是否已经不再会被使用了

如果是 就视为垃圾释放掉

引用计数法

定义“内存不再使用”的标准很简单

就是看一个对象是否有指向它的引用

如果没有任何变量指向它了 说明该对象已经不再需要了

标记清除法

标记清除算法将“不再使用的对象”定义为“无法达到的对象”

👉Return Top👆

说一下闭包

闭包是一个函数嵌套另一个函数

优点可以防止全局变量污染

缺点会造成内存泄漏

闭包最大的作用就是用来变量私有

👉Return Top👆


vue小分队🍖

组件通信的几种方式

  1. props/$emit
  2. $emit/$on
  3. vuex
  4. $parent/$children/$refs
  5. provide/inject

👉Return Top👆

如何理解vue的响应式系统

任何component都会有一个与之对应的watcher实例

vue的data上的属性都会被添加getter/setter属性

当vue component render函数被执行的时候 data会被touch(即读写) getter方法就会被调用 此时vue会去记录此vue component所依赖的所有data(这个过程被称为依赖收集)

当data被改动(主要是用户操作) setter方法就会被调用 vue会去通知所有依赖此data的组件调用他们的render函数进行更新

👉Return Top👆

keep-alive的作用

keep-alive主要用于缓存不活动的组件实例 保留组件的状态 避免被重新渲染导致的性能问题

当组件在keep-alive内被切换 组件的activated/deactivated这两个生命周期会被执行

组件一旦被缓存 再次渲染就不会执行created/mounted生命周期

要求同时只有一个子组件被渲染

👉Return Top👆

vue组件中的data为什么一定是函数

如果data是一个函数的话 每次复用一次组件 就会返回一份新的data

类似于给每个组件实例创建一个私有的数据空间 让各个组件实例都去维护自己的数据

如果单纯的写成对象的形式 会导致所有组件共享一份data 会造成一个变全部变的结果

所以就规定了vue的data必须是函数

这是js的特性 跟vue本身设计无关

js本身也是基于原型链和构造函数的 原型链上一般都是添加函数方法而非对象

👉Return Top👆

说一下vue的生命周期

常规8个 其实11个

然后我们常用的生命周期是created/mounted

如果是请求一些数据 可以把方法放在created中

如果要操作dom的话 需要把方法放在mounted中

异步请求可以在created/mounted 具体看是否需要操作dom

第一次页面加载的时候会触发beforeCreate/created/beforeMount/mounted这几个生命周期

👉Return Top👆

说一下自定义指令

自定义指令分为局部和全局 一般全局使用

// 全局自定义指令
Vue.directive('color', {
  bind(el,binding) {
    el.style.color = binding.value
  },
  update(el,binding) {
    el.style.color = binding.value
  }
})

其中bind是在第一次绑定到元素时调用 update是在每次更新DOM的时候调用

如果两者的逻辑都一样 可以通过function函数简写

// 简写形式
Vue.directive('color', function(el, binding) {
  el.style.color = binding.value
})

局部指令写法

	directives: {
    // 简写形式
		color(el, binding) {
			el.style.color = binding.value
		}

    // 常规写法
		color: {
			bind(el, binding) {
				el.style.color = binding.value
			},
			update(el, binding) {
				el.style.color = binding.value
			}
		}
	}

👉Return Top👆

什么是MVVM

model层 通过ajax/fetch完成客户端和服务端的业务模型同步

view层 作为视图模板的存在

viewmodel层 负责暴露数据给view层

对view层的(指令声明/事件绑定声明/数据绑定声明)进行实际业务的实现

viewmodel的底层会监听object.defineproperty 当数据变化的时候 view层自动更新

vue的实例就是属于viewmodel

👉Return Top👆

vue中的key有什么作用

key的主要作用是为了高效更新虚拟DOM

通过这个key 我们的diff操作可以更加准确快速

👉Return Top👆

vue同时使用v-for和v-if哪个先调用

当v-if和v-for一起使用的时候 v-for的优先级会更高

官方是不建议同时使用的 如果同时使用的话 每次v-for都会执行v-if 会造成不必要的计算 浪费性能

可以通过computed计算属性过滤掉不需要显示的item

computed: {
  items() {
    return this.list.filter(item => item.isShow)
  }
}

或者通过外层嵌套template 在这层中进行v-if判断 然后再进行内部v-for循环

<template v-if="isShow">
  <p v-for="item in list">
</template>

👉Return Top👆

v-show和v-if的区别

两者都是用来显示隐藏元素的

不同的是

  1. v-if是通过销毁和重建DOM让元素显示隐藏的
  2. v-show是通过修改display属性让元素显示隐藏的
  3. v-if有更高的切换开销 而v-show是有更高的首次渲染开销
  4. v-if有配套的v-if-else和v-else v-show没有

👉Return Top👆

为什么要替换defineProperty

因为defineProperty无法对数组对象进行深度监听

defineProperty只能响应首次渲染时候的属性 后面添加的属性是不会渲染的

proxy可以直接监听数组/对象的变化而非属性

proxy返回的是一个新的对象 我们可以直接操作新的对象就可以达到目的 而defineProperty只能遍历对象的属性进行修改

而且proxy的配置项有13种 可以做更细致的事情 这是defineProperty做不到的

defineProperty的优势就是兼容性好 可以支持ie9

👉Return Top👆

vue3和vue2的区别

  1. setup代替了之前的beforeCreate和created
  2. proxy代替Object.defineProperty(vue2的双向绑定的核心)
  3. diff算法的提升
  4. typeScript的支持
  5. 打包体积的优化
  6. 使用自己的构建工具vite

👉Return Top👆

虚拟dom的优劣

  1. 保证性能下限
  2. 无需手动操作DOM
  3. 跨平台
  4. 无法进行极致优化

保证性能下限 虚拟DOM可以经过diff找出最小差异,然后批量进行patch,这种操作虽然比不上手动优化,但是比起粗暴的DOM操作性能要好很多,因此虚拟DOM可以保证性能下限

无需手动操作DOM 虚拟DOM的diff和patch都是在一次更新中自动进行的,我们无需手动操作DOM,极大提高开发效率

跨平台 虚拟DOM本质上是JavaScript对象,而DOM与平台强相关,相比之下虚拟DOM可以进行更方便地跨平台操作,例如服务器渲染、移动端开发等等

无法进行极致优化 在一些性能要求极高的应用中虚拟DOM无法进行针对性的极致优化

👉Return Top👆

虚拟dom的实现原理

  1. 虚拟DOM本质上是JavaScript对象,是对真实DOM的抽象
  2. 状态变更时,记录新树和旧树的差异
  3. 最后把差异更新到真正的dom中

👉Return Top👆

说一下双向绑定的原理

利用Object.defineProperty劫持对象的访问器

当属性值发生变化的时候 我们获取变化进行后续的操作

vue3通过proxy进行类似的操作

👉Return Top👆


小程序小分队👻

说一下小程序的支付流程

  1. 获取用户的token
  2. 创建订单
  3. 获取预支付参数
  4. 发起微信支付

用户的token需要五个参数

其中code通过wx.login()获取 其他通过wx.getUserProfile()获取

然后就可以创建订单了 订单需要请求头和请求体参数

这时候就可以通过订单编号获取预支付参数(五个参数)

然后通过wx.requestPayment()传入预支付参数 就可以发起微信支付了

👉Return Top👆

小程序怎么实现双向绑定

通过bindinput属性

小程序是单向数据流 我们可以通过bindinput属性来实现双向数据绑定

  1. 在bindinput属性中定义个方法
  2. 在data中定义个message
  3. 通过e.detail.value获取用户输入的值
  4. 然后通过this.setData()更新数据
<text>这是用来显示文本的:</text>
<input bindinput="getMessage" placeholder="这是输入框" />
  data: {
    message: ''
  },
  getMessage(e) {
    let message = e.detail.value
    this.setData({
      message
    })
  },

👉Return Top👆

bindtap和catchtap的区别

bindtap不能阻止事件冒泡 catchtap可以

👉Return Top👆

小程序的本地存储和web的区别

小程序是通过这两个方法进行缓存获取数据的

web是通过这两个方法

web不管存入什么类型的数据都会通过toString()变成字符串存储

小程序不存在什么类型转换 存放什么类型的数据 获取的时候就是什么类型的数据

👉Return Top👆

setData和data的区别

this.setData()用于将数据从逻辑层发送到视图层 同时改变对应的this.data的值

用this.data会造成页面内容不更新的问题

👉Return Top👆

open-type的作用

用于获取手机号/客服/用户信息等等

👉Return Top👆

如何获取用户信息

通过wx.getUserProfile()获取

原来是通过open-type=”getUserInfo” 然后数据在e.detail里面

👉Return Top👆

如何授权登录

通过code和第三方服务器进行注册登录

code通过wx.login()获取

用户信息通过wx.getUserProfile()获取 数据在res里面

然后通过wx.setStorageSync()缓存用户信息

wx.getStorageSync()进行获取用户信息

this.setData()更新数据

👉Return Top👆


http协议小分队🌐

协议和域名不同的情况是否同域

不同的

同域的要求是 请求地址中的协议/域名及端口号都相同

只要有一个不相同就是跨域

👉Return Top👆

浏览器输入url后发生了什么

  1. DNS解析
  2. TCP连接
  3. 发送HTTP请求
  4. 服务器处理请求 并返回HTTP报文
  5. 浏览器解析渲染页面
  6. 连接结束

👉Return Top👆

说一下跨域及如何解决跨域

跨域是浏览器的同源策略造成的

有三种解决方案

常用的是cors 只需要后端四行代码就可以搞定

jsonp的话 只是加它并不能处理跨域问题 因为它不能post请求

proxy是在项目开发的时候使用 上线了一般接口和项目都是在同一个服务器 也就不存在跨域问题了

👉Return Top👆

说一下你知道的状态码

状态码主要分为5种类型

常见的状态码

👉Return Top👆


其他小分队🔫

常用的五个网站

  1. GitHub
  2. MDN中文网
  3. 掘金
  4. 相关技术官网文档
  5. 哔哩哔哩

👉Return Top👆


end