面试题2024年

顶部

简介遇到的困难、是如何解决的项目亮点盒子模型水平垂直居中的几种方式Flex弹性布局history和hash模式的区别构造函数和普通函数的区别new 关键字做了什么闭包URL到整个页面了哪些事情?回流(重排)重绘深浅拷贝Vue双向绑定原理原型链VUEXcomspanuted和watch的区别cookie、sessionStorage、localStorage函数防抖截流虚拟DOMv-if和v-shownextTick()Vue组件之间通信

Vue插槽事件循环机制宏任务和微任务路由性能优化ES6新特性总结前端跨域开发vue组件的步骤vue封装组件注意事项MVVM是什么H5页面适配spanC端、移动端JS 的事件流模型有哪些?什么是渐进式vue优缺点call、aspanspanly和bindforEach和maspan区别作用域和作用域链vue2和vue3的区别VUE2生命周期Vue3 生命周期setuspan()函数特性Webspanack和Vite的区别如下:Webspanack面试题Vite 的面试题:TypeScript面试题

懒加载和异步加载async和defer 异步加载的区别:HTML5新特性:css3新特性:画一个旋转的动画websocketBFC浮动带来的副作用css哪些属性不能继承

我叫胡斌,有7年前端工作经验,一共做了6个项目,3个app,3个pc端,其中包括保险投保系统,员工管理系统、公司运营视图系统、协同办公系统、低代码系统,用到的技术栈有vue、vue-cli、vuex、vue-router 、Elment UI、vant UI、JavaScript、HTML、CSS、axios、less、jQuery、echarts

遇到的困难、是如何解决的

是刚接手项目的时候,分到一个BUG,是一个表格的多条件筛选功能,问题是只能筛选当前页数据,不能筛选全量数据,我解决的方法是,先在测试环境运行项目,登录测试账号,复现这个问题,然后找到相应的代码,分析代码逻辑,经分析后,实现逻辑,是用element表格组件的column上的一个属性filter-method来过滤数据,查了下官网的API,这个属性,确实只能过滤当前展示的数据,那么这个问题根因已经找到了,目前的方案是不能满足需求的,需要新的方案,然后我查了一下官网的其它API,找到一个table事件,filter-change,当表格的筛选条件发生变化的时候会触发该事件,参数的值是一个对象,对象的 key 是每一列的columnKey,对应的 value 为用户选择的筛选条件的数组。那么这个方法就可以满足需求了,然后我就重构了一下筛选功能,先把原来的那个方案相关代码删除,在每一列加上自定义的columnKey,在vuex的store中定义一个变量,默认值为空对象,然后在筛选的事件回调中,若是筛选事件,则用键值对的形式存入到store这个变量中,键为columnKey,值为筛选的条件,若是重置筛选事件,则删除columnKey对应的键值对,这样就得到一个存储了所有筛选条件的对象,然后把所有的筛选条件从store中取出来,再组装成接口支持的入参格式,调用接口,获取数据,这个数据就是根据条件筛选全量数据后的结果,再赋值给表格展示用的变量,这个问题就解决了。

项目亮点

1.交互体验好:自动填写、快速复制、一键分享等功能受到用户的一致好评。

 2.响应式设计:可以让页面在不同设备上都有良好的展示效果。

3.前后端分离:前后端分离可以提高开发效率,降低耦合度。

 4.组件化开发:组件化开发可以提高代码复用率,降低维护成本

盒子模型

可以把页面的所有元素看成是一个一个的盒子模型,每个盒子模型包括:内容(content)、内边距(padding)、边框(border)、外边距(margin)

标准盒子模型占用大小为:内容(content)+内边距(padding)+边框(border)+外边距(margin)

IE盒子模型(也叫怪异盒子模型)占用大小为:内容(content) +外边距(margin)

box-sizing:属性可以设置content-box   标准盒子模型,border-box IE盒子模型

水平垂直居中的几种方式

1.使用flex布局

.father {

  display: flex;

  justify-content: center; /*水平居中*/

  align-items: center; /*垂直居中*/

}

2.使用grid布局

.father {

  display: grid;

  place-items: center; /*水平垂直居中*/

}

3.使用绝对定位和transform属性(父元素需要写高度)

.father {

    position: relative;

    height: 200px;

    background: skyblue;

}

.son {

  position: absolute;

  top: 50%;

  left: 50%;

  transform: translate(-50%, -50%); /*将元素自身的宽高的一半作为偏移量*/

}

4.使用position和margin属性(父子元素需要写宽高)

.father {

    position: relative;

    width: 200px;

    height: 200px;

    background: skyblue;

}

.son {

      width: 50%;

      height: 50%;

      position: absolute;

      top: 0; left: 0; bottom: 0; right: 0;

      margin: auto;

}

5.使用text-align和line-height(父元素要写高度)

.father {

    line-height: 200px;/*垂直居中关键*/

    text-align:center;

    height: 200px;

    font-size: 36px;

    background-color: #ccc;

}

Flex弹性布局

父元素属性

flex-direction  主轴排列方向 row | row-reverse | column | column-reverse;

flex-wrap  换行 nowrap | wrap | wrap-reverse;

justify-content 主轴对齐方式 flex-start | flex-end | center | space-between | space-around | space-evenly;

align-items 副轴对齐方式 flex-start | flex-end | center | stretch | baseline;

align-content 多条副轴对齐方式 flex-start | flex-end | center | stretch | space-between | space-around ;

2、子元素属性

order 排序,数值越小,排列越靠前,默认为 0 属性值 0 | 1 | 2 | ...

flex-grow 放大比例,默认为0,默认不放大,属性值 0 | 1

flex-shrink 缩小比例,默认为1,默认缩小, 属性值 1 | 0

flex-basis 子元素的大小,优先级高于width ,属性值 auto|xxPX

flex 属性是flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto。后两个属性可选。该属性有两个快捷值:auto (1 1 auto) 和 none (0 0 auto) 。属性值 auto | none | 1

align-self 子元素在副轴的对齐方式,优先级高于align-item,属性值 auto | flex-start | flex-end | center | baseline | stretch;

history和hash模式的区别

