自己整理的面试笔记(仅供参考 , 有错误请大家多多指教 , 谢谢)

javaScript,jQuery,vue的区别:

1.javaScript是运行在浏览器端的脚步语言,JavaScript主要解决的是前端与用户交互的问题,包括使用交互与数据交互,JavaScript是浏览器解释执行的。

2.jQuery就是javascript中的一个函数库,一个js文件,是把js中比较复杂的东西封装成一个库,能够让人们在开发过程中尽可能的少写多做。

3.Vue.js可以作为一个js库来使用,也可以用它全套的工具来构建系统界面,这些可以根据项目的需要灵活选择,所以说,Vue.js是一套构建用户界面的渐进式框架。Vue的核心库只关注视图层,Vue的目标是通过尽可能简单的 API 实现响应的数据绑定,在这一点上Vue.js类似于后台的模板语言。其本质上来说也是js代码总结:1.js,jQuery首先都要获取到DOM对象,然后对DOM对象进行进行值的修改等操作2.Vue是首先把值和js对象进行绑定,然后修改js对象的值,Vue框架就会自动把DOM的值就行更新。也可以简单的理解为Vue帮我们做了dom操作,我们以后用Vue就需要修改对象的值和做好元素和对象的绑定,Vue这个框架就会自动帮我们做好dom的相关操作

jQuery只是一个类库,提供了很多的方法,但不能算框架,而vue.js是一个框架,有一套完整的体系。所以Vue的优势比jQ大很多,工作中大多数也是采用Vue框架来编写的

javaScript有三种数据存储方式,分别是:

  • sessionStorage
  • localStorage
  • cookie

sessionStorage:将数据保存在session对象中。所谓session,是指用户在浏览某个网站时,从进入网站到浏览器关闭所经过的这段时间,也就是用户浏览这个网站所花费的时间。session对象可以用来保存在这段时间内所要求保存的任何数据。

localStorage:将数据保存在客户端本地的硬件设备(通常指硬盘,也可以是其他硬件设备)中,即使浏览器被关闭了,该数据仍然存在,下次打开浏览器访问网站时仍然可以继续使用。

而Cookie 是存储在客户端的一段数据,但是不同的浏览器存储 Cookie 的地方不同:

  • 一种是将 Cookie 数据保存在文件中;
  • 另一种是保存在浏览器内存中。

vue项目的优化分为三部分:

Vue 代码层面的优化webpack 配置层面的优化Web 技术层面的优化一、代码层面的优化1 v-for 遍历为 item 添加 key在列表数据进行遍历渲染时,需要为每一项 item 设置唯一 key 值,方便 Vue.js 内部机制精准找到该条列表数据。

2 v-for 遍历避免同时使用 v-ifv-for 比 v-if 优先级高,这意味着 v-if 将分别重复运行于每个 v-for 循环中,将会影响速度。建议替换成 computed 属性。

3 v-if 和 v-show 区分使用场景v-if 是真正的条件渲染,也是惰性的:如果在初始渲染时条件为假,则什么也不做,直到条件第一次变为真时,才会开始渲染条件块。v-show 就简单得多,不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 的 display 属性进行样式切换。v-if 适用于很少改变条件,不需要频繁切换的场景;v-show 则适用于需要非常频繁切换的场景。

4 computed 和 watch 区分使用场景computed 计算属性,依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值;watch 更多的是观察的作用,每当监听的数据变化时都会执行相关回调。

当需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算;当需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,watch 允许我们执行异步操作。

5 keep-alive利用keep-alive包裹,将不活动的组件缓存起来。在组件切换过程中将状态保留在内存中,防止重复渲染dom,减少加载时间及性能消耗,提高用户体验。

6 图片资源懒加载(使用插件)对于图片过多的页面,为了加快页面加载速度,可以将页面内未出现在可视区域内的图片先不做加载, 等到滚动到可视区域后再去加载。这样对于页面加载性能上会有很大的提升,也提高了用户体验。我们在项目中使用 Vue 的 vue-lazyload 插件。

7 路由懒加载路由过多,加载的资源过多,页面会出现白屏的情况,不利于用户体验。所以我们把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应的组件:

在 vue-router 配置路由的时候,采用动态加载路由的形式:

routes:[ path: 'Blogs', name: 'ShowBlogs', component: () => import('./components/ShowBlogs.vue')]以这种函数的形式加载路由,这样就可以把各自的路由文件分别打包,只有在解析给定的路由时,才会加载路由组件。

8 第三方库按需引入在日常使用UI框架,例如element-UI、iView,我们经常性直接引用整个UI库。但实际上我用到的组件只有按钮,分页,表格等很少一部分,所以我们要按需引用:

import { Button, Input, Pagination } from 'element-ui';Vue.use(Button)Vue.use(Input)Vue.use(Pagination)二、Webpack 层面的优化1 Webpack 对图片进行压缩对有些较大的图片资源,在请求资源的时候,加载会很慢,我们可以用 image-webpack-loader 来压缩图片

2 模板预编译打包时,直接把组件中的模板转换为render函数,这叫做模板预编译。这样一来,运行时就不再需要编译模板了,提高了运行效率。

三、基础的 Web 技术优化1 浏览器缓存为了提高用户加载页面的速度,对静态资源进行缓存是非常必要的。

v-model双向数据绑定的实现原理

