首页
关于
Search
1
牛客ACM输入输出特殊情况
150 阅读
2
时间复杂度与空间复杂度
143 阅读
3
实习日记 01 运行项目
110 阅读
4
常见判断输出的题
101 阅读
5
实习日记02 看项目首页源码
100 阅读
默认分类
实习
相关学习
算法
前端
登录
Search
Typecho
累计撰写
29
篇文章
累计收到
1
条评论
首页
栏目
默认分类
实习
相关学习
算法
前端
页面
关于
搜索到
8
篇与
的结果
2022-08-19
DOM相关
什么是DOM?DOM就是文档对象模型,当网页被加载时,浏览器会创建页面的文档对象模型。通过DOM,JS能够访问和改变HTML文档的所有元素。树形结构。常见DOM操作?创建节点:let a = document.createElement('div') 创建一个DIV标签 let b = document.createTextNode('content') 创建一个文本节点 let c = document.createDocumentFragment() 用来创建一个文档碎片,它表示一种轻量级的文档,主要是用来存储临时节点,然后把文档碎片的内容一次性添加到DOM中 let d = document.createAttribute('custom') 创建属性节点,可以是自定义属性获取节点:document.querySelector('.element') 传入任何有效的css选择器,即可选中单个DOM元素(首个) 如果页面没有指定的元素时,返回null document.querySelectorAll("p") 返回一个包含节点子树内所有与之相匹配的Element节点列表,如果没有相匹配的,则返回一个空节点列表。是一个静态的“快照”,而非“实时”的查询 document.getElementById('id属性值');返回拥有指定id的对象的引用 document.getElementsByClassName('class属性值');返回拥有指定class的对象集合 document.getElementsByTagName('标签名');返回拥有指定标签名的对象集合 document.getElementsByName('name属性值'); 返回拥有指定名称的对象结合 document/element.querySelector('CSS选择器'); 仅返回第一个匹配的元素 document/element.querySelectorAll('CSS选择器'); 返回所有匹配的元素 document.documentElement; 获取页面中的HTML标签 document.body; 获取页面中的BODY标签 document.all['']; 获取页面中的所有元素节点的对象集合型更新节点:innerHTML:不但可以修改一个DOM节点的文本内容,还可以直接通过HTML片段修改DOM节点内部的子树var p = document.getElementById('p'); p.innerHTML = 'ABC' p.innerHTML = 'ABC <span style="color:red">RED</span> XYZ';innerText、textContent:自动对字符串进行HTML编码,保证无法设置任何HTML标签和上面的一样。只不过没办法写标签了。style:DOM节点的style属性对应所有的CSS,可以直接获取或设置。遇到-需要转化为驼峰命名let p = document.getElementById('p-id'); p.style.color = '#ff0000'; p.style.fontSize = '20px'; // 驼峰命名 p.style.paddingTop = '2em';替换节点:父节点.replaceChild(new, old);修改属性值:父节点.setAttribute("属性名","属性值");添加节点:可以利用innerHTML在其中直接添加节点appendChild:把一个子节点添加到父节点的最后一个子节点let js = document.getElementById('js') js.innerHTML = "JavaScript" let list = document.getElementById('list'); list.appendChild(js);insertBefore:把子节点插入到指定的位置的前面setAttribute:在指定元素中添加一个属性节点,如果元素中已有该属性改变属性值parentElement.insertBefore(newElement, referenceElement) const div = document.getElementById('id') div.setAttribute('class', 'white');//第一个参数属性名,第二个参数属性值。删除节点:删除一个节点,首先要获得该节点本身以及它的父节点,然后,调用父节点的removeChild把自己删掉// 拿到待删除节点: const self = document.getElementById('to-be-removed'); // 拿到父节点: const parent = self.parentElement; // 删除: const removed = parent.removeChild(self); removed === self; // true事件监听添加监听事件,可以给一个DOM元素添加多个不同监听,也可以添加相同监听。let p1 = document.getElementById('p') p1.addEventListener(event, function, useCapture) // 第一个参数是事件的类型 (如 "click" 或 "mousedown","mouseover","mouseout")。 // 第二个参数是事件触发后调用的函数。 // 第三个参数是个布尔值用于描述事件是冒泡还是捕获。该参数是可选的。 false冒泡是默认 如果获取的是一个列表,那么可以使用foreach const lis = Array.from(document.getElementsByTagName('li')); lis.forEach(element => { function(){} } )可以给window对象添加监听// resize是监听到浏览器窗口改变的时候触发(多搭配防抖节流) window.addEventListener("resize",function(){ document.getElementById("demo").innerHTML=Math.random(); });删除监听,需要通过触发某个函数删除,例如给BUTTON绑定onclick事件。function removeHandler() { document.getElementById("myDIV").removeEventListener("mousemove",myFunction); }阻止冒泡与阻止默认e.stoppropagation() 阻止冒泡 e.preventDefault() 阻止默认 return false; 既阻止冒泡又阻止默认事件监听中的e:e.target指向的是触发事件的元素e.currentTarget指向的是添加监听事件的元素冒泡具体场景:事件委托ul.addEventListener('click', function(e){ // e.currentTarget 被监听的对象,一般不变 // e.target 正在操作的对象,有可能变 if(e.target.tagName.toLowerCase()=== 'li'){ fn(); } })监听窗口尺寸大小变化let getWindowInfo = function(){ let windowInfo = { width:window.innerWidth height:window.innerHeight } } // 无防抖的监听 window.addEventListener('resize',getWindowInfo) // 添加防抖 let debounce = (fn,delay) => { let timer return function(){ if(timer){ clearTimeout(timer) } timer = setTimeout(() => { fn(); },delay) } } let cacelDebounce = debounce(getWindowInfo,500) window.addEventListener('resize',cacelDebounce)
2022年08月19日
74 阅读
0 评论
0 点赞
2022-07-08
前端常见的手写
call:Function.prototype.myCall = function(context){ let context = context || window context.fn = this let args = [...arguments].slice(1) let result = args.length > 0 ? context.fn(...args) : context.fn() delete context.fn return result }apply:Function.prototype.myApply = function(context){ let context = context || window context.fn = this let args = [...arguments].slice(1) let result = args.length > 0 ? context.fn(args) : context.fn() delete context.fn return result }bindFunction.prototype.myBind = function(context){ let fn = this let args = [...arguments].slice(1) return function newFn(...newFnArgs){ if(this instanceOf newFn){ return new fn(...args,...newFnArgs) } return fn.apply(context,[...args,...newFnArgs]) } }new的过程function ctor(){ ... } function myNew(ctor,...args){ if(typeOf ctor !== 'function'){ throw 'error' } let newObj = Object.creat(ctor.prototype) let result = ctor.apply(newObj,args) let isObject = typeOf result === 'object' && result !==null let isFunction = typeOf result === 'function' if(isObject || isFunction){ return result } return newObj }继承// 父类 function Animal(name){ this.name = name this.sleep = function(){ console.log('sleep') } } animal.prototype.eat = function(){ console.log('eat') } //原型链继承 --将父类的实例作为子类的原型 //实例是子类的实例,也是父类的实例,父类新增原型上的属性可以访问到 //缺点:给子类新增属性和方法要在子类构造函数中。无法多继承。原型对象的属性被实例共享。创建子类实例时,无法向父类构造函数传参 function Cat(){ } cat.protytype = new Animal() cat.protytype.name = 'cat' let cat = new Cat() //构造继承--使用父类构造函数来增强子类实例,等于说复制父类实例属性给子类 // 解决了共享属性的问题,创建子类实例可以给父类传参数,可以多继承 // 缺点:实例并不是父类的实例,仅仅是子类的。不能继承父类原型属性和方法,无法复用,每个子类都有父类实例函数的副本,影响性能 function Cat(name){ Animal.call(this) this.name = name } // 实例继承---为父类实例添加新特性,作为实例子类返回 // 不限制调用方式,不管是new 子类()还是子类(),返回的对象具有相同的效果 // 缺点:实例是父类的实例,不是子类的实例,不能多继承 function Cat(name){ let instance = new Animal() instance.name = name return instance } // 拷贝继承 // 可以多继承 // 效率低,因为拷贝。无法获取父类不可枚举的属性 function Cat(name){ var animal = new Animal(); for(let p in animal){ Cat.prototype[p] = animal[p]; } this.name = name || 'Tom'; } // 组合继承---通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用 // 实例与原型属性方法都可以继承、既是子类的实例,也是父类的实例、无属性共享、可传参、可复用 // 缺点: 调用了两次父类构造函数,生成了两份实例(子类实例将子类原型上的那份屏蔽了) function Cat(name){ Animal.call(this) this.name = name } Cat.prototype = new Animal() // 组合继承需要修复构造函数指向 Cat.prototype.constructor = Cat; // 寄生组合继承---通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点 // 完美,没有缺点 function Cat(name){ Animal.call(this) this.name = name } (function(){ // 创建一个没有实例方法的类 var Super = function(){}; Super.prototype = Animal.prototype; //将实例作为子类的原型 Cat.prototype = new Super(); }) // ES6继承 //class 相当于es5中构造函数 //class中定义方法时,前后不能加function,全部定义在class的protopyte属性中 //class中定义的所有方法是不可枚举的 //class中只能定义方法,不能定义对象,变量等 //class和方法内默认都是严格模式 //es5中constructor为隐式属性 class People{ constructor(name='wang',age='27'){ this.name = name; this.age = age; } eat(){ console.log(`${this.name} ${this.age} eat food`) } } // 子类 class Woman extends People{ constructor(name = 'ren',age = '27'){ //继承父类属性 super(name, age); } eat(){ //继承父类方法 super.eat() } } let wonmanObj=new Woman('xiaoxiami'); Object.create()Object.myCreate(obj){ function fn(){} fn.prototype = obj return new fn() }instanceOf()ps:关于原型链的一个知识点, Object和Function的构造函数都是Function,所以他们两个的__proto__都指向Function.prototype。特殊点在于Function是实例也是对象。所有对象原型链的终点都是Object.prototype// 判断A是否是B的实例--A instanceof B // 不能检测基本数据类型,在原型链上的结果未必准确,不能检测null,undefined function myInstanceOf(a,b){ let left = a.__proto__ let right = b.prototype while(true){ if(left === null){ return false } if(left === right){ return true } left = left.__proto__ } }Object.assign()// 该方法用于将所有可枚举属性的值从一个或多个源对象(sources)分配到目标对象(target),并返回目标对象。是浅拷贝,继承的属性也不可以复制。属性名冲突时以后面的参数为准,异常也会打断后续的拷贝任务 // 如果想要深拷贝可以let obj = Object.assign(obj2,JSON.parse(JSON.stringify(obj1))); Object.myAssign = function(target,...source){ if(target === null){ throw new error('error') } // 将target转换为对象(避免基本数据类型不是对象) let ret = Object(target) source.forEach(function(obj){ if(obj !== null){ for(let key in obj){ // hasOwnProperty --查找obj是否有key这个属性,不去原型上找 // 由于in运算符会查找原型身上的可枚举属性,所以需要hasOwnProperty过滤 if(obj.hasOwnProperty(key)){ ret[key] = obj[key] } } } }) return ret } AJAXfunction myAjax(url,method,body,headers){ return new Promise((resolve,reject) => { // XMLHttpRequest用于发送请求,有一些参数可选 let req = new XMLHttpRequest(); req.open(method,url) for(let key in headers){ req.setRequestHeader(key,headers[key]) } req.onreadystatechange(() => { if(req.readystate === 4){ if(req.status >= '200' && req.status <= 300){ resolve(req.responeText) }else{ reject(req) } } }) req.send(body) }) }
2022年07月08日
59 阅读
0 评论
0 点赞
2022-06-14
小程序
问题小程序是单页面应用吗?小程序的开发是如何发送请求请求数据的?微信小程序的四种类型网络请求?小程序获取定位的方法?小程序中数据如何同步渲染?小程序的生命周期?小程序的rpx单位?微信小程序和vue区别?小程序原理?Bindtap和catchtap区别?Wxml和html异同?小程序三种事件对象的属性列表?小程序优势劣势?答案:小程序相关小程序是单页面应用,通过路由进行页面切换小程序的开发是如何发送请求请求数据的?微信小程序只能和指定的域名进行通信,需要进行配置。且域名只支持https协议和wss协议,域名也不能使用ip地址且必须经过备案。微信小程序的四种类型网络请求?普通http请求 wx.request 上传文件wx.updateFile载文件wx.downloadFile webSocket通信wx.connectSocket 小程序不存在跨域的限制,是因为小程序并不运行在浏览器中getlocation 获取定位小程序中数据如何同步渲染通过setdata方法Setdata原理:小程序分为逻辑层和渲染层,逻辑层改变后要通过native运行。渲染层和逻辑层分别由两个线程管理,渲染层界面使用了webView进行渲染,逻辑层采用jsCore线程运行js脚本。一个小程序存在多个页面,所以渲染层存在多个webview,这两个线程的通信经由微信客户端native做中转,逻辑层发送网络请求也是经过native 转发所以我们不要重复 setdata ,以及减少数据的传输量。我们的数据传输实际是一次 Javascript 脚本过程,当数据量过大时会增加脚本的编译执行时间,占用 WebView JS 线程。去除不必要的事件绑定( WXML 中的 bind 和 catch ),从而减少通信的数据量和次数。小程序的生命周期1 应用生命周期onLaunch() 应用第一次启动的时候,首先执行这里的事件。一般用于获取用户信息,这里不能使用setdada修改dataonShow() 小程序应用渲染之后,用户能看到组件等信息,这个时候执行onshow,用户切换到后台在切换回来的时候会执行onshow。一般用于用户返回的时候对内容进行重置onHide() 小程序被隐藏到后台的时候触发 一般用于用户切换到后台进行的暂停操作onError() 当应用发生错误的时候触发 onPageNotFound() 当小程序第一次打开找不到入口界面的时候触发 一般用户主页找不到跳转到另外的主页2 页面的生命周期(每次进入到一个新的页面)Onload() 监听页面加载onShow() 监听页面显示onReady() 监听初次渲染完成onHide() 监听界面隐藏onUnload() 监听页面卸载onPullDownRefresh() 监听用户下拉刷新onReachBottom() 监听上拉触顶onShareAppMessage() 监听用户分享转发onPageScroll() 监听页面滚动onResize() 监听页面尺寸发生改变 横竖屏onTabItemTap() 当该页面是指定的tab页面,再次点击这个tabbar对应的tab按钮,就会触发3 组件的生命周期Created 组件实例刚被创建好,此时还不能调用setdataAttacthed 组件初始化完毕,进入页面节点树时执行Ready 组件布局完成之后执行 Moved 组件实例被移动到节点树另一个位置的时候执行Detachd 组件离开页面节点数的时候触发小程序的rpx单位Rpx是微信独有的解决屏幕自适应的尺寸单位,他是规定屏幕宽度为750rpx,从而达到自动适配微信小程序和vue区别生命周期不一样,小程序的简单数据绑定不同,小程序用{{}} vue用 :显示隐藏元素不同 vue v-if v-show 小程序 wx-if hidden数据双向绑定不同,vue只需要在表单元素加v-model就可以,小程序则必须获取到表单元素改变的值,然后再把值赋给data中声明的变量小程序原理采用js,wxml,wxss三种技术进行开发,本质是单页面应用,所有的页面渲染和事件处理,都在一个页面内进行,页面的更新也是通过数据的更改来实现的。小程序分为webview和appServer,前者用来展示ui,后者用来处理逻辑、数据、接口调用,在两个进程中运行。Bindtap和catchtap区别相同:都是点击事件,点击触发不同:bindtap不会阻止冒泡,catchtap会阻止Wxml和html异同同:都是用来描述界面的构成 都是标签、属性等构成不同:标签名字不一样 一个在浏览器里预览一个在小程序开发工具中预览 组件封装不同小程序中没有dom树和window对象小程序三种事件对象的属性列表小程序优势劣势优势:无需下载 打开速度快 开发成本低 审核严格,较为安全劣势:限制多,页面大小不能超过1m 样式单一,幻灯片导航等不能修改 依托微信,麻烦宿主环境 安卓和ios
2022年06月14日
43 阅读
0 评论
0 点赞
2022-06-14
vue
问题Vue是单页面应用吗?Import和require?路由懒加载以及具体如何实现?vue图片懒加载以及js实现懒加载的原理?V-bind,v-model区别?Vue2.0双向绑定原理和缺陷?Vue3.0实现双向数据绑定的方法?路由导航守卫?HashRouter 和 HistoryRouter的原理和区别?组件之间通信方式?异步加载在mouted还是created?Vue的生命周期?Keep-alive组件?http和tcp的Keepalive?父子组件生命周期函数调用顺序?既然函数是引用类型,为什么 vue 的 data 还是可以用函数?$nextTick?V-if v-show 异同?Vuex?首页白屏如何解决?路由跳转和location.href的区别?Computed和watch区别?混入?Vue提升性能的几种办法?虚拟DOM和diff算法?如何进行路由跳转?Push和replace区别?路由跳转的时候所带的参数params和query参数区别?编程式导航跳转到当前路由(路由未变的跳转),会报错的解决办法?如果params的数据是’’,无法跳转如何解决?路由组件能不能传递props数据?答案:Vue是单页面应用单页面应用是指公共资源仅加载一次,页面加载只发送一次请求,直接把所有需要的html,css,js都加载完毕,后续的数据更新与交互是通过路由跳转和发送ajax请求来完成的。优点是页面跳转很快,只是路由跳转而没有发送http请求,缺点是首屏加载时间太长和seo效果差。优点:交互体验好,页面显示比较流畅。 前后端分离 服务器压力小缺点:首屏加载慢 不利于SEO Import和requireRequire是AMD规范,import是es6的语法标准Require运行的时候调用,所以说可以放在任何地方用,import是编译的时候调用,必须放在开头的位置两者都是模块化的体现Import和require会返回一个promise对象路由懒加载Vue是单页面应用,如果没有懒加载会导致运用webpack打包后文件变得很大,造成进入首页时需要加载的东西很 多时间过长,则会出现长时间的白屏,不利于用户体验,懒加载可以将页面进行划分,需要的时候加载页面,能够有效分担压力,减少页面加载用的时间路由懒加载的办法Component写路由名字的时候利用import或者require,由于两者是返回一个promise函数,所以说vue router只会在第一次进入这个页面的时候才会获取函数,然后使用缓存数据图片懒加载--vue-lazyload先把img标签中的src设置成同一张图片(像素较低的),然后将其真正的图片地址存储在img标签的自定义属性之中,当js监听到该图片元素进入可视窗口的时候,在把自定义属性中的地址存储到src属性中。实现方式, vue的话直接用插件可以定义默认状态图片和失败状态的图片Js原生的话需要监听页面的滚动,每次页面滚动都会获取可视区域的高度,最后在对图片到页面的高度与可视高度与滑动高度的大小进行比较,当图片出现在可视窗口内的时候进行属性的替换。V-bind,v-model区别V-bind单向数据绑定,数据只能从data流向页面。形式:v-bind:href=“xxx” xxx改变页面的url也会改变v-model双向数据绑定,修改页面数据后台数据也会变。(只用在ipnut,textarea,select)v-model = V-bind + oninput事件 @input="sth = $event.target.value"Vue2.0双向绑定原理和缺陷?采用数据劫持和发布订阅模式的方式,通过object.defineProperty()来劫持各个属性的setter,getter缺陷Vue实例创建后,无法检测到对象属性的新增或者删除(object.defineProperty只能劫持到对象的属性),只能追踪到是否被修改--------创建一个vue实例的时候,会遍历所有的dom对象,并给每个数据增加get和set。Get和set 可以观察数据的更改和更新数据。但是在vue实例创建之后在添加或删除一个属性,这个属性就没有get和set不能监听数组的变化---------实现数组的响应式是对数组的部分方法进行了重写实现的,但是只重写了push/pop/shift/unshift/splice/sort/reverse,其他的方法对数组进行改写检测不到。Vue3.0实现双向数据绑定的方法通过proxy实现,proxy--在目标对象之前架设一层拦截,外界对该对象的访问,都必须先通过这层拦截,因此可以对外界的访问进行过滤和改写。优点:可以利用proxy来处理一些非核心逻辑(如读取修改属性之前做验证等操作)可以劫持整个对象,并返回一个新对象 有13种劫持操作路由导航守卫步骤:先实例化一个VueRouter对象,把所有的路由组件都配置在里面主要是用于路由跳转的时候进行的一系列操作 分类:全局前置守卫(router.beforeEach)--导航开始的时候调用全局解析守卫(router.beforeResolve)---指所有组件内守卫和异步路由组件解析后,但是导航还没有确认之前的全局后置守卫(router.afterEach)--主要用于分析,更改页面标题等路由独享守卫(全局守卫一致,不过没有router. 了)---定义在每个路由的配置上组件内守卫(beforeRouterEnter,...Update,...Leave)---VueRouter路由组件内定义(只针对当前组件的路由跳转,分为进入、更新、离开)beforeRouterEnter--是在渲染该组件前,组件实例创建之前的,所以不能获取thisbeforeRouterUpdate--当前路由改变,但是该组件被复用的时候调用,可以访问thisbeforeRouterLeave--在导航离开渲染该组件的对应路由的时候调用,可以访问thisHashRouter 和 HistoryRouter的原理和区别他们都是url改变的时候能够监听的到HashRouter--原理是利用了hashchange事件,能够在window监听hash的变化,vue-roter默认是hash模式--这种模式利用url的hash来模拟一个完整的url,就是项目中的#,#后面的hash发生变化的时候,不会导致浏览器给服务器发请求,并且会触发hashchange,可以通过监听hash值的变化来实现页面的更新。hash模式会创建hashHistory对象,访问不同的路由组件的时候会hashHistory.push(新路由放到栈顶)和hashHistory.replace记录浏览历史HistoryRouter--利用pushState(),replaceState()结合window.popstate(监听前进后退)实现的,pushState改变url地址不发请求,replaceState可以读取历史记录栈,还可以对浏览器的历史记录修改区别pushState设置的url可以是当前同源的所有url,而hash只能修改#后面的pushState新旧url可以一致,hash的则必须不一样pushState可以通过stateObject添加任意类型数据记录,hash只可以短字符串pushState可以设置title属性pushState兼容ie10,hash ie8pushState需要后端配合将所有的访问都指向index.html,否则刷新会404Hash模式不会请求服务器HashRouter 和 HistoryRouter的原理和区别他们都是url改变的时候能够监听的到HashRouter--原理是利用了hashchange事件,能够在window监听hash的变化,vue-roter默认是hash模式--这种模式利用url的hash来模拟一个完整的url,就是项目中的#,#后面的hash发生变化的时候,不会导致浏览器给服务器发请求,并且会触发hashchange,可以通过监听hash值的变化来实现页面的更新。hash模式会创建hashHistory对象,访问不同的路由组件的时候会hashHistory.push(新路由放到栈顶)和hashHistory.replace记录浏览历史HistoryRouter--利用pushState(),replaceState()结合window.popstate(监听前进后退)实现的,pushState改变url地址不发请求,replaceState可以读取历史记录栈,还可以对浏览器的历史记录修改区别pushState设置的url可以是当前同源的所有url,而hash只能修改#后面的pushState新旧url可以一致,hash的则必须不一样pushState可以通过stateObject添加任意类型数据记录,hash只可以短字符串pushState可以设置title属性pushState兼容ie10,hash ie8pushState需要后端配合将所有的访问都指向index.html,否则刷新会404Hash模式不会请求服务器异步加载在mouted还是created两者都可以,更多是在created中,因为能够更快的获取到服务端的数据,减少页面加载的时间,created加载的早一点。但是在created中dom元素还没有加载出来,如果需要操作dom的话放在mounted中。Vue的生命周期Vue 实例从创建到销毁的过程,就是生命周期。第一次页面加载会触发哪几个钩子?beforeCreate , created , beforeMount ,mounted 这几个钩子beforeCreate:创建前,此阶段为实例初始化之后,this指向创建的实例,此时的数据观察事件机制都未形成,不能获得DOM节点。data,computed,watch,methods 上的方法和数据均不能访问。可以在这加个loading事件。created:创建后,此阶段为实例已经创建,完成数据(data、props、computed)的初始化导入依赖项。可访问 data computed watch methods 上的方法和数据。初始化完成时的事件写在这里,异步请求也适宜在这里调用(请求不宜过多,避免白屏时间太长)。可以在这里结束loading事件,还做一些初始化,实现函数自执行。未挂载DOM,若在此阶段进行DOM操作一定要放在Vue.nextTick()的回调函数中。beforeMount:挂载前,虽然得不到具体的DOM元素,但vue挂载的根节点已经创建,下面vue对DOM的操作将围绕这个根元素继续进行。beforeMount这个阶段是过渡性的,一般一个项目只能用到一两次。mounted:挂载,完成创建vm.$el,和双向绑定完成挂载DOM和渲染,可在mounted钩子函数中对挂载的DOM进行操作。可在这发起后端请求,拿回数据,配合路由钩子做一些事情。beforeUpdate:数据更新前,数据驱动DOM。在数据更新后虽然没有立即更新数据,但是DOM中的数据会改变,这是vue双向数据绑定的作用。可在更新前访问现有的DOM,如手动移出添加的事件监听器。updated:数据更新后,完成虚拟DOM的重新渲染和打补丁。组件DOM已完成更新,可执行依赖的DOM操作。注意:不要在此函数中操作数据(修改属性),会陷入死循环。activated:在使用vue-router时有时需要使用来缓存组件状态,这个时候created钩子就不会被重复调用了。如果我们的子组件需要在每次加载的时候进行某些操作,可以使用activated钩子触发。deactivated:组件被移除时使用。beforeDestroy:销毁前,可做一些删除提示,如:您确定删除xx吗?destroyed:销毁后,当前组件已被删除,销毁监听事件,组件、事件、子实例也被销毁。这时组件已经没有了,无法操作里面的任何东西了。Keep-alive组件保存组件状态而不销毁,返回后仍在选本状态,避免了重复渲染。http和tcp的Keepalive状态保持或者重用机制,一条连接的建立不会被中断父子组件生命周期函数调用顺序执行顺序:父组件开始执行到beforeMount 然后开始子组件执行,最后是父组件mounted。如果有兄弟组件,父组件开始执行到beforeMount,然后兄弟组件依次执行到beforeMount,然后按照顺序执行mounted,最后执行父组件的mounted。当子组件挂载完成后,父组件才会挂载。当子组件完成挂在后,父组件会主动执行一次beforeUpdated/updated钩子函数(仅首次)父子组件在data变化中是分别监控的,但是更新props中的数据是关联的。销毁父组件时,先将子组件销毁后才会销毁父组件。兄弟组件的初始化(mounted之前)是分开进行,挂载是从上到下依次进行当没有数据关联时,兄弟组件之间的更新和销毁是互不关联的既然函数是引用类型,为什么 vue 的 data 还是可以用函数?Js中只有函数才会构成作用域,对象的{}和if的{}不构成,data是一个函数的时候每个组件实例都可以有自己的作用域,互不影响Vue中哪个生命周期内调用异步请求Created beforeMount mounted推荐在Created的钩子函数中调用异步请求Created能更快的获取到服务器端的数据,减少页面加载时间$nextTick由于vue dom更新是异步的,所以修改数据的时候不会立马更新,而是通过监听数据的变化,并缓存在同一事件循环之中,当前事件循环所有数据变化完成后在统一进行更新数据。使用$nextTick就是为了获取页面更新后的dom和数据。原理:运用宏任务和微任务定义一个异步的方法。V-if v-show 异同Vuex--vue中的状态管理工具Actions:修改异步请求(使用commit提交) 第一个默认参数是{commit}mutations:同步更改state状态 第一个默认参数是stategetter:对state中的数据进行过滤首页白屏如何解决路由懒加载 cdn加速 开启vue服务渲染模式 减少打包体积删除不必要的代码也可以添加loading效果,增强用户体验路由跳转和location.href的区别?路由跳转静态调整不刷新页面,location.href刷新页面Computed和watch区别Computed里的属性名是自定义的,可以监听一个或者多个所依赖的数据项,watch一次只能监听一个属性,这个属性的函数有两个参数,一个新值一个旧值Computed的自定义属性不能与data里面的重复,watch则必须是已经存在的属性Watch允许异步操作以及设置中间状态,Computed不可以混入 mixin 分发vue组件中可复用的功能(和公共组件差不多)1 定义一个混入对象(包含任意组件选项,例如created,methods等)2 定义一个使用混入对象的组件Var Component = Vue.extend({Mixins:[定义的混入对象] })3 var component = new Component()4 此时component 这个组件就拥有了混入对象的所有组件选项5 当使用混入对象的组件与混入对象有同名选项的时候会进行合并,本身的优先6 混入对象的钩子在组件自身钩子之前调用Vue提升性能的几种办法?懒加载 少用v-if 组件拆分,组件内部的运行不会影响其他外部组件 使用keep-alive切换路由 v-for加key 虚拟DOM和diff算法虚拟dom 通过js的object对象模拟dom中的节点,然后再通过特定的render方法将其渲染成真实的dom节点,最后通过appendChild()添加到页面中去,比操作真实dom节点更加节省性能。Diff算法对比新老虚拟DOM,记录变化,将变化部分更新到视图上。对操作前后的dom树同一层的节点进行对比,然后一层一层的对比下去。当一层节点有很多的时候也是会一个一个的对比,但是如果增加了一个key,diff算法就能够更快的识别更改的节点,并对其进行更改。Vue列表为什么加keyKey可以标识组件的唯一性,区别各个组件的key是为了可高效的更新虚拟DOM如何进行路由跳转?声明式导航和编程式导航。声明式导航就是router-link,编程式导航就是this.$router.push|replace。如果在进行路由跳转的时候还有其他事情要做,就可以使用编程式导航,因为是在方法中定义的。Push和replace区别,push能够记住历史,repalce不能记住(登陆后后退不能返回到登录页面)路由跳转的时候所带的参数params和query参数区别params参数:路由需要占位,属于URL当中一部分。 query参数,路由不需要占位,写法类似于ajax当中query参数。query传参需要配置path,params需要配置name,在params中配置path无效。query在路由配置中不需要设置参数,params必须设置。query传递的参数会显示在地址栏。params传参刷新后无效,query会保存传过来的值。编程式导航跳转到当前路由(路由未变的跳转),会报错,解决办法重写vue原型上的push和replace如果params的数据是’’,无法跳转如何解决?指定params参数值为undefined路由组件能不能传递props数据?可以,将query参数或params参数转换成props传递props: (route)=>({keyword1:route.params.keyword, keyword2: route.query.keyword })控制某个组件的显示和隐藏(即大部分情况下要用到,偶尔用不到)在路由的配置中利用meta配置和v-show实现。在使用组件的时候使用v-show对meta判断
2022年06月14日
36 阅读
0 评论
0 点赞
2022-06-14
浏览器
问题常见状态码?http的几种请求方法?Get和post区别?减少网页加载的办法?http协议中的header及含义?浏览器事件传输机制以及应用场景?LocalStorage、sessionStorage、indexexDB?浏览器事件循环机制?浏览器渲染过程?浏览器中的回流和重绘?Iframe?Defer和async的区别?同源策略与跨域?触发跨域场景?跨域问题解决方案?Cookie,token,session storage, localStorage 区别?Cookie中的属性?输入Url后的过程?浏览器垃圾回收机制?浏览器缓存机制?常见安全问题?常见http请求头和响应头?http和https区别?https中间人攻击?Http1.x,http2.x区别?Ajax原理?CDN?答案:常见状态码200 成功 301 永久重定向 302 临时重定向 304 命中缓存 403 没权限 404 服务器上没找到该资源 505服务器错误301和302区别相同:都表示重定向,即拿到这个状态码后会跳转到其他url不同:301是永久移除了之前的网站,302是以前网站还存在,只不过换了连接。http的几种请求方法Get 获取服务器资源,参数长度有限制,最长2048字节,明文传播,会在链接中显示Post 向服务器提交数据 无限制 放在请求体中传播Put 修改服务器资源Delete 删除服务器资源Get和post区别Get数据显示在url中,post数据不会显示在url中Get对数据长度有限制,最长是2048个字符,post无限制Get可收藏为书签,post不可以Get后退按刷新无影响,post数据会被重新提交编码类型不同Get历史参数会保留在浏览器历史中,post不会post更加安全get请求只会有一次tcp连接,post请求有两次减少网页加载的办法服务器:Cdn加速 gzip压缩 开启强缓存或者协商缓存 增加服务器带宽客户端:优化代码 减少dom操作添加事件委托 防抖节流 懒加载 精灵图 少用iframe浏览器事件传输机制---为了解决页面中事件发生顺序的问题事件触发的三个阶段----捕获阶段--目标阶段--冒泡阶段和定时器一样多一个参数,true代表捕获阶段,从外到内触发 1 2 3 False代表冒泡阶段,从内到外触发 3 2 1LocalStorage与sessionStorage、indexexDB相同:都是web存储的范畴 用于存储客户的本地数据 存储数据都是5m 同源且同步不同:数据生命周期来看LocalStorage被主动清理前一直有,sessionStorage关闭页面就没了indexexDB,是浏览器自带的数据库,包括索引、事务处理和查询功能特点:存储是以键值对形式存储的,所有类型数据都可以存储是异步的,操作的时候不会锁死浏览器。Webstroage是同步的支持事务 不能跨域 存储空间大 支持二进制存储事件循环机制的执行顺序首先,js执行代码分为同步任务和异步任务,同步任务会放到栈中依次执行,而异步任务是会放在任务队列中等到同步任务执行完毕后才执行,异步任务又分成宏任务和微任务,先执行宏任务,在执行宏任务产生的微任务,如果微任务中产生了微任务,那么则会等待宏任务的下一轮循环,先把首次遇到的微任务执行完毕,然后继续执行,等到没有任务可以执行的时候再去执行又产生的微任务浏览器渲染过程 DOM --- CSDOM --- render tree --- 回流得到节点几何信息 --- 重绘得到节点像素 --- 绘制浏览器中的回流和重绘回流--重新绘制当前整个页面,包括整个结构和样式重绘--重新绘制当前页面样式如何避免?1 最小化回流和重绘的次数2 使用文档片段fragmentIframe在Iframe标签可以定义图片网页等内容,当页面中代码大量相同的时候可以使用该标签将重复的部分嵌入优点:1 原封不动嵌入网页 2 多个网页引用ifrme可以只修改其中内容就全部修改3 增加复用性缺点:1 阻塞主页面onload事件(页面或图像加载后立即发生的事件就是onload)2 用的多的时候会导致滚动条多3 代码复杂,不利于搜索引擎优化4 兼容性差,增加服务器http请求Defer和async的区别主要是在执行时间,defer会在文档解析之后执行,并且多个defer会按照顺序执行,async则是在j's加载之后就会执行,并且在多个async 的时候是哪个加载好就执行哪个同源策略 协议 端口 域名是一个安全策略,限制文档的交互,避免恶意文档减少攻击。跨域 --- 协议 端口 域名任意一个不同触发跨域场景1.域名不同 (www.yangwei.com 和www.wuyu.com 即为不同的域名)2.二级域名相同,子域名不同 (www.wuhan.yangwei.com www.shenzheng.yangwei.com 为子域不同)3.端口不同,协议不同 ( http://www.yangwei.com 和https://www.yangwei.com属于跨域www.yangwei.con:8888和www.yangwei.con:8080)跨域问题解决方案1 jsonp利用script标签没有跨域限制的漏洞(src属性),网页可以得到从其他来源动态产生的json数据,也就是说从src标签访问跨域的数据是不会报错的,但是需要对方服务器做支持才可以(https://www.baidu.com?callback=getData)具体实现就是 然后在就可以访问跨域网址里面的东西了,再和后端商量函数或者变量的名称就可以直接调用了优点 兼容性好 缺点 仅支持get,容易XSS攻击Cors 跨域资源共享跨域资源共享是一种机制,它使用额外的http头来告诉浏览器,让运行在一个origin上的web应用被准许访问来自不同源服务器上的制定的资源。当一个资源从该资源本身所在的服务器不同的域、协议或者端口请求一个资源的时候,资源会发起一个跨域http请求设置方法:设置头部origin 然后设置方法get,post 就可以两种请求都可以了2 postMessagepostMessage是HTML5 XMLHttpRequest Level 2中的API,且是为数不多可以跨域操作的window属性之一,它可用于解决以下方面的问题:页面和其打开的新窗口的数据传递多窗口之间消息传递页面与嵌套的iframe消息传递上面三个场景的跨域数据传递3 nginx反向代理搭建一个中转的nginx服务器,用于转发请求。因为nginx服务器可以直接访问服务器的资源不像前端有同源策略的限制,所以利用nginx转发浏览器的请求浏览器的主要组成部分用户界面 除了主页面外其他的页面以及功能(前进后退书签菜单等)用户界面后端 绘制基本的窗口小部件浏览器引擎 在用户界面和呈现引擎之间传送指令js解析器 解析和执行js代码渲染引擎 负责显示请求的内容,如果是http请求,就解析html和css数据存储模块 持久层,保存各种数据,ck,sessionStorage,localstorage网络模块 用于网络调用4 websocket建立连接的时候需要http协议,连接建立之后通讯就与HTTP无关了4 iframe4.1通过iframe嵌套传递,首先是主页面通过location.hash将数据传递给iframe,此时只要求两个不同的网站的url多了一个需要传递的参数,然后再次通过iframe传给接下来的iframe,然后第二个iframe和主页面是同源的,就可以完成互相传递数据了(暴露数据,且url传递的数据值容易有XSS攻击)4.2 直接通过window.name 传递(第三方iframe引用该数据都可以获取,更风险)4.3 通过postMessage传递,postMessage要求同源,而主页面和iframe满足4.4 document.domain 必须同根域名Cookie,token,session storage, localStorage 区别?Cookie:同源的http请求中携带,一直在浏览器和服务器之间来回传递,起初是服务器通过response回复报文传到客户端,客户端在访问网页时在传给服务器进行校验,cookie中有个maxage来控制cookie的有效期Session:session是保存在服务器上的,服务器把客户端的信息记录在服务器上,从而验证身份,但是session对服务器压力大,尤其是session过大的时候,每次访问服务器都会更新session最后访问时间。Session的有效期是在长期间没有活跃的话删除,session需要cookie作为识别标志Cookie,Session区别:存放地方,Session安全(服务器),session服务器压力大,cookie 4k限制,session没有限制Token:和cookie类似,客户端通过登陆验证后,服务器会返回一个加密的token,再次访问服务器的时候会带上进行验证。但是存在哪里都行服务器浏览器都可以Token和Cookie区别:了解Token和Cookie区别首先要知道http协议无状态的含义,http协议无状态是指每次对数据进行处理的时候没有记忆能力,后续如果需要处理前面的信息,则必须重传。优点是响应快。cookie和session就是用于保持http连接的技术,用于在交互中存储状态。token无状态,服务器不需要去看是谁,cookie有状态,能够弥补http无状态问题,保存用户的登陆状态。cookie默认存储和默认发送不安全,token需要自己存储自己进行发送,并且没有跨域限制,所以token更加灵活。token可抵御csrf,因为token相对于cookie不容易伪造cookie只有4kb,因此一般只存一些关键信息,其他的用户信息都是存储在服务器的session中,服务器压力大。token是没有限制的,用户信息可以自行存储。Cookie中的属性CookieName 设置cookie的名字和值httpOnly 只能通过http响应报文新增或者更新cookie,客户端无法通过脚本读取expires cookie过期时间max-age 有效时间长度path 路径作用域,判断路径是否匹配所设置的作用域,不符合则不会带cookiedomain 设置cookie的作用域 (能够在突破跨域限制 a.taobao.com和b.taobao.com如果设置了domain=.taobao.com 就可以了)secure 开启安全模式,开启后只允许https下才可以保存cookiesameSite 在跨域时是否应该被发送,必须开启secure输入Url后的过程1 url解析 首先判断输入的是合法的url还是搜索词,然后完成字符编码的过程,浏览器还会进行安全检查等2 dns解析 浏览器缓存--本地hosts缓存--操作系统缓存—本地dns服务器缓存--根服务器--域名服务器(返回到本地dns并缓存信息)(dns劫持,拦截域名解析的请求,使得该域名ip换到其他的错误ip)3 tcp链接 应用层--传输层--网络层--链路层4 服务器处理请求5 浏览器接受响应6 渲染页面 dom cssom--render tree--布局--绘制浏览器垃圾回收机制(GC)浏览器的垃圾回收机制是指垃圾回收器会定期找出那些不在使用的变量然后释放其内存。由于垃圾回收机制开销比较大,所以并不会一直运行。只会清理局部变量。常用方法是标记清除,当函数运行时给所有的变量标记一个进入环境,该变量离开环境的时候标记离开环境(会自动排除全局变量和闭包变量),最后把这些被标记过的变量删除。浏览器缓存机制(从客户端读取资源)分为强缓存和协商缓存,强缓存不会向服务器发送请求,直接从缓存中读取资源,返回了200状态码。协商缓存会给服务器发送请求,根据请求携带的参数判断是否协商缓存,如果同意协商缓存会返回304状态码并带上新的参数给浏览器并通知浏览器从缓存中读取数据。缓存有关的header强缓存:expires是response header里的过期时间,浏览器在这个时间内的话就强缓存。Cache-control:可以设置max-age==xx(s) 代表在xx秒内可以强缓存协商缓存:1 etag和if-none-match:etag是上一次加载资源的时候服务器返回的response header,当要读取缓存的时候会首先把etag放到if-none-match中然后发送到服务器看服务器中的etag是否一样,一样的话允许缓存。Etag改变的条件是服务器的资源发生了变化2 last-modified和if-modified-since:latst-modified是该资源的最后一次更改时间,具体过程与上面相同。etag精度低性能高。浏览器缓存过程1 浏览器加载资源开始,服务器返回200,浏览器会在下载资源的同时把response header和请求的时间缓存下来。2 下一次加载资源的时候,比较时间差max-age,在时间段内就直接强缓存,时间过期就向服务器发送header带有if-none-match和if-modified-since3 服务器收到请求判断etag是否变化,没有变化就直接协商缓存(返回304),如果有改动则重新返回新的资源文件并带上新的etag值并返回2004 如果没有etag值则比较if-modified-since,成功返回304,失败返回新的last-modified和200用户:地址栏访问 F5刷新(协商缓存) ctrl+f5 跳过缓存直接拉取资源常见安全问题XSS 跨站脚本攻击--通过在目标网站页面注入恶意脚本,获取用户敏感信息(评论私信等),原因是因为遇到html标签里的script标签的时候会进行执行CSRF 跨站请求伪造--通过网站B对我们的网站A进行伪造请求,以受害者的请求发送信息(正常网站登录,诱导进入第三方网站,第三方网站有跳转正常网站的请求,然后服务器无法判断谁发的请求,达到以用户的名义恶意访问)Iframe 攻击者将目标网站通过iframe嵌套的方式嵌入自己网页,并将iframe设置成透明,诱导点击CDN劫持Clickjacking 透明的iframe框诱导点击解决办法XSS:大部分浏览器与框架(vue中不能再template中写script)都进行了修改,预防办法就是对用户输入的信息进行转义或者过滤CSRF:数据修改操作必须post;http协议中使用referer属性进行请求来源过滤请求地址添加token;添加验证码或者密码Iframe:sandboxCDN劫持:开启SRI,scrpit和link标签开启integrity,会验证文件哈希值与提供的哈希值Clickjacking: http中增加X-FRAME-OPTIONS,这个属性控制页面是否可以被嵌入iframe常见http请求头和响应头? 请求头:Accept--可以接受的服务器返回类型 Accept-Encoding--接受的编码方法Accept-languag--接受的语言 Connection-- keepalive或者falseHost--主要用于被请求资源的internet主机和端口号Referer--告诉服务器从哪里来的 cookie--响应头:.Cache-Control--缓存相关 Content-Type--告诉客户端,资源文件的类型,还有字符编码,乱码就是这个没有传对 Content-Encoding--告诉客户端编码的方式Date-- Expires--允许缓存的时间段 Last-Modified--上次修改时间 Connection--keepalive的话表示客户端还可以一直给服务器发消息Etag--缓存相关的标记值http和https区别https需要申请ca证书;http超文本传输协议明文传播,https是安全性的ssl(现在是tls了)加密传输协议Http80端口https443端口;http连接无状态https中间人攻击服务器向客户端发送公钥攻击者截取公钥,保留在自己手上攻击者生成伪造公钥,发给客户端客户端收到伪造的公钥,加密生成加密hash值发给服务器攻击者获得加密的hash值,用自己的私钥解密获得真密钥同时生成假hash值发送给服务器服务器用私钥解密获得假密钥服务器用假密钥加密传输信息防范方法:服务器给浏览器的公钥中加入ca证书,浏览器可以验证证书有效性Http1.x,http2.x区别http2.x使用二进制传输,1则是文本(字符串)传输http2.x支持多路复用,一个http请求实现多个http请求传输,可以用流ID进行标记http2.x支持头部压缩,客户端服务端维护一张信息表,之后只传输信息表上的索引http2.x 支持服务器推送,就是再未经客户端允许,主动向客户端推送内容Ajax原理Ajax是在不需要刷新页面的情况下,通过异步请求请求加载后台数据并呈现出来。例如表单验证是否登录成功,下拉框提示等原理相当于在用户和服务器之间加了一个中间层,让用户操作和服务器响应异步化。不会把所有的请求都递交服务器,需要表单验证等交给ajax引擎来做,需要服务器的数据的时候用ajax引擎发送创建过程创建XMLHttpRequest对象,也就是创建一个异步调用对象创建一个新的http请求,并指定该http请求的方法,url和验证信息设置响应http请求状态变化的函数发送http请求获取异步调用后返回的数据使用js和dom实现局部刷新XMLHttpRequestXMLHttpRequest对象用于在后台与服务器交换数据Promise封装ajax请求CDN在现有的因特网中增加一层新的网络架构,将网站的内容发布到离用户最近的网络边缘,提高访问速度。Cdn=镜像加缓存
2022年06月14日
37 阅读
0 评论
0 点赞
1
2