历史记录(history)模式和哈希(hash)模式都是前端路由的实现方式。在哈希模式中,路由路径被拼接在真实URL的井号(#)后面,而在历史记录模式中,路由路径直接作为真实URL的一部分。哈希模式的特点是在路径变化时,浏览器不会重新发起请求,而是触发hashchange事件;而历史记录模式利用window.history对象的方法来实现路由变化,并且可以修改浏览器的历史记录。

  1. 实现方式:hash模式利用浏览器地址栏URL中的#符号来实现路由,不会重新发起请求;history模式利用浏览器的历史记录栈来实现路由,可以改变后端资源。

  2. 外观美观性:hash模式看起来相对较丑,而history模式更加优雅。

  3. 兼容性:hash模式兼容性较好,可以兼容到IE8;history模式兼容性较差,只能兼容到IE10。

  4. SEO优化:hash模式不利于SEO(搜索引擎优化),而history模式对SEO更友好。

总的来说,hash模式在兼容性和不需要后端参与方面有优势,而history模式在外观美观性和SEO优化方面更有优势。在选择使用哪种模式时,可以根据具体的项目需求和技术要求来进行权衡和选择。

构造函数和普通函数的区别

构造函数是一种特殊的函数,用于创建和初始化对象实例。在 JavaScript 中,构造函数通常用于定义对象的属性和方法,以及为对象实例分配初始值。

  1. 调用方式不同:构造函数需要使用new关键字来调用,而普通函数直接调用即可。

  2. 作用不同:构造函数用于创建新实例对象,而普通函数用于执行特定的功能或任务。

  3. 函数命名习惯不同:一般构造函数的函数名称会用大写,而普通函数用小写。

  4. 函数中this的指向不同:在构造函数中,this指向新创建的实例对象,而在普通函数中,this的指向取决于调用函数的对象或者是全局对象。

总的来说,构造函数用于创建对象实例并初始化对象的成员变量,而普通函数用于执行特定的功能或任务。

new 关键字做了什么

总结来说,new 关键字的主要作用是创建一个新的对象实例,并且在构造函数中初始化这个新对象的属性和方法。

  1. 创建一个新的空对象。

  2. 将这个空对象的原型(__proto__)指向构造函数的原型(prototype)。

  3. 将构造函数中的 this 指向这个新创建的对象。

  4. 执行构造函数内部的代码,为这个新对象添加属性、方法等。

  5. 如果构造函数没有显式返回一个对象,则返回这个新对象实例;如果构造函数返回了一个对象,则返回该对象。

因此,new关键字实际上是创建了一个新的对象,并且将这个对象与构造函数的原型对象连接起来,以实现继承的效果。

闭包

当一个函数内部定义的函数引用了外部函数的变量时,就形成了闭包。

function fn1(){
    var arr = new Array[666666]
    function fn2(){
        console.log(arr.length)
    }
    return fn2
}
var f = fn1()
f()

闭包的好处:

1.闭包可以让一个变量长期保存在内存中不被释放,可以重复使用,不会造成变量污染

2.可以访问函数内部的私有变量或者私有数据。

3.可以用来定义私有属性和私有方法。

闭包缺点

由于闭包会使函数中的变量被保存在内存中,所以不能滥用闭包,否则会造成网页的性能问题。解决方法在退出函数之前,将不用的闭包释放掉。

解决闭包缺点:把声明接收返回函数的那个变量设置成null

2.当把父函数作为对象使用,把闭包当做他公共方法,把内部变量当做他的私有属性时,这时一定要小心不要随便改变父函数内部变量的值

二、闭包的使用场景

  • 防抖和节流

防抖-在规定的时间内,多次触发函数,只执行最后一次

节流-在规定的时间内,多次触发函数,只执行第一次

  • 函数柯里化

柯里化是把接收多个参数的函数变换成接受一个单一参数的函数,并且返回接收余下参数的新函数的技术。

柯里化的好处:

一、让函数职责单一

1.在函数式编程中,我们其实往往希望一个函数的问题尽可能的单一,而不是将一大堆的处理过程交给一个函数来处理;
2.那么是否就可以将每次传入的参数在单一的函数中进行处理,处理完后在下一个函数中再使用处理后的结果;

二、逻辑的复用,不同的功能,传入不同的参数,可以使用同一个柯里化函数。调用柯里化函数的时候,如果某一个参数在每次调用中都相同,可以避免重复传入这个参数。

URL到整个页面了哪些事情?
  1. DNS解析:当用户在浏览器中输入网站的URL时,浏览器会向DNS服务器发送请求,DNS服务器会将域名转换为对应的IP地址。
  2. 建立连接:浏览器通过TCP协议与服务器建立连接,通过三次握手,确保双方都能够通讯。
  3. 发起请求:建立连接后,浏览器会向服务器发送HTTP请求,请求包括获取网页内容的具体信息。
  4. 服务器处理请求:服务器接收到请求后,会根据请求的内容进行相应的处理,包括读取网页文件、数据库查询等操作。
  5. 返回响应:服务器处理完请求后会返回相应的数据,通常是HTML、CSS、JavaScript等网页文件。
  6. 浏览器渲染:浏览器接收到服务器返回的数据后,会开始对网页进行渲染,包括html被html解析器解析成DOM Tree,css被css解析器解析成CSSOM Tree;DOM Tree 和 CSSOM Tree 合并到一起,形成 Render Tree ;重排,根据渲染树计算出每个节点的几何信息,位置及大小;重绘,绘制渲染出最终的页面。

常见状态码:200表示请求成功;403 服务器拒绝请求;404表示请求的资源未找到;500表示服务器内部错误。

回流(重排)

元素的尺寸和位置发生变化,就需要重新计算渲染树,这就是回流

DOM元素的几何特性(width、height、padding、margin、border)发生变化时会触发回流

DOM元素移动或者增加会触发回流

读写offset、scroll、client等属性时会触发回流

调用window.getComputedStyle会触发回流。

重绘

DOM样式发生变化,但是没有影响DOM的几何属性时,会触发重绘,而不会触发回流。重绘由于DOM位置信息不需要更新,省去了布局的过程,因而性能上优于回流。

如何减少回流和重绘

  1. 减少对 DOM 的操作:避免频繁地对单个 DOM 进行操作,尽量批量处理样式修改。可以缓存 DOM,减少 DOM 深度和数量,以及批量操作 DOM。

  2. 使用 transform 和 opacity 实现动画效果:它们可以开启 GPU 加速,减少回流和重绘。

  3. 将需要多次重绘的元素独立为 render layer 渲染层,如设置 absolute,可以减少重绘范围。

  4. 避免使用表格布局,因为可能很小的一个小改动会造成整个表格的重新布局。

  5. 避免频繁读取导致回流的属性值,例如 offsetTop、offsetLeft、clientWidth 等。

深浅拷贝

浅拷贝只是复制了对象的引用地址,两个对象实际指向同一个内存地址。因此,如果两者任意一个发生了改变,那么另一个也会随之改变。

深拷贝则是创建一个完全独立的新对象,新对象中的元素是原对象中元素的复制品,而不是引用。所以,即使原对象中的元素发生了改变,深拷贝的对象中的元素也不会受到影响。

浅拷贝:

(1)Object.assign()

var obj1={a:1,b:2};

var obj2=Object.assign(&,obj1);

(2)解构赋值

var obj2={...obj1};

深拷贝

JSON.parse(JSON.stringify(obj)),这个方法只能适用于一些简单的情况。

如果你的对象里有函数,函数无法被拷贝下来

原型链上的属性和方法也无法拷贝下来

2、深拷贝的实现,for  in + 递归(for   in 遍历键,for of 遍历值)

•     深拷贝,就是遍历那个被拷贝的对象

•     判断对象里每一项的数据类型

•     如果不是对象类型,就直接赋值,如果是对象类型,就再次调用deepCopy,递归的去赋值。

function deepCopy( source ) {

    let target = Array.isArray( source ) ? [] : {}

    for ( var k in source ) {

        if ( typeof source[ k ] === 'object' ) {

            target[ k ] = deepCopy( source[ k ] )

        } else {

            target[ k ] = source[ k ]

        }

    }

    return target

}
一个方法重复调用自身的情况叫做递归,但是需要注意的是,一定要有一个条件来结束递归,否则将会陷入无限的循环

3、深拷贝:还可以使用第三方库,lodash 中的cloneDeep函数,JQ里有$.extend()函数

Vue双向绑定原理

vue数据的双向绑定是通过数据劫持结合发布者和订阅者模式的方式来实现的。

主要是以下步骤实现的:

实现一个监听器 Observer:对数据对象进行遍历,包括子属性对象的属性,利用 Object.defineProperty() 对属性都加上 setter 和 getter方法。这样的话,给这个对象的某个值赋值,就会触发 setter,那么就能监听到了数据变化。

实现一个解析器 Compile:解析 Vue 模板指令,将模板中的变量都替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,就调用更新函数进行数据更新。

实现一个订阅者 Watcher:每个组件实例都对应一个 watcher 实例,Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁 ,主要的任务是订阅 Observer 中的属性值变化的消息,当收到属性值变化的消息时,就触发解析器 Compile 中对应的更新函数。

Watcher 主要做的事情是: ① 在自身实例化时往属性订阅器(dep)里面添加自己; ② 自身必须有一个update()方法; ③ 待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调。


相关题目一:Vue 怎么监听数组变化的

为什么只对对象劫持,而要对数组进行方法重写?
因为对象最多也就几十个属性,拦截起来数量不多,但是数组可能会有几百几千项,拦截起来非常耗性能,所以直接重写数组原型上的方法,是比较节省性能的方案

数组考虑性能原因没有用 defineProperty 对数组的每一项进行拦截,
而是选择对 7 种数组(push,shift,pop,splice,unshift,sort,reverse)方法进行重写


(2)数据劫持
通过 Object.defineProperty() 方法实现的,vue 在内部会把定义在 data 中的属性通过这个方法全部转为 getter/setter,在数据变化时发布消息给订阅者,触发相应的监听回调,也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随之发生改变

原型链

原型链是JavaScript中的一种机制,用于实现对象之间的继承关系。每个对象都有一个指向其原型(prototype)的链接,而原型本身也是一个对象。当访问一个对象的属性或方法时,JavaScript引擎会先在对象本身查找,如果找不到,就会继续在原型对象上查找,以此类推,直到找到匹配的属性或方法,或者到达原型链的末尾(即null)为止。原型链的作用是实现对象的继承和多态,通过链式结构实现属性和方法的继承和重用。

二.原型链的作用
通过原型链,子类实例可以访问父类原型上的方法,实现了代码的重用和简化。原型链的作用是实现继承,简化代码,实现代码重用。在实际开发中,原型链可以通过继承来实现对象之间的联系和共享方法,从而提高代码的可维护性和重用性。

三.实现继承

定义父类函数,将父类的属性和方法添加到父类函数的prototype对象上,然后定义子类函数,并将子类的prototype指向父类的实例。

四.隐式原型和显示原型的区别
在过去我们常用__proto__表示隐式原型(它其实就是[[Prototype]])。用prototype代表显示原型。
每个对象(数组,对象,函数)都有自己的__proto__,通过__proto__可以添加数据到原型,也可以通过它一层一层查找数据。构造函数默认会有prototype属性,prototype属性是用来继承的,实例化之后__proto会指向构造函数的prototype。

函数有原型对象prototype, hasOwnProperty方法,可以判断一个属性是否来自对象本身。

简单回顾下构造函数,原型和实例的关系:

每个构造函数(constructor)都有一个原型对象(prototype),原型对象都包含一个指向构造函数的指针,而实例(instance)都包含一个指向原型对象的内部指针.

JS对象的圈子里有这么个游戏规则:

如果试图引用对象(实例instance)的某个属性,会首先在对象内部寻找该属性,直至找不到,然后才在该对象的原型(instance.prototype)里去找这个属性.

VUEX

state: 用来存储公共数据的(变量),类似于组件中的data。
mutations:数据修改的逻辑,也是唯一修改state数据的地方。(提交更新数据的方法),它必须是同步操作,如果有异步操作的话,那么就需要actions。
actions:它也是用来改变数据的,但是它无法直接修改数据,actions提交的是mutations,在mutations里面更改数据,actions支持异步操作。
getters:从基本数据,派生过来的数据,相当于组件里的计算属性computed。
modules:是用来模块化vuex的,可以让每一个模块拥有自己的state、mutation、actions、getters使得结构更加清晰,方便管理。

computed和watch的区别

功能:computed是计算属性;watch是监听一个值的变化执行对应的回调
2、是否调用缓存:computed函数所依赖的属性不变的时候会调用缓存;watch每次监听的值发生变化时候都会调用回调
3、是否调用return:computed必须有;watch可以没有
4、使用场景:computed当一个属性受多个属性影响的时候;例如购物车商品结算;watch当一条数据影响多条数据的时候,例如搜索框
5、是否支持异步:computed函数不能有异步;watch可以

cookie、sessionStorage、localStorage

存储空间:cookie存储空间最小、只有4kb、但是http请求中可以携带cookie,loacalstorage、sessionstorage存储空间5m或更大
2、有效期:cookie可以设置一个规定的时间,若不设置时间、则关闭游览器销毁,sessionstorage关闭游览器(窗口或者标签页)销毁,loacalstorage如果不手动清除则一直保留
3、作用域:sessionStorage不在不同游览器窗口(标签页)共享、即使同源,cookie、localstorage在所有同源窗口之间共享

4.cookie可以服务端通信,loacalstorage、sessionstorage不参与服务端通信

cookie场景:验证用户登录信息

sessionstorage:临时数据

localstorage:静态资源、持久化登录

函数防抖截流

①防抖:是在规定的时间内连续触发函数,只执行最后一次,并重新计算时间

防抖场景:

搜索框搜索输入。只需用户最后一次输入完,再发送请求

输入内容的校验

窗口大小 Resize。只需窗口调整完成后,计算窗口大小。防止重复渲染。

②节流:是在规定的时间内连续触发函数,只能执行第一次,并计时开始,直到规定时间结束,才能执行下一次。

截流场景:

1.滚动加载

2.搜索框的联想功能

3.高频点击提交,表单重复提交

两者目的都是,降低回调执行频率。节省计算资源。

虚拟DOM

虚拟DOM是一种用JavaScript对象表示的轻量级的DOM结构,用于描述视图的界面结构。在Vue中,每个组件都有一个render函数,每个render函数都会返回一个虚拟DOM树,这也就意味着每个组件都对应一棵虚拟DOM树。虚拟DOM的主要作用是在渲染时使用虚拟DOM来替代真实DOM,以解决渲染效率的问题。在Vue中,虚拟DOM最终会转换为真实DOM,通过一系列操作使虚拟DOM树映射到真实环境上。

虚拟DOM的实现可以通过JavaScript对象来模拟DOM结构,并通过Diff算法等实现最新改动更新。在Vue和React中,虚拟DOM的优点包括批处理和高效的Diff算法,以及跨平台能力。然而,虚拟DOM也存在缺点,例如首次渲染性能较慢,以及理想的DOM diff算法需要大量的遍历操作。

综合而言,虚拟DOM是一种用于提高渲染效率和优化视图更新的机制,通过JavaScript对象来模拟DOM结构并实现更新操作。在Vue和React等框架中,虚拟DOM的应用为跨平台能力和性能优化提供了支持。

v-if和v-show

v-if是真正的条件渲染,会根据条件动态创建或销毁元素,因此在频繁切换时会有较大的性能消耗。它适合在条件很少改变的情况下使用。

v-show则始终会渲染元素,只是通过CSS的display属性来控制元素的显示和隐藏,因此在频繁切换时性能消耗较小。它适合在需要非常频繁地切换元素显示状态的情况下使用。

总的来说,v-if适合在条件较少改变的情况下使用,而v-show适合在需要非常频繁地切换元素显示状态的情况下使用。

V-if为什么不能和v-for一起使用

因为这样使用会导致重复渲染,影响性能

nextTick()

nextTick()方法的作用是在DOM更新循环结束后执行延迟回调,以确保在操作DOM时数据已经完成更新。

nextTick()的使用场景:

  1. 在数据变化后立即操作DOM:当需要在Vue实例数据发生变化后,立即操作更新后的DOM时,可以使用nextTick()方法来确保在DOM更新之后执行操作。

  2. 异步更新数据后的回调:有时候需要在数据发生改变后执行一些回调函数,但希望这些回调函数是在DOM更新之后执行的,这时可以使用nextTick()。

  3. 在Vue生命周期钩子函数中的操作:在Vue的生命周期钩子函数中,有时需要在DOM更新之后执行一些操作,这时可以使用nextTick()来确保在适当的时机执行这些操作。

总的来说,nextTick()方法适用于需要在DOM更新之后执行的操作,特别是在数据变化后立即操作DOM或需要在Vue生命周期钩子函数中进行操作时。

Vue组件之间通信

父子组件通信: props;$refs; $parent / $children;

兄弟组件通信: eventBus ;  vuex,sessionstorage,localstorage,路由跳转传参

跨级通信:  eventBus;Vuex;provide / inject 、$attrs / $listeners

  1. 父子组件通信:父组件通过props向子组件传递数据,子组件通过$emit触发事件通知父组件。

  2. 子父组件通信:子组件通过this.$parent直接访问父组件的数据和方法,但这种方式不够灵活且不推荐使用。

  3. 兄弟组件通信:可以通过一个共享的父组件作为中介,将数据通过props传递给共享的父组件,再通过$emit和$on传递给需要通信的兄弟组件。

  4. 使用EventBus:创建一个空的Vue实例作为事件总线,通过$emit和$on来触发和监听事件,实现任意组件之间的通信。

  5. 使用Vuex:Vuex是Vue官方推荐的状态管理工具,适用于大型项目中的组件通信和状态管理。

  6. 使用$refs:可以通过$refs直接访问子组件实例,从而调用子组件的方法和访问子组件的数据。

BFC

是块级格式化上下文,他的特性是可以看作是隔离的独立容器,容器里面的元素不会在布局上影响到外面的元素

作用

1.清除浮动。

2 防止外边距合并

3.避免与浮动元素的重叠。

浮动带来的副作用

1. 块状元素,会钻进浮动元素的下面,被浮动元素所覆盖

2. 行内元素,例如文字, 则会环绕在浮动元素的周围,为浮动元素留出空间

3. 浮动元素的父元素坍缩

解决浮动的副作用方法:
                clear  清除浮动
                2、给父级添加高度 height
                    有的时候是不能给父级添加高度的,所以这个方法就用不了(父级没有高度的情况下)
                3、父级设置 display: inline-block
                4、overflow:hidden;
                    如果子级有定位的话,并且这个定位超出了父级的范围,那样的话就看不到了,所以不能加这个命令
                5、after伪类清除浮动(现在最主流的方法)
                    after       代表选择到的元素的内容的最后面
                                after伪类的内容默认是一个行内元素
                    content     设置的内容

  1. BFC的形成条件是什么? BFC形成的条件包括:

    • 根元素或包含根元素的元素

    • 浮动元素(float不为none)

    • 绝对定位元素(position为absolute或fixed)

    • 行内块元素(display为inline-block)

    • 表格单元格(display为table-cell)

    • 表格标题(display为table-caption)

    • 包含以上元素的块级盒子

  2. 如何创建一个BFC? 可以通过以下方式来创建一个BFC:

    • 设置元素的float属性为leftright

    • 设置元素的position属性为absolutefixed

    • 设置元素的display属性为inline-blocktable-celltable-caption

    • 使用overflow属性的值不为visible的块级元素

Vue插槽

就是子组件中提供给父组件使用的一个占位符,用<slot></slot> 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的<slot></slot>标签。

事件循环机制

事件循环是指在JavaScript中用于处理异步操作的一种机制。JavaScript是单线程语言,意味着它一次只能执行一个任务。然而,由于存在需要等待的异步操作(如定时器、网络请求、事件监听等),因此事件循环机制就显得非常重要。

事件循环的工作原理如下:

  1. 所有同步任务都在主线程上执行,形成一个执行栈(Execution Stack)。

  2. 当遇到异步任务时,会被挂起并放到任务队列(Task Queue)中。

  3. 一旦执行栈为空,主线程就会去查看任务队列,如果有任务则将其放回执行栈中执行。

  4. 这个过程会不断重复,即使是异步任务,也会在主线程空闲时被执行。

这种机制保证了JavaScript的单线程不会被阻塞,同时能够处理大量的异步任务。事件循环的设计使得异步编程变得更加简单和高效。

宏任务和微任务

在 JavaScript 中,宏任务(Macro Task)和微任务(Micro Task)是用于管理异步代码执行顺序的概念。

宏任务通常包括整体代码、setTimeout、setInterval、UI 渲染等,它们会被放入宏任务队列中等待执行。

微任务通常包括 Promise、process.nextTick 等,它们会被放入微任务队列中等待执行。

在事件循环中,当执行栈为空时,会先执行所有微任务队列中的任务,直到微任务队列为空,然后再执行宏任务队列中的任务。这个过程会不断重复,直到所有任务执行完毕。

路由

Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。路由实际上就是可以理解为指向,就是我在页面上点击一个按钮需要跳转到对应的页面,这就是路由跳转;

路由守卫有三种:
1:全局钩子: beforeEach、 afterEach
2:独享守卫(单个路由里面的钩子): beforeEnter、 beforeLeave
3:组件内守卫:beforeRouteEnter、 beforeRouteUpdate、 beforeRouteLeave
每个守卫方法接收三个参数:

①to: Route: 即将要进入的目标路由对象(to是一个对象,是将要进入的路由对象,可以用to.path调用路由对象中的属性)②from: Route: 当前导航正要离开的路由③next: Function: 这是一个必须需要调用的方法,执行效果依赖 next 方法的调用参数。

1、全局的路由钩子函数

1.1、beforeEach(全局前置钩子),意思是在每次每一个路由改变的时候都要执行一遍

它有三个参数:

to: route:即将要进入的目标 路由对象

from:route:当前导航正要离开的路由

next:function:一定要调用该方法来resolve这个钩子。执行效果依赖next方法

应用场景:

1、进行一些页面跳转前的处理,例如跳转到的页面需要进行登录才可以访问时,就会做登录的跳转

2、进入页面登录判断、管理员权限判断、浏览器判断

1.2、afterEach(全局后置钩子)

beforeEach是在页面加载之前的,而afterEach是在页面加载之后的,所以这些钩子是不会接受next函数,也不会改变导航本身

2、单个路由内的钩子函数

2.1、beforeEnter

可以直接在路由配置上直接定义beforeEnter,这些守卫与全局前置守卫的方法参数是一样的

3、组件内的路由钩子函数

beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave

应用场景

1、清除组件中的定时器

2、当页面有未关闭的窗口,或未保存的内容时,阻止页面跳转

3、保存相关内容到Vuex和Session中

旧的路由组件beforeRouteLeave

全局配置的beforeEach

复用的路由组件beforeRouteUpdate

新路由的beforeEnter

新路由组件的beforeRouteEnter

全局配置的beforeResolve

navigate执行完毕后,会调用triggerAfterEach函数,触发afterEach

动态路由:

在Vue中,动态路由是指路由路径中的一部分是动态的,也就是说路由的参数是根据实际情况动态变化的。使用动态路由可以让我们根据不同的参数值加载不同的页面内容,而不需要为每个可能的路由都编写单独的路由规则。

在Vue中,我们可以通过在路由路径中使用冒号(:)来定义动态路由参数。

 
  1. // 定义动态路由

  2. const routes = [

  3. {

  4. path: '/user/:id',

  5. component: User

  6. }

  7. ];

首先我们来学习三个单词(route,routes,router):

  route:指路由对象表示当前活跃的路由this.$route.meta.num

  routes:指创建vue-router路由实例的配置项,用来配置多个route路由对象

  router:路由器对象,new出来的路由器对象VueRouter,包含一些操作路由的功能函数,来实现编程式导航。如访问路由:$router.push()和router.replace()

  1. 请介绍一下Vue Router的基本用法和核心功能。 答:Vue Router是Vue.js官方的路由管理器,用于构建单页应用。它可以通过定义路由和组件的映射关系来实现页面的跳转和导航。Vue Router的核心功能包括路由映射、路由导航、路由参数传递和路由守卫等。

  2. 如何在Vue中定义路由? 答:在Vue中定义路由需要先安装Vue Router,并在Vue应用中引入Vue Router插件。然后通过创建一个Router实例,定义路由规则和对应的组件,最后将Router实例注入到Vue实例中。

  3. 请解释一下Vue Router中的动态路由是什么,如何使用? 答:动态路由是指在路由路径中包含动态参数,这样可以根据不同的参数显示对应的页面。在Vue Router中,可以通过在路由路径中使用动态参数来定义动态路由,例如/user/:id,然后通过$route.params.id来获取动态参数的数值。

  4. 如何在Vue Router中实现路由导航守卫(路由拦截)? 答:Vue Router提供了路由导航守卫,包括全局前置守卫、全局后置守卫、路由独享的守卫和组件内的守卫。可以通过beforeEach、afterEach、beforeRouteEnter等方法来实现路由导航守卫。

  5. 请说明一下Vue Router中的路由懒加载是什么,如何实现? 答:路由懒加载是指在路由被访问时才加载对应的组件,而不是在应用初始化时就加载所有的组件。在Vue Router中,可以通过动态import语法或者使用工厂函数返回组件的方式来实现路由懒加载。

当 install 方法被同一个插件多次调用,插件将只会被安装一次。

性能优化
  1. 压缩和合并资源:压缩HTML、CSS和JavaScript文件,减小文件体积,并将多个文件合并成一个,加快页面加载速度。

  2. 图片优化:使用适当的图片格式(如WebP、svg等)、压缩图片,以减小图片文件大小,提高页面加载速度。

  3. 使用CDN(内容分发网络):通过CDN来分发网站的静态资源,减少服务器负载并加快资源加载速度。

  4. 延迟加载:延迟加载页面中的图片、视频等资源,只有在用户滚动到可见区域时才加载,减少初始加载时间。

  5. 使用异步加载:通过异步加载JavaScript和CSS文件,减少页面加载时间。

loadScript函数用于动态创建一个script标签,并设置其src属性为指定的JavaScript文件URL,然后将该标签添加到head标签中,以实现异步加载。同时,可以通过设置script标签的onload事件来监听JavaScript文件的加载完成。

loadCSS函数用于动态创建一个link标签,并设置其href属性为指定的CSS文件URL,然后将该标签添加到head标签中,以实现异步加载。

  1. 缓存优化:利用浏览器缓存和HTTP缓存机制,设置合适的缓存策略,减少重复的网络请求。

  2. 减少HTTP请求:使用雪碧图或者字体图标等方式来减少页面的HTTP请求次数。

  3. 代码优化:避免不必要的重绘和回流,尽量减少DOM操作,使用事件委托,防抖节流等优化代码性能。

  4. 响应式设计:采用响应式布局来适配不同设备和屏幕尺寸,提高页面的适用性和用户体验。

  5. 预加载和预渲染:通过预加载和预渲染技术,提前加载页面所需的资源和内容,以提高页面加载速度和用户体验。

ES6新特性总结

let、const 块级作用域

let 表示申明变量。const 表示申明常量。常量定义了就不能改了。const在申明是必须被赋值。

2. 模块字符串``

可以使用反引号``来进行字符拼接。${}

3. 解构赋值

可以使用[]{}来对数组和对象进行解构。

4. 函数的参数可以设置默认值

函数传参可以设置默认值

5. ...扩展运算符

JavaScript中的一种语法,其主要作用是将数组或对象进行展开。扩展运算符可以用于函数调用、数组、字符串、对象中,它的作用是将表达式拆分为独立的元素,或者将多个元素合并为一个整体。这种语法可以简化代码并提高代码的可读性。

用途:(1)复制数组 const a1 = [1, 2]; const a2 = [...a1];

(2)合并数组  const arr1 = ['a', 'b'];const arr2 = ['c'];[...arr1, ...arr2]

(3)与解构赋值结合 const [first, ...rest] = [1, 2, 3, 4, 5];first // 1 rest  // [2, 3, 4, 5]

(4)字符串转为真正的数组。[...'hello']  // [ "h", "e", "l", "l", "o" ]

(5)具有 Iterator(遍历器) 接口的对象,都可以使用扩展运算符,比如 Set、Map数据

6. 箭头函数

箭头函数和普通函数的区别主要体现在以下几个方面:

  1. 外形不同:箭头函数使用箭头定义,而普通函数中没有箭头。

  2. 匿名性:箭头函数都是匿名函数,而普通函数可以是匿名函数也可以是具名函数。

  3. this指向不同:箭头函数的this始终指向定义时所在的外层函数的this,而普通函数的this指向取决于函数的调用方式。

  4. 构造函数:箭头函数不能用作构造函数,而普通函数可以通过new关键字用作构造函数创建对象实例。

  5. 参数对象:箭头函数不能使用arguments对象,而普通函数可以使用arguments对象来获取传入的参数。

7.proxy

Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。

8. class

ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。

9. 导入导出

exportimportexport导出,import导入

10. promise

Promise是JavaScript中用于处理异步操作的对象。它有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。Promise对象代表一个异步操作的最终完成或失败,并返回相应的结果。

在使用Promise时,可以通过构造函数创建一个Promise对象,并在其内部执行异步操作。当异步操作成功完成时,可以调用resolve方法将Promise状态变为fulfilled,并返回异步操作的结果;当异步操作失败时,可以调用reject方法将Promise状态变为rejected,并返回错误信息。

Promise对象具有thencatch方法用于处理异步操作的结果。then方法用于指定异步操作成功时的回调函数,catch方法用于指定异步操作失败时的回调函数。通过then方法可以进行链式调用,依次处理异步操作的结果。

  • finally 方法用于指定无论异步操作成功还是失败都要执行的回调函数。它会在前面的 then 或 catch 方法执行完毕后被调用。

  • all 方法用于将多个 Promise 实例包装成一个新的 Promise 实例。当所有的 Promise 实例状态都变为fulfilled时,包装实例才会变为fulfilled;只要有一个 Promise 实例状态变为rejected,包装实例就会变为rejected。

  • race 方法用于将多个 Promise 包装成一个新的 Promise 实例,只要其中一个 Promise 实例率先改变状态,包装实例的状态就会跟着改变。

特点:

(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。

(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。

有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise对象提供统一的接口,使得控制异步操作更加容易。

Promise也有一些缺点。首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。第三,当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

  1. 请解释一下 Promise 是什么,以及它的作用是什么? 答:Promise是一种用于处理异步操作的对象,它代表了一个异步操作的最终完成或失败,并返回相应的结果。Promise可以让开发者更加方便地处理异步代码,避免了回调地狱,使得代码更加清晰和易于维护。

  2. Promise的三种状态是什么?并且它们分别代表什么意思? 答:Promise有三种状态,分别是Pending(进行中)、Fulfilled(已成功)和Rejected(已失败)。当一个Promise对象刚被创建时,它处于Pending状态,表示异步操作正在进行中。当异步操作成功完成时,Promise会变为Fulfilled状态,表示操作已成功完成。当异步操作失败时,Promise会变为Rejected状态,表示操作已失败。

  3. Promise中的then和catch方法分别是做什么用的? 答:then方法用于指定异步操作成功时的回调函数,catch方法用于指定异步操作失败时的回调函数。当Promise状态变为Fulfilled时,then方法中的回调函数会被调用;当Promise状态变为Rejected时,catch方法中的回调函数会被调用。

  4. 请解释一下Promise中的链式调用(chaining)是什么,以及它的作用是什么? 答:Promise中的链式调用是指在一个Promise对象上多次调用then方法,以便依次处理异步操作的结果。这种链式调用可以使得代码更加清晰和易于维护,避免了回调地狱的问题。

11. async/await

  1. 什么是async/await?

    async/await是JavaScript中用于处理异步操作的关键字,它们使得异步代码的编写和理解变得更加简单和直观。
  2. async函数返回的是什么?

    async函数总是返回一个Promise对象。如果async函数内部显式地返回一个值,那么这个值会被Promise.resolve()包装成一个Promise对象。
  3. await关键字的作用是什么?

    await关键字用于等待一个Promise对象的解析,并且只能在async函数内部使用。它会暂停async函数的执行,直到Promise对象被解析或拒绝。
  4. async/await与Promise有什么区别?

    async/await是基于Promise的一种更加直观和简化的异步编程语法。它们使得异步代码更易于理解和维护

12. Symbol

一种新的基本数据类型,表示独一无二的值。Symbol 值通过Symbol()函数生成。这就是说,对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的 Symbol 类型。凡是属性名属于 Symbol 类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。

13. Set、map数据结构

Set是一种集合,它存储唯一的值,不允许重复。可以用来存储任何类型的值,而且它的值是无序的,因此不能通过索引访问。

Map是一种键值对的集合,它由键值对组成,其中键是唯一的,值可以重复。Map可以使用各种数据类型作为键和值。

区别:

  1. 数据结构不同:Set是一种集合,存储唯一的值;而Map是一种键值对的集合。

  2. 存储方式不同:Set存储的是单个值,而Map存储的是键值对。

  3. 访问方式不同:Set不能通过键来访问元素,只能通过值来判断是否存在;而Map可以通过键来访问对应的值。

  4. 用途不同:Set适合用于存储不重复的值,Map适合用于存储键值对的关联关系。

微服务

WebSocket 

rem

跨域

JS设计模式

Vue.use做了什么

前端跨域

跨域是浏览器的一个特性,指的是浏览器从一个"域"向另一个"域"的服务器发出请求,来访问另一个"域"上的资源。但是,由于请求的文件可能会存在恶意攻击,浏览器并不允许直接访问另一个"域"上的资源,只能访问同一个"域"上的资源,这个就是"同源策略"。同源策略指的是"协议、域名、端口号"一致。

解决跨域:

  1. 通过jsonp跨域

只支持 GET 请求 不支持post请求

JSONP 没有浏览器兼容问题,任何浏览器都支持。

核心思想:网页通过添加一个<script>元素,向服务器请求 JSON 数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来

  1. document.domain + iframe跨域

此方案仅限主域相同,子域不同的跨域应用场景。

实现原理:两个页面都通过js强制设置document.domain为基础主域,就实现了同域。

  1. location.hash + iframe

实现原理: a欲与b跨域相互通信,通过中间页c来实现。 三个页面,不同域之间利用iframe的location.hash传值,相同域之间直接js访问来通信。

  1. window.name + iframe跨域

window.name属性的独特之处:name值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)。

  1. postMessage跨域

postMessage是为数不多可以跨域操作的window属性之一,它可用于解决以下方面的问题:
a) 页面和其打开的新窗口的数据传递
b) 多窗口之间消息传递
c) 页面与嵌套的iframe消息传递

  1. 跨域资源共享(CORS)