双向数据绑定最核心的方法就是通过object.defineProperty()来实现对属性的劫持,达到监听数据变动的目的,先是从data里的数据msg通过绑定到input 控件和p标签上,然后input上通过v-on:input监听控件,出发change(),调用方法都可以默认获取e事件 , e.targrt.value是获取调用该方法的dom对象的value值,吧value值再赋值给data 里的msg,就实现了双向数据绑定的原理.

js事件循环机制

  • 事件循环的理解

JS是单线程的语言,优点:简单、清晰,无死锁。

但是必须制定详尽的、合理的运行规则才能保证单线程更好的运行。

主线程、执行栈、执行线程、消息队列。

主线程:解析代码,声明变量、声明函数(幼儿园小王老师)

主线程解析完成代码后,将代码分成同步任务和异步任务。(检出其他的品种///)

执行栈:专门执行代码 (小朋友)

主线程分完任务后交由执行线程就会将同步任务放入到执行栈里运行,执行的过程中,会有异步的任务,会推入到消息队列,消息队列的代码会等到执行栈里面的任务执行完成后才会执行

当执行栈清空或者消息队列中有新的任务进入的时候, 都会触发一次检查机制,检查执行栈是否没有其他的同步任务要执行了,如果没有了,就会执行消息队列中的任务,这就是一次事件循环。

这些同步的代码,可以分为宏任务和微任务,一个宏任务可能会伴随几个微任务,执行的时候,会先执行宏任务,然后执行这个宏任务所伴随的微任务,然后再去执行下一个宏任务。

  • 宏任务:setTimeout,setInterval,Ajax,DOM事件
  • 微任务:Promise,async/await

setTimeout(function () { // 宏任务 }) new Promise((resolve) => { // 宏任务 resolve() }).then(() => { // 微任务 })

// 位置 1 setTimeout(function () { console.log('timeout1'); }, 1000); ​ // 位置 2 console.log('start'); ​ // 位置 3 Promise.resolve().then(function () { // 位置 5 console.log('promise1'); // 位置 6 Promise.resolve().then(function () { console.log('promise2'); }); // 位置 7 setTimeout(function () { // 位置 8 Promise.resolve().then(function () { console.log('promise3'); }); // 位置 9 console.log('timeout2') }, 0); }); ​ // 位置 4 console.log('done'); ​ // start // done // promise1 // promise2 // timeout2 // promise3 // timeout1

new Promise(resolve => { console.log('promise'); resolve(5); }).then(value=>{ console.log('then回调', value) }) function func1() { console.log('func1'); } setTimeout(() => { console.log('setTimeout'); }); func1() ​ // promise // func 1 // then回调 5 // setTimeout ​ ​

  • 发布订阅模式

理解

  • 宏任务和微任务
  • 防抖节流相关
  • 数组的内置方法(返回值)

Vue组件通信

  1. 父子组件通信
    1. 父组件传入数据到子组件中, 子组件当做属性props来接受然后使用(不能更改,违背单向数据流)
    1. 父组件将方法传递给子组件,子组件当做属性props来接受,子组件可以通过调用这个方法,通知父组件执行逻辑
    1. 父组件可以给子组件绑定一个事件,事件的处理程序是父组件自己的方法,子组件可以通过触发被绑定的这个事件,从而通知父组件执行逻辑
    1. 父组件可以利用ref来为组件做标记,从而获取到子组件的实例,然后就可以使用子组件的数据、调用子组件的方法(不推荐)
  1. 兄弟组件通信

1.事件总线bus

2.vuex

  1. 跨组件传递
    1. provide inject vue2.0里因为传递的数据不是响应的,所以基本不使用, 但是在3.0里可以传递响应的数据了,使用的场景多了
    1. 事件总线bus
    1. vuex
  1. 状态共享
    1. vuex
  • JSX原理

盒子实现居中

1.定位

2.外边距:margin-left:值;

margin-top:值;

3.margin:auto(不兼容低版本ie浏览器)

4.弹性盒模型:display:flex;

justify-content:conter;

align-items:center;

5.用transform属性translate平移

6.calc计算

7.display:table-cell;

axios二次封装

闭包的使用场景

1.setTimeout

2.回调 , 代码作为一个回调绑定事件

3.封装私有变量

4.函数防抖

闭包的使用场景_gong_colin的博客-CSDN博客_闭包的使用场景..%2522%257D&request_id=166367676216800186583255&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1

watch和watcheffect的区别

Vue —— watch和watchEffect的区别_甜甜酷盖的博客-CSDN博客_watch和watcheffect的区别..%2522%257D&request_id=166367701316782417035336&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_click~d

在vue中组件通信的方式:

1.父子组件:porps + $emit()

2.兄弟组件:eventbus(事件总线bus , 使用一个空的vue实例作为事件总线 , 自定义事件event.$on event.$emit)

3.大范围数据共用:vuex

4.子代组件:provide + inject (依赖注入)

6.自定义传值:v-model

  1. 兄弟组件通信

1.事件总线bus

2.vuex

  1. 跨组件传递
    1. provide inject vue2.0里因为传递的数据不是响应的,所以基本不使用, 但是在3.0里可以传递响应的数据了,使用的场景多了
    1. 事件总线bus
    1. vuex

spa单页应用

单页应用与多页应用的区别

单页应用优缺点

优点:

具有桌面应用的即时性、网站的可移植性和可访问性

用户体验好、快,内容的改变不需要重新加载整个页面

良好的前后端分离,分工更明确

缺点:

不利于搜索引擎的抓取

首次渲染速度相对较慢

面试官:说说你对SPA(单页应用)的理解?_动感超人,的博客-CSDN博客..%2522%257D&request_id=166367864516782428668325&biz_id=0&utm_medium=distribute.

跨域

什么是跨域?跨域解决方法_@Demi的博客-CSDN博客_什么是跨域..%2522%257D&request_id=166367880416782428682016&biz_id=0&utm_medium=distribute.pc_search_resul

vuex的五大属性和使用方法----包括辅助函数

vuex的五大属性和使用方法----包括辅助函数_学后端的小萝卜头的博客-CSDN博客^v48^new_blog_pos_by_title,201^v3^control_2&spm=1018.2226.3001.4187

vue中使用vuex(超详细)

组件派发任务到actions , actions出发mutions中的方法 , mutions改变state中的数据 , 数据变更后响应推送给组件,组件从新渲染

vue中使用vuex(超详细)_坏丶毛病的博客-CSDN博客_vue使用vuex

箭头函数与普通函数的区别

箭头函数 不可以当作构造函数, 所以不能使用new命令 ,

箭头函数不能使用arguments对象

箭头函数本身没有this , this指向父级

箭头函数不能使用yield命令 , 因此箭头函数不能用作generator函数

箭头函数不能使用call()和apply()调用

promise 的方法

https://blog.csdn.net/qq_37974755/article/details/12364263

1.为什么v-for 要用key

2.vue组件生命周期

3.vue组件跨级通信

4.移动端适配(rem , em , viewport)

5.vue2/3响应式原理(object.defineProperty 缺点)

6.$nextTick

7.vue如何解决跨域

8.回流和重绘

9.盒模型

10.BFC

11.解决display:inline-block后产生空袭问题:

(1 )给li的父元素 设置 display:table;即可(最优解决) (2)是给li添加浮动元素 float:left (3 )给父元素设置font-size:0 子元素再设置正确的大小

12.js数据类型

13.js判断数据类型的方法

14.null和undefined区别

15.new一个对象的过程中发生了什么

16.原型和原型链

17.一个函数a和一个函数b , a继承b(组合继承)

18.promise和async awite区别

19.jsonp原理

20.js事件循环机制

21.箭头函数和普通函数的区别

22.promise.all中如果有一个如果有一个状态变成了 rejected, 其他的 promise的状态都达到 resolved的时候 , 怎么返回一个resolved

23.三个宏任务两个微任务从上到下排列 , 两个微任务在在第一个宏任务里, 怎么运行?

24.两个等号和三个等号区别

25.cookie和session的区别

两者的区别:在安全和性能方面考虑

1、cookie数据存放在客户端,session数据放在服务器上。

2、cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑到安全应当使用session。

3、session会在一定时间内保存在服务器上,当访问增多,会比较占用你服务器的性能,考虑性能应当使用cookie。

4、不同浏览器对cookie的数据大小限制不同,个数限制也不相同。单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。

5、可以考虑将登陆信息等重要信息存放为session,不重要的信息可以放在cookie中。

26.defer与async的区别是:

前者要等到整个页面正常渲染结束,才会执行;后者一旦下载完,渲染引擎就会中断渲染,执行这个脚本以后,再继续渲染。一句话,defer是“渲染完再执行”,async是“下载完就执行”。另外,如果有多个defer脚本,会按照它们在页面出现的顺序加载,而多个async脚本是不能保证加载顺序的。

1.手写轮播图

2.vue 打包的方式

vue 打包的方式_usmile.的博客-CSDN博客_vue打包

原型和原型链的理解:(面试题)

原型:每个函数都有 prototype 属性,该属性指向原型对象;使用原型对象的好处是所有对象实例共享它所包含的属性和方法。原型链:主要解决了继承的问题;每个对象都拥有一个原型对象,通过proto 指针指向其原型对象,并从中继承方法和属性,同时原型对象也可能拥有原型,这样一层一层,最终指向 null。

深拷贝(四种方法)

为什么要使用深拷贝?

我们希望在改变新的数组(对象)的时候,不改变原数组(对象)

如何进行深拷贝(四种方法)

1、使用JSON.stringify()以及JSON.parse()

2、通过for in实现

3、递归 (自身调用自身)

4.concat(数组的深拷贝)

使用concat合并数组,会返回一个新的数组。对象是一个引用数据类型 普通的复制是一个浅拷贝

排序:冒泡排序 选择排序 快速排序 去重 扁平化

冒泡排序

外层 n个单元 循环n-1次 完成排序 最后一个单元 已经排序好了 没有比较判断的其他单元 0 至 数组.length-1-1 循环 内层 每次循环 从 第一个单元 循环至 本子需要循环单元的 倒数第二个 循环至 最后一个单元 没有 下一个单元 比较判断 上一次循环比较 存储到数组末位的最大值 不用参与下一次循环比较 也就是 第一次 少 比较判断 0 个单元 也就是 第二次 少 比较判断 1 个单元 也就是 第三次 少 比较判断 2 个单元

var arr = [5, 4, 3, 2, 1]; // 外层 0 至 arr.length-1-1 循环 for (var j = 0; j <= arr.length -1 -1; j++) { // 内层 0 至 arr.length-1-1-j for (var i = 0; i <= arr.length -1 -1 -j; i++) { if (arr[i] > arr[i + 1]) { var num = arr[i]; arr[i] = arr[i + 1]; arr[i + 1] = num; } } } console.log(arr);

选择排序

核心原理 1, 定义一个变量 存储 起始位置 索引下标 2, 循环遍历数组 从 起始位置的下一个单元 开始 循环至 数组的最后一个单元 如果 变量存储的索引下标 对应单元的数据数值 大于 循环单元 存储的数据数值 变量 存储 循环单元的索引下标 循环结束 变量中存储 当前所有循环单元 最小值 所在单元的索引下标 3, 比较判断 如果 变量 中 存储的不是 起始位置的索引下标 交换 变量储存索引下标 和 起始位置索引下标 对应单元 存储的数据数值 4, 多次循环 完成 整个数组数据的排序 算法优化 外层 n个单元 循环 n-1次 完成排序 arr.length -1 -1 内层 从 本次循环 起始位置的下一个单元开始循环 var i = index + 1

var arr = [100 , 23 , 25 , 30 , 36 , 80 , 50]; for( var j = 0 ; j <= arr.length - 1 - 1 ; j++){ var index = j ; for( var i = index + 1 ; i <= arr.length - 1 ; i++ ){ if( arr[index] > arr[i]){ index = i ; } } if( index !== j){ var res = arr[index] ; arr[index] = arr[j]; arr[j] = res; } } console.log( arr );

快速排序

思路:

1、选出一个key,一般是最左边或是最右边的。

2、定义一个begin和一个end,begin从左向右走,end从右向左走。(需要注意的是:若选择最左边的数据作为key,则需要end先走;若选择最右边的数据作为key,则需要bengin先走)。

3、在走的过程中,若end遇到小于key的数,则停下,begin开始走,直到begin遇到一个大于key的数时,将begin和right的内容交换,end再次开始走,如此进行下去,直到begin和end最终相遇,此时将相遇点的内容与key交换即可。(选取最左边的值作为key)

4.此时key的左边都是小于key的数,key的右边都是大于key的数

5.将key的左序列和右序列再次进行这种单趟排序,如此反复操作下去,直到左右序列只有一个数据,或是左右序列不存在时,便停止操作,此时此部分已有序

//快速排序法 挖坑法

void QuickSort1(int* arr, int begin, int end)

{

if (begin >= end)

return;

int left = begin,right = end;

int key = arr[begin];

while (begin < end)

{

//找小

while (arr[end] >= key && begin < end)

{

--end;

}

//小的放到左边的坑里

arr[begin] = arr[end];

//找大

while (arr[begin]

{

++begin;

}

//大的放到右边的坑里

arr[end] = arr[begin];

}

arr[begin] = key;

int keyi = begin;

//[left,keyi-1]keyi[keyi+1,right]

QuickSort1(arr, left, keyi - 1);

QuickSort1(arr, keyi + 1, right);

}

数组去重

数组去重的方法

一、利用ES6 Set去重(ES6中最常用)

不考虑兼容性,这种去重的方法代码最少。这种方法还无法去掉“{}”空对象,后面的高阶方法会添加去掉重复“{}”的方法。

二、利用for嵌套for,然后splice去重(ES5中最常用)

//NaN和{}没有去重,两个null直接消失了

双层循环,外层循环元素,内层循环时比较值。值相同时,则删去这个值。

想快速学习更多常用的ES6语法,可以看我之前的文章《学习ES6笔记──工作中常用到的ES6语法》。

3、利用indexOf去重

//NaN、{}没有去重

新建一个空的结果数组,for 循环原数组,判断结果数组是否存在当前元素,如果有相同的值则跳过,不相同则push进数组。

4、利用includes

5、利用filter

数组扁平化

1.二维数组时,可以简单使用flat()方法

let arr = [[1,2],[3,4],[5,6]].flat();

如果是多维数组,则flat()将达不到效果,

需要给flat()传一个参数,var newArray = arr.flat([depth]),

参数:depth ,可选,指定要提取嵌套数组的结构深度,默认值为 1。

2.迭代实现 (ES6扩展运算符...)

3.普通递归实现

4.高级递归(reduce方法)

5. toString()

该方法利用了 toString 把数组变成以逗号分隔的字符串,然后可通过遍历数组把每一项再变回原来的类型。

6.[].concat.apply

对象数组的排序

自定义指令

如何自定义指令

注册一个自定义指令有全局注册与局部注册

全局注册注册主要是用过Vue.directive方法进行注册

Vue.directive第一个参数是指令的名字(不需要写上v-前缀),第二个参数可以是对象数据,也可以是一个指令函数

局部注册通过在组件options选项中设置directive属性

应用场景

图片懒加载

设置一个v-lazy自定义组件完成图片懒加载

const LazyLoad = {

// install方法

install(Vue,options){

// 代替图片的loading图

let defaultSrc = options.default;

Vue.directive('lazy',{

bind(el,binding){

LazyLoad.init(el,binding.value,defaultSrc);

},

inserted(el){

// 兼容处理

if('InterpObserver' in window){

LazyLoad.observe(el);

}else{

LazyLoad.listenerScroll(el);

}

}, }) }, // 初始化 init(el,val,def){ // src 储存真实src el.setAttribute('src',val); // 设置src为loading图 el.setAttribute('src',def); }, // 利用InterpObserver监听el observe(el){ let io = new InterpObserver(entries => { let realSrc = el.dataset.src; if(entries[0].isIntersecting){ if(realSrc){ el.src = realSrc; el.removeAttribute('src'); } } }); io.observe(el); }, // 监听scroll事件 listenerScroll(el){ let handler = LazyLoad.throttle(LazyLoad.load,300); LazyLoad.load(el); window.addEventListener('scroll',() => { handler(el); }); }, // 加载真实图片 load(el){ let windowHeight = document.documentElement.clientHeight let elTop = el.getBoundingClientRect().top; let elBtm = el.getBoundingClientRect().bottom; let realSrc = el.dataset.src; if(elTop - windowHeight<0&&elBtm > 0){ if(realSrc){ el.src = realSrc; el.removeAttribute('src'); } } }, // 节流 throttle(fn,delay){ let timer; let prevTime; return function(...args){ let currTime = Date.now(); let context = this; if(!prevTime) prevTime = currTime; clearTimeout(timer); if(currTime - prevTime > delay){ prevTime = currTime; fn.apply(context,args); clearTimeout(timer); return; } timer = setTimeout(function(){ prevTime = Date.now(); timer = null; fn.apply(context,args); },delay); } }

}

export default LazyLoad;

HTTP

http协议 (1) 前端 后端 在进行数据交互时 遵守的 网络传输协议 (2) http 是 没有加密的网络传输协议 https 是 对传输内容进行加密的 网络传输协议 (3) 三次握手 通过 TCP/IP 协议 在 客户端和服务器正式创建网络链接之前 执行的代码程序 通过 三次握手 客户端 和 服务器 都 确认 客户端和服务器 都能正常工作 第一次 客户端 --- 服务器 客户端知道 客户端 可以 正常 发送 请求 服务器知道 客户端 可以 正常 发送 请求 服务器 可以 正常 接收 请求 第二次 服务器 --- 客户端 服务器知道 服务器 可以 正常 发送 请求 客户端知道 客户端 可以 正常 接收 请求 服务器 可以 正常 接收 请求 服务器 可以 正常 发送 请求 第三次 客户端 --- 服务器 服务器知道 客户端 可以 正常 接收 请求 (4) 四次挥手 通过 TCP/IP 协议 再 客户端 和 服务器正式断开连接之前 执行的程序 通过 四次挥手 确保 客户单和服务器都是正常的断开链接的 第一次 挥手 客户端 --- 服务器 客户端 告诉 服务器 客户端要断开链接 第二次 挥手 服务器 --- 客户端 服务器 告诉 客户端 服务器知道客户端要断开链接了 服务器等待客户端的反馈响应结果 如果客户端 有反馈 服务器 终止 断开链接程序的执行 如果客户端 没有反馈 服务器 继续 断开链接程序的执行 第三次 挥手 服务器 --- 客户端 服务器 告诉 客户端 服务器 已经 关闭 不再发送 请求 服务器 可以 接收请求 第四次 挥手 客户端 --- 服务器 客户端 告诉 服务器 客户端 知道 服务器 已经关闭了 客户端 也 关闭了 客户端 不再 接收 请求了 客户端 可以 发送请求 (5) 请求报文 客户端 向 服务器 发送请求时 执行的 http程序 请求行 请求头 请求空行 请求体 (6) 响应报文(get没有请求体 , post有请求体) 服务器 向 客户端 响应请求结果时 执行的 http程序 响应行 响应头 响应体 (7) http状态码 100 - 199 链接成功 等待进行下一步操作 200 - 299 请求结束 并且 请求成功 300 - 399 重定向请求 400 - 499 请求错误 原因是 客户端 造成的 500 - 599 请求错误 原因是 服务器 造成的

同源请求 跨域请求 1, 一个完整的请求 包括 三个部分 请求协议 请求IP地址 / 请求域名 请求的端口

ajax技术

ajax技术 1 概念 Asynchronous Javascript And XML 异步的js和XML的数据交互技术 现在发展到html也可以和ajax进行交互 2, 特点 异步的执行方式 局部数据交互( 不用跳转页面 ) 面向对象的编程方式 需要创建一个实例化对象 通过实例化对象的属性和函数方法 执行ajax操作 使用http协议完成ajax请求 ajax程序的执行 必须要通过服务器完成 本地直接运行ajax 程序执行是要报错的 3, 步骤过程 (1) 创建实例化对象 (2) 通过 open() 方法 设定 请求方式 请求地址 如果是 get 方式 通过 open() 方法携带参数 (3) 如果是 post 方式 需要设定 请求头 (4) 通过 send() 方法 发送 ajax请求 如果是 post 方式 通过 send() 方法携带参数 (5) 通过 onload() 方法 在 ajax 请求结束时 获取 响应体数据

get为什么比post快/小?get,post请求的文本类型 , 地址栏长度有没有限制

new一个对象的过程中发生了什么?

1.创建一个空对象

2.设置新对象的constrsctor属性为构造函数的名称,设置新对象的_proto_属性指向构造函数的prototype对象;

3.使用新对象调用函数,函数中的this被指向新实例对象;

4,将初始化完毕的新对象地址,保存到等号左边的变量中

this指向?

声明式,赋值式函数,定时器,延时器,foreach指向window

数组,对象中的函数的this指向这个数组,对象

面向对象编程中,this指向创建的实例化对象

事件绑定中this指向永远是事件源

通过call,apply,bind,改变的this指向是绑定的对象

箭头函数this指向的是父级

input中的type属性

路由传参方式

原型和原型链

原型

①所有引用类型都有一个__proto__(隐式原型)属性,属性值是一个普通的对象

②所有函数都有一个(原型)属性,属性值是一个普通的对象

③所有引用类型的__proto__属性指向它构造函数的prototype

原型链

当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的__proto__隐式原型上查找,即它的构造函数的prototype,如果还没有找到就会再在构造函数的prototype的__proto__中查找,这样一层一层向上查找就会形成一个链式结构,我们称为原型链。

自适应和响应式布局的区别

1.自适应布局通过检测视口分辨率,来判断当前访问的设备是:pc端、平板、手机,从而请求服务层,返回不同的页面;响应式布局通讨检测视门分辨率﹐针对不同客户端在客户端做代码处理,来展现不同的布局和内容。

2.自适应布局需要开发多套界面,而响应式布局只需要开发一套界面就可以了。

3.自适应对页面做的屏幕适配是在一定范围:比如pc端一般要大于1024像素,手机端要小于768像素。而响应式布局是一套页面全部适应。

4.自适应布局如果屏幕大小会发生内容过于拥挤。而响应式布局正是为了解决这个问题而衍生出的概念,它可以自动识别屏幕宽度并做出相应调整的网页设计。

定位属性

static:代表默认值,没有定位,也可以用来取消之前设置的定位值。

relative:相对定位,它的参照物是自己本身,可以通过left、top、right、bottom设置偏移值。它并没有脱离文档流,所以原来所占的位置依然会保留。相对定位并不会影响其他元素的布局。

absolute:绝对定位,它的参照物是包含块,也就是离自己最近的有定位属性的祖先级元素。如果祖先元素都没有定位属性,则默认按照浏览器的窗口(body)来定位。我们可以通过给祖先元素设置position:relative/absolute/fixed来让祖先元素变成包含块,通常情况下,我们会用position:relative来设置祖先元素为包含块,因为它不会脱离文档流,不会对布局造成影响。通过left、top、right、bottom来给绝对定位的元素设置偏移值。绝对定位是脱离文档流的,它原来所占位置不会保留。

fixed;固定定位,fixed参照物是浏览器的整个窗口。也会使元素脱离文档流。也是通过设置left、top、right、bottom来确定位置。

sticky:黏性定位。设置该属性后,只有当滑动到这个位置时,才会生效。生效后效果相当于固定定位fixed。也是通过设置left、top、right、bottom来确定位置。

es6新增的属性和方法

  1. let const 块级作用域

let 声明的变量在当前作用域上内不能使用变量 也不能够重新声明

1) let const 和var 的区别

1.都存在暂时性死区

2.不能够重复声明

3. 不存在变量提示

2)let 和 const的区别

1.const 声明的是一个常量 当声明引用数据类型时 是说他的堆存储地址不能改

2.基本数据类型

基本数据类型有 : num string Boolean undefined Null 新增的是: symbol

1.symbol 用来代表唯一的 可以用来定义唯一的值 号称第七种数据类型

2.使用Typeof 来判断数据类型

3.应用的场景: 给对象添加私有属性的

3.解构赋值

es6 允许按照一定的结构对变量进行赋值 , 这个就叫做解构赋值 针对对象 、数组

4.promise

1.promise 是用来解决异步的一种方案 也是解决地域回调问题 是一种链式调动的方式

2.promise 可以说是一个容器 , 里面保存着某个未来才会结束的事件

3.promise 分为3个状态:

1) pending 初始状态 ---正在进行 或者请求 或者 初始化

2) fulfilled 成功状态 ---- 成功状态

