HTML语义化

  • html语义化是指在使用html标签构建页面的时候,避免大篇幅的使用无语义的标签,比如span div,尽可能的使用带有语义的标签,比如header footer aside main h1-16等

  • 使用语义化标签的好处
    (1)结构清晰,易于用户阅读
    (2)增加代码的可读性,有利于开发和维护
    (3)有利于搜索引擎的SEO优化,提高网站的排名
    (4)有利于屏幕阅读器的解析


CSS盒模型

  • CSS盒模型定义了盒子的每一个部分,包括margin border padding content
  • 根据盒子大小的计算方式不同可以分为标准盒模型和怪异盒模型
  • 标准盒模型:设置width和height实际上设置的时content,border padding和width height一起决定了盒子的大小
  • 怪异盒模型:设置width和height包含了border和padding,width和height就是盒子的实际大小
  • 设置标准盒模型: box-sizing: content-box
  • 设置怪异盒模型: box-sizing: border-box

浮动和清除浮动

  • 浮动包括左浮动 float:left 右浮动 float:right

  • 给图片设置浮动可以实现文字环绕
    给块级元素设置浮动可以使其在一行上排列
    对行内元素设置浮动,可以对齐进行宽高的设置

  • 给元素设置浮动,元素会脱离标准文档流
    给元素设置浮动,会改变元素的display属性,改变为display:block
    给元素设置浮动,如果父元素没有设置宽高,会造成父元素的高度塌陷,影响父元素后面的兄弟元素的布局

  • 清除浮动的方法:
    (1) 伪元素清除浮动
    (2) 双伪元素清除浮动
    (3) 给父元素添加overflow:hidden
    (4) 标签插入法:给父元素的末尾添加一个块级元素,并设置样式clear:both

 /* 1. 伪元素清除浮动 */
.clearfix::after{
  display: block;
  content: '';
  height: 0;
  clear: both;
}
.clearfix{
  *zoom:1;
}

/* 2. 双伪元素清除浮动 */
.clearfix::before, .clearfix::after{
  display: table;
  content: '';
}
.clearfix::after{
  clear:both;
}
.clearfix{
  *zoom:1;
}

CSS样式优先级的规则是什么

  • CSS的样式优先级是根据权重来计算的,高位权重的优先级永远大于低位权重的优先级,低位权重无法通过叠加来超过高位权重

  • !important
    内联样式
    嵌入样式和外链样式
    继承样式
    浏览器默认样式

  • 权重:
    !important 10000
    内联样式 1000
    id选择器 100
    类选择器 伪类选择器 属性选择器 10
    元素选择器 伪元素选择器 1
    子选择器 相邻选择器 通配符选择器 0


CSS尺寸设置的单位

  • CSS尺寸单位有 px em rem vw vh

  • px:绝对长度单位,大小取决于屏幕分辨率
    em:相对长度单位,在font-size中使用,相对于父元素的字体大小,在其他属性中使用,取决于父元素的字体大小,由于字体大小可继承,可以逐级向上查找,如果最终找不到,则使用浏览器默认字体大小
    rem:相对长度单位,相对于html根元素的字体大小,如果根元素没有设置字体大小,则相对于浏览器默认字体大小
    vw:相对长度单位,大小为视窗宽度的1%
    vh:相对长度单位,大小为视窗高度的1%

  • 页面响应式的实现方式有:
    rem配合媒体查询或flexible.js
    rem配合vw

  • rem配合配体查询或者flexible.js的原理:通过媒体查询或flexible.js,当屏幕尺寸发生改变时,重置html根元素的字体大小,页面中的元素都使用rem为单位,当根元素字体大小改变时,其他元素的尺寸也随之改变

  • rem配合vw的原理:使用vw设置根元素的html字体大小,当窗口大小发生改变时,vw代表的尺寸也随之改变,无需使用媒体查询或flexible.js,页面中的其他元素仍使用rem为单位,就可以实现响应式