CORS是跨域资源共享的缩写,是一种用于解决跨域请求的机制。CORS机制允许服务器在响应中设置一个特殊的头部(Access-Control-Allow-Origin),用来指定哪些域可以访问该资源。如果服务器允许当前域的请求,浏览器就会处理该请求并返回相应的数据。否则,浏览器会阻止该请求。

  1. nginx代理跨域

实现思路:通过nginx配置一个代理服务器(域名与demo1相同,端口不同)做跳板机,反向代理访问demo2接口,并且可以顺便修改cookie中demo信息,方便当前域cookie写入,实现跨域登录。

  1. nodejs中间件代理跨域

node中间件实现跨域代理,原理大致与nginx相同,都是通过启一个代理服务器,实现数据的转发,也可以通过设置cookieDomainRewrite参数修改响应头中cookie中域名,实现当前域的cookie写入,方便接口登录认证。

  1. WebSocket协议跨域

WebSocket protocol是HTML5一种新的协议。它实现了浏览器与服务器全双工通信,同时允许跨域通讯

开发vue组件的步骤
  1. 在components文件夹中创建一个新的文件夹,用于存放组件的相关文件。

  2. 在新创建的文件夹中,创建一个以.vue为后缀的文件,用于编写组件的模板、脚本和样式。

  3. 在.vue文件中,使用<template>标签编写组件的模板,<script>标签编写组件的脚本,<style>标签编写组件的样式。

  4. 在脚本部分,使用export default导出一个对象,该对象包含组件的相关配置,例如data、methods、computed等。

  5. 在index.js文件中,引入组件的.vue文件,并使用Vue.component()方法注册组件。

  6. 在需要使用组件的地方,通过标签的形式引入组件,并在Vue实例中注册组件。