3) rejected 失败状态------失败状态

一般发生改变则不可逆

5.箭头函数

参数: 如果没有参数 或多个参数 一定要用()包括起来

箭头函数没有this 指向

箭头函数不能作为构造函数

没有arguments(arguments对象是所有(非箭头)函数中都可用的局部变量。你可以使用arguments对象在函数中引用函数的参数。此对象包含传递给函数的每个参数,第一个参数在索引 0 处。例如,如果一个函数传递了三个参数,你可以以如下方式引用他们:

arguments[0] arguments[1] arguments[2]

Copy to Clipboard

参数也可以被设置:

arguments[1] = 'new value';

)

6.findindex

7.generator 函数

声明: function 和函数名 之间加上 * 号 : 普通函数就会变成generator 函数

特点: 也是异步编程的一个解决方案 : 分段执行

启动函数: next()

8.object.defineproperty

给对象新增属性 或修改属性使用

9.proxy

10.展开合并运算符...

11.类

在es5中如果一些公共属性是要写到原型里面 但是在es6中可以用 class来表示

例如:

12.继承

在es5中想要继承属性 需要将一些想要被继承的属性写到原型对象里面才可以 在es6中用extends即可完成

例如:

在子类构造函数使用super调用父类的构造函数 不需要考虑this指向