BFC

  • BFC是什么
    BFC是 Block Formatting Context的缩写,意思是块级格式化上下文

  • BFC有哪些特性
    (1)BFC是一块独立的渲染区域,内部元素的渲染不会影响边界以外的元素
    (2)属于同一个BFC的两个相邻的盒子的margin会发生重叠
    (3)BFC区域不会与float-box区域重叠
    (4)计算BFC的高度时,浮动元素也参与计算

  • BFC形成的条件
    (1)float: left
    (2)float: right
    (3)position: absolute
    (4)position: fixed
    (5)overflow: auto
    (6)overflow: scroll
    (7)overflow: hidden
    (8)overflow: flex
    (9)display: inline-bolock

  • BFC能做什么
    (1)清除浮动
    (2)解决外边距塌陷的问题
    (3)实现自适应两列布局

  • BFC的方式都可以清除浮动,但是常用的只有 overflow-hidden


未知宽高元素水平垂直居中的方法

  1. 绝对定位 + transform
.parent{
  position: relative;
}
.son{
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
  1. table-cell
.parent{
  display: table-cell;
  vertical-align: middle;
  text-align: center;
}

.son{
  display: inline-block;
}
  1. flex布局
.parent{
  display: flex;
  justify-conent: center;
  align-items: center;
}
  1. grid布局
.parent{
  display: grid;
  justify-content: center;
  align-items: center;
}

三栏布局的实现方案

三栏布局简述

  1. 三栏布局要求左右定宽,中间宽度自适应,所有盒子的高度随内容撑开
  2. 一般中间盒子的内容较多,为了页面渲染速度快,中间盒子放在左右盒子的前面

实现三栏布局的实现方案

  1. 圣杯布局
  2. 双飞翼布局

圣杯布局的实现方案

  1. 三个盒子放在同一个父级元素中
  2. 中间盒子放在左右盒子的前面
  3. 父级盒子设置左右padding
  4. 三个盒子全部浮动
  5. 中间盒子宽度100%
  6. 左右盒子定宽
  7. 左边盒子设置margin-left:-100%
  8. 右边盒子设置margin-right:负的自身宽度
  9. 父级盒子清除浮动
<html>

<head>
  <style>
    .header{
      height: 100px;
      background-color: pink;
    }
    .footer{
      height: 100px;
      background-color: green;
      clear:both;
    }
    .container{
      height: 200px;
      padding-left: 200px;
      padding-right: 150px;
    }
    .container .column{
      float: left;
      height: 200px;
    }
    .center{
      background-color: red;
      width: 100%;
    }
    .left{
      background-color: yellow;
      width:200px;
      margin-left:-100%;
      position: relative;
      right:200px;
    }
    .right{
      background-color: blue;
      width: 150px;
      margin-right: -150px;
    }
  </style>
</head>

<body>
  <div class="header">
  </div>
  <div class="container">
    <div class="center column">
    </div>
    <div class="left column"></div>
    <div class="right column"></div>
  </div>
  <div class="footer"></div>
  <div class="xxx1"></div>
  <div class="xxx2"></div>
</body>

</html>

双飞翼布局实现方案

  1. 三个盒子放在同一个父元素中
  2. 中间盒子放在左右盒子的前面
  3. 中间盒子套了两层,中间盒子的内部盒子设置左右margin
  4. 三个盒子全部浮动
  5. 中间盒子宽度100%
  6. 左右盒子定宽
  7. 左边盒子设置margin-left:-100%
  8. 右边盒子设置margin-left:负的自身宽度
  9. 父级盒子清除浮动
<html>

<head>
  <style>
    .header,.footer{
      height: 200px;
      width: 100%;
      background-color: #0000FF;
    }
    .content,.left,.right{
      float: left;
      height: 200px;
    }
    .content{
      width: 100%;
      background-color :red;
    }
    .left{
      width: 300px;
      background-color: pink;
      margin-left:-100%;
    }
    .right{
      width:300px;
      background-color: grey;
      margin-left: -300px;
    }
    .center{
      height:200px;
      margin-left: 300px;
      margin-right: 300px;
      background-color: green;
    }
    .container::after{
      display: block;
      content: '';
      height: 0;
      clear: both;
    }
  </style>
</head>

<body>
  <div class="header">头部</div>
  <div class="container">
    <div class="content">
      <div class="center">中间</div>
    </div>
    <div class="left">左边</div>
    <div class="right">右边</div>
  </div>
  <div class="footer">尾部</div>
</body>

</html>

优缺点

  • 圣杯布局:优点:比双飞翼布局少了一层dom节点 缺点:当中间部分的宽度小于左边部分的宽度时时就会发生布局混乱。
  • 双飞翼布局:优点:不会像圣杯布局那样变形,缺点:多加了一层dom节点

JS数据类型有哪些,区别是什么

JS数据类型一共有8种,分为基本数据类型和引用数据类型

其中基本数据类型有

  1. Number
  2. String
  3. Boolean
  4. Null
  5. Undefined
  6. Symbol
  7. BigInt

引用数据类型有

  1. Object:普通对象 数组 正则 日期 Math数学函数都属于Object

它们的区别是

  1. 基本数据类型和引用数据类型在内存中的存储方式不同
  2. 基本数据类型是直接存储在栈中的简单数据段,占用空间小
  3. 引用数据类型是存储在堆内存中,占用空间大
  4. 引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址
  5. 当解释器寻找引用值时,会检索其在栈中的地址,取得地址后从堆中获得实体

加分回答:
Symbol是ES6新出的一种数据类型,这种数据类型的特点是没有重复的数据,可以作为Object的key
Biglnt也是ES6新出的一种数据类型,特点是数据涵盖的范围大,能够解决超出普通数据类型范围报错的问题


null和undefined的区别,如何让一个属性变为null

undefined

  1. undefined是全局对象的一个属性,表示变量的初始状态
  2. 当一个变量没有被赋值、一个函数没有返回值、访问了不存在的对象属性或者函数定义了形参却没有传递实参,这时候都是undefined
  3. undefined通过typeof判断类型为undefined

null

  1. null表示对象的值未设置,相当于对象没有设置指针
  2. 要让一个对象的属性变为null,直接赋值为null就可以了
  3. 要释放一个对象,也是直接赋值为null就可以了
  4. null通过typeof判断类型为object

比较

  1. null == undefined
  2. null !== undefined

加分回答

  1. null的类型为null,而不是object类型,typeof之所以会判定为object类型,是因为JavaScript数据类型在底层都是以二进制的形式表示的,前三位为0就会被判定为object类型,而null的二进制位恰好都是0,所以就被误判断为object类型
  2. 当一个对象被赋值为null,对象在堆内存中的值就处于游离状态,在适当的时机会被回收释放,因此要释放一个对象,直接赋值为null就可以了

JavaScript有几种方法判断变量的类型

  1. typeof
  2. instanceof
  3. constructor
  4. Object.prototype.toString.call()

typeof

  • 常用于判断基本数据类型
  • 对于引用数据类型除了function返回function,其余全部返回object

instanceof:

  • 主要用于区分引用数据类型
  • 检测方法是检测的类型如果在当前实例的原型链上,用其检测出来的结果就是true,
  • 不太适合用于基本数据类型的检测

constructor:

  • 检测方法是获取当前实例的构造函数,
  • 然后判断和某个类是否相同

Object.prototype.toString.call()

  • 适用于所有类型的判断检测,
  • 返回的是该数据类型的字符串

数组去重有哪些方法

利用对象的key给数组去重,原理是对象的key不能重复

  1. 首先定义一个空的对象
  2. 然后使用filter方法对数组进行过滤
  3. 在回调函数中使用hasOwnProperty方法来判断对象是否存在该属性,入参是当前遍历的元素
  4. 如果存在则返回false
  5. 如果不存在,就把当前遍历元素作为对象的key,设置一个值,并返回true
function unique(arr) {
  let obj = {}
  return arr.filter((item, index, arr) => {
    return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true)
  })
}