vue路由面试题,什么是动态路由,路由生命周期有哪些

vue封装组件注意事项

1.遵循高内聚原则

高内聚:又称单一责任原则,是指一个模块只负责一项任务。在我们组件中体现在一个组件只有一项功能,若是功能太复杂,那我们还需将组件进行拆解抽离。

2.遵循低耦合原则

耦合:指的是模块之间的依赖性强弱。模块之间的依赖性越弱则称为耦合度低,反之耦合度就越高。由于vue是单向数据流,在我们封装组件时,尽量使用父传子props,子传父emit,避免子组件直接操作父组件数据

4.预留插槽(slot)位置

一个通用组件,往往不能够适应所有应用场景,所以在封装组件的时候,要预留插槽位置,让父组件来编写插槽的内容。

5. vue 组件封装遵循单向数据流原则

所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致数据的流向难以理解。并且,每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。因此组件的数据传递应当是父组件通过prop向子组件传递值,子组件通过emit事件来通知父组件修改值,而不是直接修改prop的值。

MVVM是什么
  1. MVVM 是Model-View-ViewModel 的缩写,

Model(模型):Model 是数据和业务逻辑的表示。它负责处理数据的获取、存储、验证和转换等操作,以及定义与数据相关的业务规则。

View(视图):View 是用户界面的可视化表示。它负责展示数据、接收用户输入,并将用户的操作传递给 ViewModel 进行处理。