13.try.catch和throw

try尝试 catch捕获 throw异常抛出

例如:

14.set

set对象储存的值每个值只能出现一次 可用作数组去重

例如:

作用域

在 ES6 之前,ES 的作用域只有两种:全局作用域和函数作用域。

1、全局作用域  中的对象在代码中的任何地方都能访问,其生命周期伴随着页面的生命周期。

2、函数作用域  就是在函数内部定义的变量或者函数,并且定义的变量或者函数只能在函数内部被访问。函数执行结束之后,函数内部定义的变量会被销毁。

块级作用域就是使用一对大括号包裹的一段代码,比如函数、判断语句、循环语句,甚至单独的一个{}都可以被看作是一个块级作用域。

示例代码

简单来讲,如果一种语言支持块级作用域,那么其代码块内部定义的变量在代码块外部是访问不到的,并且等该代码块中的代码执行完成之后,代码块中定义的变量会被销毁。

变量提升所带来的问题

1. 变量容易在不被察觉的情况下被覆盖掉

2. 本应销毁的变量没有被销毁

为了解决这些问题,ES6 引入了 let 和 const 关键字,从而使 JavaScript 也能像其他语言一样拥有了块级作用域。

使用 let 关键字声明的变量是可以被改变的,而使用 const 声明的变量其值是不可以被改变的。但不管怎样,两者都可以生成块级作用域,