利用Set构造函数给数组去重,原理是Set类型的数据没有重复值

  1. 首先new一个Set对象,参数为需要去重的数组
  2. Set会自动删除重复的元素
  3. 然后将Set转为数组返回
function unique(arr) {
  return Array.from(new Set(arr))
}

通过filter+indexOf去重,原理是indexOf方法会返回被查找元素首次出现的位置

  1. 使用filter方法对数组进行过滤
  2. 在回调函数中使用indexOf方法查找当前遍历元素的下标
  3. 然后和当前遍历的index做比较
  4. 如果相等则返回true,否则返回false
function unique(arr) {
  return arr.filter((item,index,arr) => {
    return arr.indexOf(item) === index
  })
}

利用双重循环去重

  1. for循环嵌套for循环
  2. 将外层循环的元素和内层循环的元素进行比较
  3. 如果值相同,则删除后面的那个元素
function unique(arr) {
  for(let i=0; i<arr.length; i++) {
    for (let j=i+1; j<arr.length; j++) {
      if(arr[i] === arr[j]) {
        arr.splice(j,1);
        j--;
      }
    }
  }
  return arr
}

通过reduce+includes给数组去重

  1. 使用reduce方法对数组元素进行迭代
  2. 传入一个空数组作为去重后的新数组
  3. 在回调函数中通过includes方法判断新数组中是否存在当前遍历的元素
  4. 如果不存在就插入到新的数组中