ViewModel:视图模型,可实现数据的双向绑定,连接View和Model的桥梁,当数据变化时,ViewModel够监听到数据的变化(通过Data Bindings),自动更新视图,而当用户操作视图,ViewModel也能监听到视图的变化(通过DOM Listeners),然后通知数据做改动,这就实现了数据的双向绑定,在 MVVM中, 是不允许Model和View 直接通信的, 只能通过 ViewModel 来通信,MVVM的设计思想:只关注Model的变化,让MVVM框架利用自己的机制去自动更新DOM,从而把开发者从操作DOM的繁琐中解脱出来!

优点:1. 耦合性低。view 和 model 之间没有直接的关系,通过 viewModel 来完成数据双向绑定。

2. 可复用性。可以把一些视图逻辑放在一个ViewModel里面,让很多view复用这段视图逻辑。

3. 独立开发。开发人员可以专注于业务逻辑和数据的开发,设计人员可以专注于页面设计。

4. 可测试性。ViewModel的存在可以帮助开发者更好地编写测试代码。

2、MVC是一种架构思想,全称Model-View-Controller,即模型-视图-控制器,MVC是后端的开发思想,将数据从后端经过控制器层转向前端视图展示。

Model:模型 数据,View:视图, Controller:控制器 接受并处理用户请求通知Model改变,并将Model返回给 View

H5页面适配PC端、移动端
  1. 媒体查询
  2. flex布局
  3. rem
  4. calc()函数
  5. min-height,min-width,max-height,nax-width
  6. 用百分比设置样式属性
  7. vw/vh/vmin/vmax
  8. 如果差异太大,则开发PC端和移动端两套页面,通过判断设备,运行不同的代码。
 JS 的事件流模型有哪些?

标准事件模型

在该事件模型中,一次事件共有三个过程,也就是上文提到的事件流 3 阶段,

  • 事件捕获阶段:事件从 Document 一直向下传播到目标元素, 依次检查经过的节点是否绑定了事件监听函数,如果有则执行

  • 事件处理阶段:事件到达目标元素, 触发目标元素的监听函数

  • 事件冒泡阶段:事件从目标元素向上冒泡到 Document,依次检查经过的节点是否绑定了事件监听函数,如果有则执行

IE事件模型

IE事件模型共有两个过程:

  • 事件处理阶段:事件到达目标元素, 触发目标元素的监听函数。

  • 事件冒泡阶段:事件从目标元素冒泡到document, 依次检查经过的节点是否绑定了事件监听函数,如果有则执行

原始事件模型

事件绑定监听函数比较简单, 有两种方式:

  • 一HTML代码中直接绑定  οnclick=“fun”   二、通过JS代码绑定 document.getElementById('#aaa').onclick = fun

特性

  • 绑定速度快,DOM0 级事件具有很好的跨浏览器优势,会以最快的速度绑定,但由于绑定速度太快,可能页面还未完全加载出来,以至于事件可能无法正常运行。

  • 只支持冒泡,不支持捕获

  • 同一个类型的事件只能绑定一次。当希望为同一个元素绑定多个同类型事件的时候,是不被允许的,后绑定的事件会覆盖之前的事件。

什么是渐进式

渐进式框架是一种软件开发框架的概念,它强调构建应用程序的方法是逐步增强的,允许开发者根据项目的需求和复杂度选择性地使用框架提供的不同功能和特性。

Vue.js 允许开发者逐渐引入它的核心库和附加的生态系统库,如Vue Router、Vuex等。开发者可以选择在项目中逐步使用这些库,从而创建出满足需求的应用程序。渐进式框架为开发者提供了更大的灵活性和控制权,让他们根据项目的需求进行选择和使用不同的功能,而无需承担过多的不必要复杂性。

vue优缺点

vue两大特点:响应式编程、组件化。

vue的优势:轻量级框架、简单易学、双向数据绑定、组件化、数据和视图分离、虚拟DOM、运行速度快。vue是单页面应用,使页面局部刷新,不用每次跳转页面都要请求所有数据和dom,这样大大加快了访问速度和提升用户体验。而且他的第三方ui库很多,节省开发时间。

确点:

  • 不支持IE8
  • vue是单页面页面,对于搜索引擎不友好
  • 容易上手,不缺入门教材,但是缺乏高阶教程、文档以及书籍
  • 功能环境比不上angular和react
call、apply和bind

相同点:call、apply和bind都是JS函数的公有的内部方法,他们都是重置函数的this,改变函数的执行环节。

不同点:bind是创建一个新的函数,而call和aplay是用来调用函数;call和apply作用一样,只不过call为函数提供的参数是一个个的,而apply为函数提供的参数是一个数组。

forEach和map区别

1.foreach返回值是undefined,而map会返回一个新的数组,这个新数组由原数组中的每个元素都调用一次提供的函数后的返回值组成。
2.foreach不支持链式调用,而map支持链式调用,可以继续对返回的新数组进行操作。

支持链式调用是指可以在一个方法调用的结果上直接调用另一个方法。对于map()方法来说,它返回一个新的数组,因此可以在这个新的数组上直接调用其他数组方法,例如filter()、reduce()、forEach()等。这种链式调用的方式可以让代码更加简洁和易读。

作用域和作用域链

作用域指的是变量和函数的可访问范围。在js中,作用域可以分为全局作用域和局部作用域。全局作用域是指在代码的任何地方都能访问的变量和函数,而局部作用域则是指在特定的代码块内部定义的变量和函数,只能在该代码块内部访问。

作用域的嵌套就形成了作用域链,在jst中,当查找变量或函数时,会沿着作用域嵌套的结构依次向上查找。当在当前作用域无法找到需要的变量或函数时,会沿着作用域链向上查找,直到找到为止。这个过程就是作用域链。

vue2和vue3的区别

1.双向数据绑定原理不同
Vue2 的双向数据绑定是利用ES5的一个APIObject.definePropert() 对数据进行劫持,结合发布订阅模式的方式来实现的。

Vue3 中使用ES6的Proxy API对数据代理。

Vue3 使用数据代理的优势有以下几点:1)definePropert 只能监听某个属性,不能对整个对象进行监听 2)可以省去for in,闭包等内容来提升效率(直接绑定整个对象即可)3)可以监听数组,不用再单独的对数组做特异性操作,Vue3可以检测到数组内部数据的变化

2.根节点
Vue2 只有一个根节点。Vue3 可以拥有多个根节点

3.API 类型不同

Vue2:选项式API,面向对象编程

Vue3:选项式API/组合式API,面向函数编程;

选项式 API

选项式 API是通过一个包含各种选项的对象来描述组件。这些选项包括data、methods、computed、watch、生命周期钩子等属性与方法,共同处理页面逻辑。

2、组合式API

组合式API是Vue3中引入的新特性,通过一组函数来描述组件。这些函数包括setup、reactive、computed、watch等。组合式API的优点是更灵活、更加的可复用,适合大型组件的编写。数据和方法都定义在setup中。组件根据逻辑功能来编写的,一个功能定义的API 放在一起,实现更好的高内聚,低耦合特性。

4定义数据变量和方法不同
Vue2是把数据放到了data 中,在 Vue2中 定义数据变量是data(){},创建的方法要在method:{}

Vue3 用了新增的setup()方法,此方法在组件初始化构造的时候触发。使用三个步骤来建立响应性数据:1)从vue 引入 reactive;2)使用 reactive ()方法来声明数据为响应性数据;3) 使用setup()方法来返回我们的响应性数据,从而template 可以获取这些响应性数据。

 ref是将基本类型数据转换为响应式数据。reactive用将复杂数据类型转换为响应式数据。

ref、toref(对象中单个属性变为响应式)

都是把reactive包裹的对象内的属性变为ref响应式的

区别:toref使得操作对象的属性,{ {对象}}和对象内{ {属性}}都变为响应式,而ref仅让{ {属性}}变为响应式,对象不发生变化

torefs(对象中多个属性变为响应式)

包裹一个对象,把对象内部的属性变为响应式的。把响应式对象变为普通对象,但是对象内属性变为ref响应式

5.生命周期钩子函数不同

VUE2生命周期

beforeCreate(创建vue实例前):beforeCreate钩子函数,这个时候,vue实例的挂载元素$el和数据对象data都为undefined,还未初始化。无法访问到数据和真实的dom和data中的数据,可以在这里面使用loading

2、created(创建vue实例后):created函数中可以对data对象里面的数据进行使用和更改,不会触发其他的钩子函数,一般可以在这里做初始数据的获取,也可以结束loading; 这里进行dom操作需要使用vue.nextTick()方法

3、beforeMount(挂载前):beforeMount钩子函数,vue实例的$el和data都初始化了,但还是虚拟的dom节点,具体的data.filter还未替换。在这里也可以更改数据,不会触发其他的钩子函数,一般可以在这里做初始数据的获取

4、mounted(挂载后):mounted钩子函数,此时,组件已经出现在页面中,数据、真实dom都已经处理好了,事件都已经挂载好了,data.filter成功渲染,可以在这里操作真实dom等事情...

5、beforeUpdate (更新前):当组件或实例的数据更改之后,会立即执行beforeUpdate,然后vue的虚拟dom机制会重新构建虚拟dom与上一次的虚拟dom树利用diff算法进行对比之后重新渲染,一般不做什么事儿

6、updated(更新后):当更新完成后,执行updated,数据已经更改完成,dom也重新render完成,可以操作更新后的虚拟dom

7、beforeDestroy(销毁前):当经过某种途径调用$destroy方法后,立即执行beforeDestroy,一般在这里做一些善后工作,例如清除计时器、清除非指令绑定的事件等等