vue2和vue3的区别

  1. vue2和vue3双向数据绑定原理发生了改变

vue2的双向数据绑定是利用了es5 的一个API Object.definepropert() 对数据进行劫持 结合发布订阅模式来实现的。vue3中使用了es6的proxyAPI对数据进行处理。

相比与vue2,使用proxy API 优势有:defineProperty只能监听某个属性,不能对全对象进行监听;可以省去for in 、闭包等内容来提升效率(直接绑定整个对象即可);可以监听数组,不用再去单独的对数组做特异性操作,vue3可以检测到数组内部数据的变化。

2.Vue3支持碎片(Fragments)

就是说可以拥有多个跟节点。

1

3. Composition API

Vue2 与vue3 最大的区别是vue2使用选项类型api,对比vue3合成型api。旧得选项型api在代码里分割了不同得属性:data,computed,methods等;新得合成型api能让我们使用方法来分割,相比于旧的API使用属性来分组,这样代码会更加简便和整洁。

4. 建立数据data

vue2是把数据放入data中,vue3就需要使用一个新的setup()方法,此方法在组件初始化构造得时候触发。使用一下三个步骤来简=建立反应性数据: 1. 从vue引入reactive;使用reactive() 方法来声明数据为响应性数据;3. 使用setup()方法来返回我们得响应性数据,从而template可以获取这些响应性数据。