function unique(arr) {
  return arr.reduce((pre, cur)=>{
    return pre.includes(cur) ? pre : [...pre, cur]
  },[])
}

伪数组和数组的区别

  1. 伪数组的类型是Object,数组的类型是Array
  2. 伪数组可以使用length属性查看长度
  3. 也可以使用[index]获取某个属性
  4. 但是不可以使用数组的其他方法,比如push forEach等,也不能改变长度
  5. 遍历使用for in 方法

伪数组的常见场景

  1. 函数的arguments
  2. 原生js获取dom: document.querySelector(‘div’)
  3. juqery获取dom:$(‘div’)

伪数组转为真数组的方法:

  1. Arry.prototype.slice.call(伪数组)
  2. [].slice.call(伪数组)
  3. Array.from(伪数组)

转换后的数组长度由length属性决定
索引不连续时转换结果是连续的,会自动补位


Vue2.0双向绑定原理与缺陷

Object.defineProperty(object, propName, descript)

Object.defineProperty(object, propName, {
  get: function() {

  },
  set: function(newVal) {

  }
})
  • Vue双向绑定指的是组件的data发生改变,会立刻触发视图的更新

  • 原理:Vue采用数据劫持结合订阅者-发布者模式的方式实现数据的响应式,通过Object.defineProperty来劫持数据的getter和setter,当数据发生改变时,发送消息给订阅者,订阅者接收到消息之后进行相应的处理。通过原生JS提供的监听数据的API,在回调函数中修改dom

  • 核心API: Object.defineProperty
    Object.defineProperty用来定义对象的属性
    获取属性的时候会触发getter函数,修改属性的时候会触发setter函数,在setter函数中调用修改dom的方法

  • Object.defineProperty的缺点
    (1)一次性递归到底开销很大,当数据很大时,大量的递归会导致调用栈溢出
    (2)无法监听对象属性的添加和删除
    (3)无法监听数组下标的数据变化


讲一下vuex

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    num: 0
  },
  getters: {

  },
  mutations: {
    UPDATENUM(state, payload) {
      state.num = payload
    }
  },
  actions: {

  },
  modules: {

  }
})
// 获取
this.$store.state.num
// 设置
this.$store.commit('UPDATENUM', 0)

vue的data为什么必须使用函数

结论

因为对象是引用数据类型,如果你写成对象,这个组件在多处被引用,只要修改一处的值,那么另一处的引用的值也会变化,这样就乱套了。

而使用返回对象的函数,由于每次返回的都是一个新对象(Object的实例),引用地址不同,则不会出现这个问题。

举例

对象方式:

var data = {
	x: 1
}
var vm1 = {
	data: data
}
var vm2 = {
	data: data
}

vm1.data === vm2.data // => true,指向同一个对象

函数方式:

var func = function () {
	return {
		x: 1
	}
}

var vm3 = {
	data: func
}
var vm4 = {
	data: func
}
vm3.data() === vm4.data() // => false,指向不同对象

函数中data都指向同一个函数,但这个函数每次的返回值都是一个新的对象

{x:1} === {x:1} // => false
new Object({x:1}) === new Object({x:1}) // false

Vue组件生命周期

<template>
  <div>

  </div>
</template>
<script>
export default {
  data() {
    return {

    }
  },
  beforeCreate() {

  },
  created() {

  },
  beforeMount() {

  },
  mounted() {

  },
  beforeUpdate() {

  },
  updated() {

  },
  activated() {

  },
  deactivated() {

  },
  beforeDestroy() {

  },
  destroyed() {

  },
  errorCaptured() {
    
  }
}
</script>

vue组件之间有哪些传值 方式

props和 e m i t 实现父子组件传值, emit实现父子组件传值, emit实现父子组件传值,parent和 c h i l d r e n 获取父组件和子组件 , children获取父组件和子组件, children获取父组件和子组件,refs获取实例组件, e m i t / emit/ emit/on事件总线,vuex状态管理器。


你是如何封装组件的,封装过哪些组件?