8、destroyed(销毁后):vue实例解除了事件监听以及和dom的绑定(无响应了),但DOM节点依旧存在。这个时候,执行destroyed,在这里做善后工作也可以

Vue3 生命周期

 Vue3 生命周期在调用前需要先进行引入。

onBeforeMount( ) 组件挂载到节点上之前执行的函数 

onMouted( ) 组件挂载完成后执行的函数

onBeforeUpdate( ) 组件更新之前执行的函数

onUpdated( ) 组件更新完成之后执行的函数

onBeforeUnmount( )  组件卸载前执行的函数

onUnmounted( ) 组件卸载后执行的函数

onActivated( )  被包含在 <keep-alive> 中的组件 会多出两个生命周期钩子函数 被激活时执行 

onDeactivated( ) 从A组件 切换 到 B 组件 A组件消失时执行

onErrorCaptured( ) 当前捕获一个子孙组件的异常时激活钩子函数

6.父子传参不同

vue2:父传子,用props,子传父用事件 Emitting Events。在vue2中,会调用this$emit然后传入事件名和对象。

vue3:父传子,用props,子传父用事件 Emitting Events。在vue3中的setup()中的第二个参数content对象中就有emit,所以在setup方法中就可以使用emit。

setup()函数特性


setup() 钩子函数是在组件中使用组合式 API 的入口,通常只在以下情况下使用:

  1. 需要在非单文件组件中使用组合式 API 时。

  2. 需要在基于选项式 API 的组件中集成基于组合式 API 的代码时。

其他情况下,都应优先使用 <script setup> 语法。

  • setup()函数接收两个参数:props、context(包含attrs、slots、emit、expose)。
  • setup函数是处于生命周期beforeCreated和created俩个钩子函数之前。
  • 执行setup时,组件实例尚未被创建(setup函数中得this是undefined)。
  • 与模板一起使用时,需要返回一个对象。
  • 因为setup函数中,props是响应式得,当传入新的prop时,它将会被更新,所以不能使用es6解构,因为它会消除prop得响应性,如需解构prop,可以通过使用setup函数中得toRefs来完成此操作。
  • 在setup()内使用响应式数据时,需要通过 .value 获取。
  • setup函数只能是同步的不能是异步的。

7.Main.js 文件不同

Vue2中我们可以使用pototype(原型)的形式去进行操作,引入的是构造函数。

Vue3 中需要使用结构的形式进行操作,引入的是工厂函数;

总的来说,构造函数和工厂函数都是用于创建对象的方式,它们在使用的语法和创建对象的方式上有一些区别。

区别:

  1. 使用 new 关键字:构造函数需要使用 new 关键字来创建对象,而工厂函数不需要。

  2. 返回值:构造函数内部不需要显式地返回对象,因为它会自动返回新创建的对象实例;而工厂函数需要显式地返回对象。

  3. 原型链:构造函数创建的对象实例共享同一个原型对象;而工厂函数创建的对象实例并不共享同一个原型对象,每个实例都有自己的方法。

8.Vue3新增了cacheHandlers来缓存事件监听器,提高了事件处理的效率。

10.vue3中使用hooks,vue中使用mixin

  • Mixin:以对象的形式进行定义和应用。它的特点是允许开发者将多个组件中共享的方法或属性组合在一起,形成一个“混合”的模块,从而减少重复代码并提高代码的可维护性。Mixin在组件中的属性和方法会与组件本身的属性和方法进行会进行合并,可能会导致命名冲突。采用选项api。
  • Hooks:采用函数式编程的方式来定义和使用组件逻辑。可以通过创建自定义的函数来封装相关的逻辑,并将其应用到一个或多个组件中,并且不会导致命名冲突。vue采用的是组合式api。
Webpack和Vite的区别如下:
  1. 打包方式:Webpack是一个模块打包工具,将各种资源打包成一个整体的bundle.js文件;而Vite是基于浏览器原生 ES 模块加载的开发服务器,可以即时编译和构建代码,以提高开发效率。

  2. 启动速度:Vite的启动速度比Webpack更快,因为它在开发环境下使用了浏览器原生的 ES 模块加载,而不是像Webpack一样使用打包后的文件进行模块加载。

  3. 热更新:Vite的热更新更快,能够实现按需加载和热更新,而Webpack的热更新相对较慢。

  4. 生态系统:Webpack具有更丰富的生态系统,可以通过插件和loader扩展其功能;而Vite的生态系统相对不够成熟。

  5. 适用场景:Vite适合快速开发、需要高效热更新的场景,而Webpack适合需要更复杂的打包配置或更丰富的生态系统的场景。

总的来说,Vite注重开发效率和快速热更新,适合小型项目和需要快速开发的场景;而Webpack注重兼容性和丰富的生态系统,适合复杂项目和需要定制化打包配置的场景。选择使用哪一个取决于项目类型和规模、技术栈和生态系统、性能和构建速度等因素。

Webpack面试题
  1. 请解释Webpack是什么,以及它的主要功能是什么? 答:Webpack是一个现代的静态模块打包工具,它主要用于处理各种类型的资源,例如JavaScript、样式表、图片等,并将它们打包成一个或多个bundle。它还支持各种插件和加载器,以便于处理不同类型的文件。

  2. 请介绍一下Webpack的核心概念和主要组件? 答:Webpack的核心概念包括入口(entry)、输出(output)、加载器(loader)、插件(plugin)和模式(mode)。入口指定了打包的起点,输出指定了打包后的文件输出位置,加载器用于对各种类型的文件进行转换,插件用于执行更广泛的任务,例如打包优化、资源管理等,模式用于指定打包的环境,例如开发环境或生产环境。

  3. 请解释Webpack的热模块替换(HMR)是什么,以及它的作用是什么? 答:热模块替换是Webpack的一个特性,它允许在不重新加载整个页面的情况下替换、添加或删除模块。它的作用是在开发过程中实现实时更新,提高开发效率。

  4. 请解释Webpack的代码分离是什么,以及它的优点是什么? 答:Webpack的代码分离是一种将代码拆分成多个bundle的技术,它的优点包括减少初始加载时间、提高页面性能、减少重复下载等。

 Vite 的面试题:
  1. 请解释 Vite 是什么,以及它与传统的构建工具(如 Webpack)有何不同? 答:Vite是一个基于现代浏览器原生 ES 模块导入的开发服务器,它专注于为现代浏览器提供快速的开发体验。与传统的构建工具(如 Webpack)相比,Vite利用浏览器的原生 ES 模块加载,实现了快速的冷启动和热模块更新,从而提高了开发效率和构建速度。

  2. Vite的优势是什么?它为开发者带来了哪些便利? 答:Vite的优势包括快速的冷启动、热模块更新、按需编译、即时开发环境和生产环境的一致性等。它为开发者带来了更快的开发体验、更快的构建速度、更快的热更新等便利。

  3. 请介绍一下 Vite 的插件化架构及其优势? 答:Vite采用了插件化架构,可以通过插件来扩展其功能。这使得开发者可以根据自己的需求,方便地定制和扩展Vite的功能,从而满足特定的开发需求。

  4. Vite适用于哪些类型的项目?它与传统的构建工具相比有何优势? 答:Vite适用于现代化的前端项目,特别是那些需要快速开发和高性能构建结果的项目。与传统的构建工具相比,Vite具有更快的构建速度、更快的热更新、更快的冷启动等优势。

TypeScript面试题
  1. 请介绍一下 TypeScript,以及它与 JavaScript 的关系? 答:TypeScript是由微软开发的一种开源的编程语言,它是JavaScript的超集,意味着所有的JavaScript代码也是合法的TypeScript代码。TypeScript通过添加静态类型和其他特性来扩展JavaScript的功能,从而提供更强大的工具和错误检测。

  2. TypeScript的优势是什么?为什么要使用它? 答:TypeScript的优势包括静态类型检查、更好的代码提示和补全、更好的工具支持、更好的代码可读性和可维护性等。使用TypeScript可以提高代码质量、减少错误、提高开发效率。

  3. 请解释一下 TypeScript中的接口(interface)是什么,以及它的作用是什么? 答:接口是一种用于描述对象的形状(shape)的方式,它定义了对象应该具有的属性和方法。通过使用接口,可以在TypeScript中进行类型检查,以确保对象的结构符合预期。

  4. TypeScript中的泛型(generics)是什么,以及它的作用是什么? 答:泛型是一种在定义函数、类或接口时使用类型参数的方式,它可以增加代码的灵活性和可重用性。通过使用泛型,可以编写更加通用和灵活的代码,从而提高代码的复用性和可维护性。

  5. 请解释一下 TypeScript中的类型推断(type inference)是什么,以及它的作用是什么? 答:类型推断是TypeScript的一种特性,它可以根据上下文推断出变量的类型。通过使用类型推断,可以减少代码中的冗余类型注解,从而提高代码的简洁性和可读性。

懒加载和异步加载
  1. 异步加载(Asynchronous Loading): 异步加载是指在需要时加载资源或数据,而不是在页面加载时立即加载所有内容。这可以通过异步请求来获取数据或资源,从而减少页面的初始加载时间,并提高用户体验。在前端开发中,常见的异步加载包括请求服务端获取数据,或者动态加载 js文件或模块。

  2. 延迟加载(Lazy Loading): 延迟加载是指在需要时才加载某些组件、图片或其他资源。这有助于减少初始加载时间,特别是对于大型应用程序或页面来说,可以提高页面加载速度。在前端开发中,常见的延迟加载包括延迟加载图片(例如在用户滚动到可见区域时才加载图片)、延迟加载组件或模块(例如在用户访问特定页面时才加载相关的组件)等。

async和defer 异步加载的区别:
  1. 通常情况下defer的使用频率较高,它能保证script之间的变量依赖。标记为 async 的脚本并不保证能按照它们出现的次序执行,标记为 defer的脚本是按出现顺序执行的
  2. 需要注意的是:async script的资源请求时异步的,但async script的执行仍然会阻塞后续渲染,defer是在html渲染完之后执行的所以不会阻塞后续渲染。

HTML5新特性:

HTML5的十大新特性 

  为了更好地处理今天的互联网应用,HTML5添加了很多新元素及功能,比如: 图形的绘制,多媒体内容,更好的页面结构,更好的形式 处理,和几个api拖放元素,定位,包括网页 应用程序缓存,存储,网络工作者,等

(1)语义标签

  语义化标签使得页面的内容结构化,见名知义

 标签 描述
 <hrader></header> 定义了文档的头部区域
 <footer></footer> 定义了文档的尾部区域
<nav></nav>定义文档的导航
 <section></section> 定义文档中的节(section、区段)
 <article></article> 定义页面独立的内容区域
<aside></aside>定义页面的侧边栏内容
<detailes></detailes>用于描述文档或文档某个部分的细节
<summary></summary>标签包含 details 元素的标题
<dialog></dialog>定义对话框,比如提示框