1

5. 生命周期

vue2 --------------- vue3

beforeCreate -> setup()

Created -> setup()

beforeMount -> onBeforeMount

mounted -> onMounted

beforeUpdate -> onBeforeUpdate

updated -> onUpdated

beforeDestroyed -> onBeforeUnmount

destroyed -> onUnmounted

activated -> onActivated

deactivated -> onDeactivated

6. 父子传参不同,setup()函数特性

(1).setup()函数接收两个参数:props、context(包含attrs、slots、emit)

(2).setup函数是处于生命周期beforeCreated和created俩个钩子函数之前

(3).执行setup时,组件实例尚未被创建(在setup()内部,this不会是该活跃实例得引用,即不指向vue实例,Vue为了避免我们错误得使用,直接将setup函数中得this修改成了undefined)

(4).与模板一起使用时,需要返回一个对象

(5).因为setup函数中,props是响应式得,当传入新的prop时,它将会被更新,所以不能使用es6解构,因为它会消除prop得响应性,如需解构prop,可以通过使用setup函数中得toRefs来完成此操作。

(6).父传子,用props,子传父用事件 Emitting Events。在vue2中,会调用this$emit然后传入事件名和对象;在vue3中得setup()中得第二个参数content对象中就有emit,那么我们只要在setup()接收第二个参数中使用分解对象法取出emit就可以在setup方法中随意使用了。