vue router的原理

vue router的原理是更新视图但不重新请求页面,主要有两种方式hash模式和history模式。
hash模式和history模式直观的区别是hash模式带#,history模式不带#号
另外,hash模式的hash值虽然在url中,但不会被包括在http请求中,对后端完全没有影响,所以改变hash不会重新加载页面。
history模式则是利用了HTML5 history interface中新增的pushState()和replaceState()方法。history模式下,前端的URL必须和实际向后端发起请求的URL一致,比如http:www.xxx.com/user/id,如果后端缺少对/user/id的路由处理,将返回404错误,所以需要在服务端增加一个覆盖所有情况的候选资源。


vue router有哪些钩子

import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)

const Foo = {
  template: `...`,
  beforeRouteEnter(to, from, next) { // 组件内守卫

  },
  beforeRouteUpdate(to, from, next) { // 组件内守卫

  },
  beforeRouteLeave(to, from, next) { // 组件内守卫

  }
}

export default new Router({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter(to, from, next) { // 路由独享守卫

      }
    }
  ],
  beforeEach(to, from, next) { // 全局导航守卫

  },
  beforeResolve(to, from, next) { // 全局导航守卫

  },
  afterEach(to, from) { // 全局导航守卫

  }
})

Vue router路由有几种模式?History模式导致页面请求404如何解决?


前端性能优化

  • 图片压缩和文件压缩
  • 雪碧图/精灵图
  • 节流防抖
  • HTTP缓存
  • 本地缓存
  • keep-alive缓存
  • 服务端渲染
  • 懒加载
  • 对dom查询进行缓存
  • 将dom操作合并

vue的性能优化

vue性能优化可以从两方面进行优化,第一就是源码优化,第二就是打包优化。源码优化可以从提高组件的复用性,给for循环设置key值(可以更快的定位到diff),给路由设置懒加载,使用keep-alive对组件进行缓存几个方面进行优化,打包优化可以修改vue.config.js的配置项,把productionSourceMap设置成 false,使用cdn的方式加载一些外部资源,用css3的效果来代替 图片,按需引入几个方面来进行优化。


vue的一些webpack配置


vue3.0的新特性

压缩体积更小,使用es6的proxy代替defineProperty,Virtual DOM重构(虚拟DOM重构),编译时优化(Slot插槽默认编译为函数),更好的支持TypeScript。


从输入rul到浏览器显示页面发生了什么?


Vue项目的权限配置时如何配置的?


v-for为什么要使用key?讲一下deff算法


Vue computed和watch的区别?


闭包和作用域链

变量有两种:全局变量和局部变量。

函数内部可以直接读取全局变量,在函数外部无法读取函数内部的局部变量。

那么如何从外部读取函数内部的变量呢?正常情况下这是办不到的,只有通过变通的方法才能实现:那就是在函数内部再定义一个函数

function f1 () {
   var n = 999;
   function f2 () {
     alert(n); // ==> 999
   }
 }

在上面的代码中,函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来就不行,f2内部的局部变量,对f1是不可见的。这就是Javascript语言特有的“链式作用域”结构(chain scope),子对象会一级一级的向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的反之则不成立。

既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,我们不就可以在f1外部读取它的内部变量了吗!

function f1 () {
   var n = 999;
   function f2 () {
     alert (n);
   }
   return f2;
 }
 var result = f1();
 result(); // 999

闭包的概念

上一节代码中的f2函数,就是闭包。

简单的理解:闭包就是能够读取其他函数内部变量的函数,由于在JavaScript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单的理解成“定义在一个函数内部的函数”。
闭包和作用域链详解


Javascript原型链

原型:

①所有 引用类型 都有一个 __proto__(隐式原型)属性,属性值是一个普通的对象
②所有 函数 都有一个 prototype(原型)属性,属性值是一个普通的对象
③所有 引用类型的 __proto__ 属性 指向 它的 构造函数的prototype

原型链:

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

JavaScript原型和原型链详解


js事件循环


vue重复赋值一个变量,页面渲染几次


浏览器无痕模式(京东)


如何通过CSS制作一个箭头(京东)


真人试穿实现思路(京东)


直播实现思路(京东)


你在做项目的过程中遇到过什么难解决的问题,你是如何解决的?(京东)+ 其他面试也经常问到

Logo

前往低代码交流专区

更多推荐