(2)增强型表单

  HTML5 拥有多个新的表单 Input 输入类型。这些新特性提供了更好的输入控制和验证。

输入类型

描述

color

主要用于选取颜色

date

从一个日期选择器选择一个日期

datetime

选择一个日期(UTC 时间)

datetime-local

选择一个日期和时间 (无时区)

email

包含 e-mail 地址的输入域

month

选择一个月份

number

数值的输入域

range

一定范围内数字值的输入域

search

用于搜索域

tel

定义输入电话号码字段

time

选择一个时间

url

 URL 地址的输入域

week

选择周和年

   HTML5 也新增以下表单元素

表单元素描述

<datalist>

 元素规定输入域的选项列表

使用 <input> 元素的 list 属性与 <datalist> 元素的 id 绑定

<keygen>

提供一种验证用户的可靠方法

标签规定用于表单的密钥对生成器字段。

<output>

用于不同类型的输出

比如计算或脚本输出

  HTML5 新增的表单属性

    • placehoder 属性,简短的提示在用户输入值前会显示在输入域上。即我们常见的输入框默认提示,在用户输入后消失。
    • required  属性,是一个 boolean 属性。要求填写的输入域不能为空
    • pattern 属性,描述了一个正则表达式用于验证<input> 元素的值。
    • min 和 max 属性,设置元素最小值与最大值。
    • step 属性,为输入域规定合法的数字间隔。
    • height 和 width 属性,用于 image 类型的 <input> 标签的图像高度和宽度。
    • autofocus 属性,是一个 boolean 属性。规定在页面加载时,域自动地获得焦点。
    • multiple 属性 ,是一个 boolean 属性。规定<input> 元素中可选择多个值。   

(3)视频和音频

  • HTML5 提供了播放音频文件的标准,即使用 <audio> 元素

    ?

    1

    2

    3

    4

    5

    <audio controls>

      <source src="horse.ogg" type="audio/ogg">

      <source src="horse.mp3" type="audio/mpeg">

    您的浏览器不支持 audio 元素。

    </audio>

 control 属性供添加播放、暂停和音量控件。

 在<audio> 与 </audio> 之间你需要插入浏览器不支持的<audio>元素的提示文本 。

 <audio> 元素允许使用多个 <source> 元素. <source> 元素可以链接不同的音频文件,浏览器将使用第一个支持的音频文件

 目前, <audio>元素支持三种音频格式文件: MP3, Wav, 和 Ogg

  • HTML5 规定了一种通过 video 元素来包含视频的标准方法。

    ?

    1

    2

    3

    4

    5

    <video width="320" height="240" controls>

      <source src="movie.mp4" type="video/mp4">

      <source src="movie.ogg" type="video/ogg">

    您的浏览器不支持Video标签。

    </video>

    control 提供了 播放、暂停和音量控件来控制视频。也可以使用dom操作来控制视频的播放暂停,如 play() 和 pause() 方法。

    同时 video 元素也提供了 width 和 height 属性控制视频的尺寸.如果设置的高度和宽度,所需的视频空间会在页面加载时保留。如果没有设置这些属性,浏览器不知道大小的视频,浏览器就不能再加载时保留特定的空间,页面就会根据原始视频的大小而改变。

    与 标签之间插入的内容是提供给不支持 video 元素的浏览器显示的。

    video 元素支持多个source 元素. 元素可以链接不同的视频文件。浏览器将使用第一个可识别的格式( MP4, WebM, 和 Ogg)

(4)Canvas绘图

  标签只是图形容器,必须使用脚本来绘制图形。

  • Canvas - 图形

  1. 创建一个画布,一个画布在网页中是一个矩形框,通过 <canvas> 元素来绘制。默认情况下 元素没有边框和内容。

    ?

    1

    <canvas id="myCanvas" width="200" height="100" style="border:1px solid #000000;"></canvas>

      标签通常需要指定一个id属性 (脚本中经常引用), width 和 height 属性定义的画布的大小,使用 style 属性来添加边框。你可以在HTML页面中使用多个 <canvas> 元素

  2. 使用Javascript来绘制图像,canvas 元素本身是没有绘图能力的。所有的绘制工作必须在 JavaScript 内部完成

    ?

    1

    2

    3

    4

    5

    6

    <script>

      var c=document.getElementById("myCanvas");

      var ctx=c.getContext("2d");

      ctx.fillStyle="#FF0000";

      ctx.fillRect(0,0,150,75);

    </script>

      getContext("2d") 对象是内建的 HTML5 对象,拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法。

      设置 fillStyle 属性可以是CSS颜色,渐变,或图案。fillStyle默认设置是#000000(黑色)。fillRect(x,y,width,height) 方法定义了矩形当前的填充方式。意思是:在画布上绘制 150x75 的矩形,从左上角开始 (0,0)。 

  • Canvas - 路径

在Canvas上画线,我们将使用以下两种方法:

moveTo(x,y) 定义线条开始坐标

lineTo(x,y) 定义线条结束坐标

绘制线条我们必须使用到 "ink" 的方法,就像stroke()。

?

1

2

3

4

5

6

7

<script>

    var c=document.getElementById("myCanvas");

    var ctx=c.getContext("2d");

    ctx.moveTo(0,0);

    ctx.lineTo(200,100);

    ctx.stroke();

</script>

    定义开始坐标(0,0), 和结束坐标 (200,100). 然后使用 stroke() 方法来绘制线条

  • Canvas - 文本

使用 canvas 绘制文本,重要的属性和方法如下:

  font - 定义字体

  fillText(text,x,y) - 在 canvas 上绘制实心的文本

  strokeText(text,x,y) - 在 canvas 上绘制空心的文本

使用 fillText():

?

1

2

3

4

var c=document.getElementById("myCanvas");

var ctx=c.getContext("2d");

ctx.font="30px Arial";

ctx.fillText("Hello World",10,50);

  使用 "Arial" 字体在画布上绘制一个高 30px 的文字(实心)

  • Canvas - 渐变

渐变可以填充在矩形, 圆形, 线条, 文本等等, 各种形状可以自己定义不同的颜色。

以下有两种不同的方式来设置Canvas渐变:

  createLinearGradient(x,y,x1,y1) - 创建线条渐变

  createRadialGradient(x,y,r,x1,y1,r1) - 创建一个径向/圆渐变

当我们使用渐变对象,必须使用两种或两种以上的停止颜色。

addColorStop()方法指定颜色停止,参数使用坐标来描述,可以是0至1.

使用渐变,设置fillStyle或strokeStyle的值为渐变,然后绘制形状,如矩形,文本,或一条线。

?

1

2

3

4

5

6

7

8

9

10

11

var c=document.getElementById("myCanvas");

var ctx=c.getContext("2d");

// Create gradient

var grd=ctx.createLinearGradient(0,0,200,0);

grd.addColorStop(0,"red");

grd.addColorStop(1,"white");

// Fill with gradient

ctx.fillStyle=grd;

ctx.fillRect(10,10,150,80);

  创建了一个线性渐变,使用渐变填充矩形

  • Canvas - 图像

  把一幅图像放置到画布上, 使用 drawImage(image,x,y) 方法

?

1

2

3

4

var c=document.getElementById("myCanvas");

var ctx=c.getContext("2d");

var img=document.getElementById("scream");

ctx.drawImage(img,10,10);

  把一幅图像放置到了画布上

(5)SVG绘图

  SVG是指可伸缩的矢量图形

SVG 与 Canvas两者间的区别

  SVG 是一种使用 XML 描述 2D 图形的语言。

  Canvas 通过 JavaScript 来绘制 2D 图形。

  SVG 基于 XML,这意味着 SVG DOM 中的每个元素都是可用的。您可以为某个元素附加 JavaScript 事件处理器。

  在 SVG 中,每个被绘制的图形均被视为对象。如果 SVG 对象的属性发生变化,那么浏览器能够自动重现图形。

  Canvas 是逐像素进行渲染的。在 canvas 中,一旦图形被绘制完成,它就不会继续得到浏览器的关注。如果其位置发生变化,那么整个场景也需要重新绘制,包括任何或许已被图形覆盖的对象。


(6)地理定位

  HTML5 Geolocation(地理定位)用于定位用户的位置。

window.navigator.geolocation {
    getCurrentPosition:  fn  用于获取当前的位置数据
    watchPosition: fn  监视用户位置的改变
    clearWatch: fn  清除定位监视
}   

  获取用户定位信息:

复制代码

navigator.geolocation.getCurrentPosition(
    function(pos){

    console.log('用户定位数据获取成功')
    //console.log(arguments);
    console.log('定位时间:',pos.timestamp)
    console.log('经度:',pos.coords.longitude)
    console.log('纬度:',pos.coords.latitude)
    console.log('海拔:',pos.coords.altitude)
    console.log('速度:',pos.coords.speed)

},    //定位成功的回调
function(err){ 

    console.log('用户定位数据获取失败')
    //console.log(arguments);

}        //定位失败的回调
)

复制代码

(7)拖放API

  拖放是一种常见的特性,即抓取对象以后拖到另一个位置。在 HTML5 中,拖放是标准的一部分,任何元素都能够拖放。

  拖放的过程分为源对象和目标对象。源对象是指你即将拖动元素,而目标对象则是指拖动之后要放置的目标位置。

拖放的源对象(可能发生移动的)可以触发的事件——3个

dragstart:拖动开始

drag:拖动中

dragend:拖动结束

整个拖动过程的组成: dragstart*1 + drag*n + dragend*1

拖放目标对象(不会发生移动)可以触发的事件——4个

dragenter:拖动着进入

dragover:拖动着悬停

dragleave:拖动着离开

drop:释放

整个拖动过程的组成1: dragenter*1 + dragover*n + dragleave*1

整个拖动过程的组成2: dragenter*1 + dragover*n + drop*1

dataTransfer:用于数据传递的“拖拉机”对象;

  在拖动源对象事件中使用e.dataTransfer属性保存数据:

e.dataTransfer.setData( k,  v )

  在拖动目标对象事件中使用e.dataTransfer属性读取数据:

var value = e.dataTransfer.getData( k )

(8)Web Worker

  当在 HTML 页面中执行脚本时,页面的状态是不可响应的,直到脚本已完成。

  web worker 是运行在后台的 JavaScript,独立于其他脚本,不会影响页面的性能。您可以继续做任何愿意做的事情:点击、选取内容等等,而此时 web worker 在后台运行。

  首先检测浏览器是否支持 Web Worker

?

1

2

3

4

5

6

if(typeof(Worker)!=="undefined"){

  // 是的! Web worker 支持!

  // 一些代码.....

  }else{

  // //抱歉! Web Worker 不支持

  }

  下面的代码检测是否存在 worker,如果不存在,- 它会创建一个新的 web worker 对象,然后运行 "demo_workers.js" 中的代码

?

1

2