(7).在setup()内使用响应式数据时,需要通过 .value 获取

import { ref } from 'vue'

const count = ref(0)

console.log(count.value)

(8).从setup() 中返回得对象上得property 返回并可以在模板中被访问时,它将自动展开为内部值。不需要在模板中追加.value。

(9).setup函数只能是同步的不能是异步的。

get和post区别

1. GET请求没有请求体。POST请求有请求体。

2. GET请求的参数(需要传递的数据)要放在URL中发送,大小有限制。

  POST请求的参数可以放在URL后传递,也可以放在请求体中(大小不受限制)。

3.GET安全性相对较差。

  a.参数明文

  b.数据会被浏览器缓存

4.设计的用途不同。

  GET用来查询--不操作数据,参数量小。

  POST用来插入、更新数据--安全要求高,数据量大

css中的before和after

:before是css中的一种伪元素,可用于在某个元素之前插入某些内容。

:after是css中的一种伪元素,可用于在某个元素之后插入某些内容。

移动端项目

我的项目是一个职业资格证书在线报名/学习/考试系统,主要完成了商品的展示,商品的详情介绍,如果客户在浏览的时候有喜欢的商品,可以注册我们的账户,登录成果之后可以立即购买,也可以收藏或者加入购物车 , 在购物车里 , 我们可以更改商品的数量 , 或者不想要也可以删除 , 当我们点击提交订单 , 跳转到订单页面确认订单 , 确认数量 ,价格 .

商品的展示

通过封装好的axios请求 , 调用后端数据接口 , 将数据用v-for 在首页或者分类列表页中渲染视图 , 利用了keep-alive包裹去渲染商品列表的路由 , 这样当我们点击跳转到详情页的时候点击返回就可以保证之前页面不被销毁 , 跳转的时候还需要将之前列表滚动的高度数据存起来 , 然后 , 返回列表页的时候就可以将scrolltop设置成之前存的 , 就看可以在返回的时候返回到原来浏览的位置 , 关键是用keep -alive 附带的两个钩子函数的activeted , 还可以通过筛选条件渲染不同的列表 , 利用computed计算属性 , 点击筛选条件时 , 调用computed中的方法 , 然后传参 , 根据参数区分用户点击的筛选条件 , 然后return 不同的数据 , 返回渲染不同的商品列表

当用户点击喜欢的商品或者从猜你喜欢的推荐中的商品时 , 我们就通过点击事件的回调发送请求 , 将所点击的商品的商品id传参传入回调中 , 将请求的数据渲染到商品的详情页当中,

我们可以在详情页中点击图片放大预览, 如果有视频 , 我们还可以点击播放按钮 , 通过遮罩层弹窗播放视频 , 为了详情页的快速加载 , 使用图片懒加载.

点击商品规格, 利用vant组件库中的弹出层,弹出一个可以选择的页面 , 如果该商品规格已经售空 , 对应的数量修改按钮加入购物车按钮全部被禁用 , 如果可以购买 , 我们点击立即购买 , 就会进入订单页面 , 确认订单的详情 , 订单详情可以选择支付方式.

注册登录

当我们点击加入购物车的时候 , 通过vuex中存的登录状态判断存的数据通常为布尔值类型.

登录可以用户 ,密码登录 , 请求数据库进行验证 , 也可以点击其他社交平台及进行登录 , 发请求验证是否手机号绑定过 , 如果绑定过就跳转到使用社交平台 , 注册登录 , 绑定手机号的时候 , 给输入框绑定input事件 , 如果在事件的回调中使用正则对输入的手机号进行验证 , 如果手机号规范不合格 , 注册按钮是禁用状态 , 注册下一步还要发送请求验证是否绑定过该项目中的其他账号 , 如果有提示用户换一个手机号 , 此手机号已经被注册 , 包括其他的验证码和密码的输入框都需要用正则验证规范 , 注册完三秒后自动跳转到登录页 , 在发送短信验证的时候发送按钮会进入一个读秒倒计时 , 如果时间没有结束不可以再次点击发送 , 如果中途切走 , 将时间存到本地存储中 , 清掉倒计时的定时器 , 当我从其他页面切回来 , 重新获取时间 , 继续开始倒计时 , 只有当倒计时结束后 ,将button绑定的disable改为false , 才可以再次点击发送 , 避免由于网络延迟问题 , 有的用户通过切换页面,连续点击发送短信.

如何实现上拉加载和下拉刷新

下拉刷新和上拉加载这两种交互方式通常出现在移动端中

1、上拉加载

上拉加载的本质是页面触底,或者快要触底时的动作

触底公式:scrollTop + clientHeight >= offsetTop

2、下拉刷新

下拉刷新的本质是页面本身置于顶部时,用户下拉时需要触发的动作,主要分为三个步骤:

监听原生touchstart事件,记录其初始位置的值,e.touches[0].pageY;

监听原生touchmove事件,记录并计算当前滑动的位置值与初始位置值的差值,大于0表示向下拉动,并借助CSS3的translateY属性使元素跟随手势向下滑动对应的差值,同时也应设置一个允许滑动的最大值;

监听原生touchend事件,若此时元素滑动达到最大值,则触发callback,同时将translateY重设为0,元素回到初始位置。

监听touchstart事件,记录初始的值

监听touchmove移动事件,记录滑动差值

监听touchend离开的事件

项目

按钮权限控制

我们跟后端约定好了一个字段options再后端返回的结构中options对象里面包含了比如三个按钮权限控制新增编辑删除然后我们封装了一个自定义指令permission

再指令里面我们首先要拿到一个指令值指令值是后端返回的可操作的按钮的指令,然后在获取都当前路由的名称,再通过方法拿到该路由名称对应的角色权限数据结构中的相关对象,判断options内是否有该内容权限,如果有就可以点击执行,如果没有的话会弹出窗告诉用户无操作权限

forEach , for in , for of

forEach更多用于遍历数组

for in 一般用来遍历对象或json

for of数组对象都可以遍历 , 遍历对象需要通过Object.keys()

for in 循环出的是key , for of 循环出的是value

git

var let const区别

var声明变量可以重复声明,而let不可以重复声明

var是不受限于块级的,而let是受限于块级

var会与window相映射(会挂一个属性),而let不与window相映射

var可以在声明的上面访问变量,而let有暂存死区,在声明的上面访问变量会报错const声明之后必须赋值,否则会报错

const定义不可变的量,改变了就会报错

const和let一样不会与window相映射、支持块级作用域、在声明的上面访问变量会报错

WebSocket协议

WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。

为什么需要 WebSocket?

因为 HTTP 协议有一个缺陷:通信只能由客户端发起,HTTP 协议做不到服务器主动向客户端推送信息。

举例来说,我们想要查询当前的排队情况,只能是页面轮询向服务器发出请求,服务器返回查询结果。轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。因此WebSocket 就是这样发明的。

webpack

  1. 1.安装webpack

cnpm install webpack webpack-cli -g;

新建一个src文件,在其目录下新建一个main.js入口文件(如果都已经生成存在则不用管)

2. 初始化项目包

npm init -y 生成package.json

3. 本地安装webpack依赖

cnpm install webpack webpack-cli --save-dev

4. webpack打包

webpack ./src/main.js -o ./dist/bundle.js --modedevelopment //开发模式

webpack ./src/main.js -o ./dist/bundle.js --modeproduction //生产模式

---------------------配置文件打包流程---------------------

前提你已经进行以上1,2,3步骤,再新建webpack.config.js文件,并配置它

vue的热更新

使用vue的热加载可以实现局部内容的刷新,更改数据后,不会刷新整个页面

在webpack.config.js中设置:

对config.devServer中添加属性hot:true

对config.plugins添加

new webpack.HotModuleReplacementPlugin(),

new webpack.NoEmitOnErrorsPlugin()

具体设置如图:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值