3

4

if(typeof(w)=="undefined")

  {

  w=new Worker("demo_workers.js");

  }

  然后我们就可以从 web worker 发送和接收消息了。向 web worker 添加一个 "onmessage" 事件监听器:

?

1

2

3

w.onmessage=function(event){

document.getElementById("result").innerHTML=event.data;

};

  当 web worker 传递消息时,会执行事件监听器中的代码。event.data 中存有来自 event.data 的数据。当我们创建 web worker 对象后,它会继续监听消息(即使在外部脚本完成之后)直到其被终止为止。

如需终止 web worker,并释放浏览器/计算机资源,使用 terminate() 方法。

 完整的 Web Worker 实例代码

复制代码

<!DOCTYPE html>
<html>
<body>

<p>Count numbers: <output id="result"></output></p>
<button οnclick="startWorker()">Start Worker</button> 
<button οnclick="stopWorker()">Stop Worker</button>
<br><br>

<script>
var w;

function startWorker()
{
if(typeof(Worker)!=="undefined")
{
  if(typeof(w)=="undefined")
    {
    w=new Worker("demo_workers.js");
    }
  w.onmessage = function (event) {
    document.getElementById("result").innerHTML=event.data;
  };
}
else
{
document.getElementById("result").innerHTML="Sorry, your browser does not support Web Workers...";
}
}

function stopWorker()
{ 
w.terminate();
}
</script>

</body>
</html>

复制代码

  创建的计数脚本,该脚本存储于 "demo_workers.js" 文件中

var i=0;

 function timedCount()
 {
 i=i+1;
 postMessage(i);
 setTimeout("timedCount()",500);
 }

 timedCount(); 

复制代码

(9)Web Storage

  使用HTML5可以在本地存储用户的浏览数据。早些时候,本地存储使用的是cookies。但是Web 存储需要更加的安全与快速. 这些数据不会被保存在服务器上,但是这些数据只用于用户请求网站数据上.它也可以存储大量的数据,而不影响网站的性能。数据以 键/值 对存在, web网页的数据只允许该网页访问使用。

客户端存储数据的两个对象为:

    • localStorage - 没有时间限制的数据存储
    • sessionStorage - 针对一个 session 的数据存储, 当用户关闭浏览器窗口后,数据会被删除。

  在使用 web 存储前,应检查浏览器是否支持 localStorage 和sessionStorage

复制代码

if(typeof(Storage)!=="undefined")
   {
   // 是的! 支持 localStorage  sessionStorage 对象!
   // 一些代码.....
   }
 else
   {
   // 抱歉! 不支持 web 存储。
   }

复制代码

  不管是 localStorage,还是 sessionStorage,可使用的API都相同,常用的有如下几个(以localStorage为例):

    • 保存数据:localStorage.setItem(key,value);
    • 读取数据:localStorage.getItem(key);
    • 删除单个数据:localStorage.removeItem(key);
    • 删除所有数据:localStorage.clear();
    • 得到某个索引的key:localStorage.key(index);


(10)WebSocket

  WebSocket是HTML5开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。在WebSocket API中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。当你获取 Web Socket 连接后,你可以通过 send() 方法来向服务器发送数据,并通过 onmessage 事件来接收服务器返回的数据。

复制代码

<!DOCTYPE HTML>
<html>
   <head>
   <meta charset="utf-8">
   <title>W3Cschool教程(w3cschool.cn)</title>
    
      <script type="text/javascript">
         function WebSocketTest()
         {
            if ("WebSocket" in window)
            {
               alert("您的浏览器支持 WebSocket!");
               
               // 打开一个 web socket
               var ws = new WebSocket("ws://localhost:9998/echo");
                
               ws.onopen = function()
               {
                  // Web Socket 已连接上,使用 send() 方法发送数据
                  ws.send("发送数据");
                  alert("数据发送中...");
               };
                
               ws.onmessage = function (evt) 
               { 
                  var received_msg = evt.data;
                  alert("数据已接收...");
               };
                
               ws.onclose = function()
               { 
                  // 关闭 websocket
                  alert("连接已关闭..."); 
               };
            }
            
            else
            {
               // 浏览器不支持 WebSocket
               alert("您的浏览器不支持 WebSocket!");
            }
         }
      </script>
        
   </head>
   <body>
   
      <div id="sse">
         <a href="javascript:WebSocketTest()">运行 WebSocket</a>
      </div>
      
   </body>
</html>

css3新特性:

1.新增选择器

选择符类型

表达式

描述

子串匹配的属性选择符

E[att^="val"]

匹配具有att属性、且值以val开头的E元素

E[att$="val"]

匹配具有att属性、且值以val结尾的E元素

E[att*="val"]

匹配具有att属性、且值中含有val的E元素

结构性伪类

E:root

匹配文档的根元素。在HTML标准通用标记语言下的一个应用)中,根元素永远是HTML

E:nth-child(n)

匹配父元素中的第n个子元素E

E:nth-last-child(n)

匹配父元素中的倒数第n个结构子元素E

E:nth-of-type(n)

匹配同类型中的第n个同级兄弟元素E

E:nth-last-of-type(n)

匹配同类型中的倒数第n个同级兄弟元素E

E:last-child

匹配父元素中最后一个E元素

E:first-of-type

匹配同级兄弟元素中的第一个E元素

E:only-child

匹配属于父元素中唯一子元素的E

E:only-of-type

匹配属于同类型中唯一兄弟元素的E

E:empty

匹配没有任何子元素(包括text节点)的元素E

目标伪类

E:target

匹配相关URL指向的E元素

UI元素状态伪类

E:enabled

匹配所有用户界面(form表单)中处于可用状态的E元素

E:disabled

匹配所有用户界面(form表单)中处于不可用状态的E元素

E:checked

匹配所有用户界面(form表单)中处于选中状态的元素E

E::selection

匹配E元素中被用户选中或处于高亮状态的部分

否定伪类

E:not(s)

匹配所有不匹配简单选择符s的元素E

通用兄弟元素选择器

E ~ F

匹配E元素之后的F元素

2.圆角边框、多层边框、边框色彩与边框图片

CSS3对网页中的边框进行了一些改进,主要包括支持圆角边框、多层边框、边框色彩与图片等。在CSS3中最常用的一个改进就是圆角边框,通过CSS3的属性可以快速实现圆角定义,同时还可以根据实际情况针对特定角进行圆角定义 [40]。

3.多背景图

CSS3允许使用多个属性(比如background-image、background-repeat、background-size、background-position、background-origin和background-clip等)在一个元素上添加多层背景图片。该属性的应用大大改善了以往面对多层次设计需要多层布局的问题,帮助Web前端开发者在不借助Photoshop的情况下实现对页面背景的设计,简化了背景图片的维护成本 [40]。

4.颜色与透明度

CSS3颜色模块的引入,实现了制作Web效果时不再局限于RGB和十六进制两种模式。CSS3增加了HSL、HSLA、RGBA几种新的颜色模式。这几种颜色模式的提出,在做开发的时候不仅可以设置元素的色彩,还能根据需要轻松地设定元素透明度 [40]。

5.多列布局与弹性盒模型布局

CSS3多列布局属性可以不使用多个div标签就能实现多列布局。CSS3中的多列布局模块描述了如何像报纸、杂志那样,把一个简单的区块拆成多列,并通过相应属性来实现列数、列宽、各列之间的空白间距。弹性盒模型布局方便了Web前端开发者根据复杂的前端分辨率进行弹性布局,轻松地实现页面中的某一区块在水平、垂直方向对齐,是进行响应式网站开发的一大利器 [40]。

6.盒子的变形

在CSS2.1中,想让某个元素变形必须要借助JavaScript写大量的代码实现,在CSS3中加入了变形属性,该属性在2D或3D空间里操作盒子的位置和形状,来实现例如旋转、扭曲、缩放或者移位。变形属性的出现,使Web前端中的元素展示不仅仅局限在二维空间,Web前端开发者可以通过旋转、扭曲、缩放或者移位等操作实现元素在三维控件上的展示。通过变形元素,web前端中的内容展示更加形象、真实 [40]。

7.过渡与动画

CSS3的“过渡”(transition)属性通过设定某种元素在某段时间内的变化实现一些简单的动画效果,让某些效果变得更加具有流线性与平滑性。CSS3的“动画”(animation)属性能够实现更复杂的样式变化以及一些交互效果,而不需要使用任何Flash或JavaScript脚本代码。过渡与动画的出现,使CSS在Web前端开发中不再仅仅局限于简单的静态内容展示,而是通过简单的方法使页面元素动了起来,实现了元素从静到动的变化 [40]。

8.Web字体

CSS3中引入了@font-face,@font-face是链接服务器字体的一种方式,这些嵌入的字体能变成浏览器的安全字体,开发人员不用再担心用户没有这些字体而导致网页在用户浏览器无法正常显示的问题 [40]。

9.媒体查询

CSS3中引入媒体查询(mediaqueries),可为不同分辨率的设备定义不同的样式。比如,在可视区域小于480像素时,可能想让原来在右侧的网站侧栏显示在主内容的下边,以往必须通过JavaScript判断用户浏览器的分辨率,然后再通过JavaScript修改CSS。CSS3中只需要通过媒体查询就可实现上述操作 [40]。

10.阴影

阴影主要分为两种:文本阴影(text-shadow)和盒子阴影(box-shadow)。文本阴影在CSS2中已经存在,但没有得到广泛的运用(CSS2.1中删除了)。CSS3延续了这个特性,并进行了新的定义,该属性提供了一种新的跨浏览器解决方案,使文本看起来更加醒目。CSS3中的盒子阴影的引入,可轻易地为任何元素添加盒子阴影 [40]。

画一个旋转的动画:

@keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.rotate {
animation: rotate 2s linear infinite;
}
上面的代码定义了一个名为rotate的关键帧动画,从0度旋转到360度。然后将这个动画应用到一个元素上,例如一个图片或者一个div,通过添加.rotate类名来实现旋转动画。你可以根据自己的需要调整动画的持续时间、旋转角度以及其他属性来实现不同的效果。

css哪些属性不能继承 定位属性(position、top、right、bottom、left、z-index)

盒模型属性(margin、padding、border、width、height)

背景属性(background-color、background-image、background-repeat、background-position)

边框属性(border-style、border-width、border-color)

清除浮动属性(clear)

浮动属性(float)

显示属性(display)

渐变属性(linear-gradient、radial-gradient)

伪元素相关属性(::before、::after)

css哪些属性可以继承

字体属性(font-family、font-size、font-weight、font-style)

文本属性(color、text-align、text-decoration、line-height)

列表属性(list-style-type、list-style-position、list-style-image)

表格属性(border-collapse、border-spacing、caption-side)

元素框属性(margin、padding、border、width、height)

一些其他属性(visibility、cursor、white-space、overflow)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值