前端面试

172 阅读3分钟

1.对语义化标签的理解

  • 头部:header
  • 导航:nav
  • 小结:section
  • 主体内容:main
  • 侧边栏:aside
  • 页脚:footer
  • 网页加载慢导致CSS文件还未加载时(当没有样式),页面仍然清晰、可读、好看、不混乱。
  • 提升用户体验,例如title、alt可用于解释名词或解释图片信息。
  • 有利于SEO:和搜索引擎建立良好沟通,有助于爬虫抓取更多的有效信息。
  • 方便其他设备(如屏幕阅读器、盲人阅读器、移动设备)更好的解析页面。
  • 使代码更具可读性,便于团队开发和维护。

2.SEO、SPA

SEO:

中文一般译作:搜索引擎优化,调整网站,以提高该网站在搜索引擎中某些关键词的搜索结果排名。

  • 使用语义化标签
  • 标题: 即<title>标签
  • 描述: 即HTML<meta>标签的description
  • 关键字: 即HTML<meta>标签的keywords
  • 尽量只使用一个<h1>并包裹重要内容,如logo、某些重要关键词
  • <img>加alt属性

vue seo方案

  1. SSR服务端渲染
  2. 预渲染(推荐):利用库 prerender-spa-plugin + vue-meta-info 配置webpack和页面实现预渲染方案,最终build出来多个html文件

SPA:

在传统的网站中,不同的页面之间的切换都是直接从服务器加载一整个新的页面,而在SPA这个模型中,是通过动态地重写页面的部分与用户交互,而避免了过多的数据交换,响应速度自然相对更高。

SPA的优点

基本上前面所说的前后端分离的优点它都有,另外还有以下的一些优点

  • 页面之间的切换非常快
  • 一定程度上减少了后端服务器的压力(不用管页面逻辑和渲染)
  • 后端程序只需要提供API,完全不用管客户端到底是Web界面还是手机等

SPA的缺点

  • 首屏打开速度很慢,因为用户首次加载需要先下载SPA框架及应用程序的代码,然后再渲染页面。
  • 不利于SEO

根据这几个缺点,我们便又引出了接下来讨论的两个主题,SEO和SSR,先谈谈SEO。

3.盒模型

默认为标准盒模型(box-sizing: content-box) dom实际宽度 = width + padding + border (也就是所谓的撑开盒子) IE盒模型(也称怪异盒模型box-sizing: border-box) dom实际宽度 = width

4.图片懒加载

参考
IntersectionObserver的使用

5.scrollWidth、clientWidth、offsetWidth、width的区别

scrollWidth为实际内容的宽度。
clientWidth是内容可视区的宽度。
offsetWidth是元素的实际宽度。

image.png offsetWidth属性可以返回对象的padding+border+元素width属性值之和,style.width返回值就是定义的width属性值。
offsetWidth属性仅是可读属性,而style.width是可读写的。
offsetWidth属性返回值是整数,而style.width的返回值是字符串,并且带有单位。
4.style.width仅能返回以style方式定义的内部样式表的width属性值。

6.页面的加载与渲染顺序

页面的加载与渲染顺序:

1.一个页面的加载顺序是从上到下顺序加载的,并且加载与渲染同时进行。

2.引用外部js文件时,当在加载过程中遇到

因为浏览器需要1个稳定的DOM树结构,而JS中很有可能有代码直接改变了DOM树结构,比如使用document.write 或 appendChild,甚至是直接使用的location.href进行跳转,浏览器为了防止出现JS修改DOM树,需要重新构建DOM树的情况,所以加载js就会阻塞其后内容的下载和呈现。

3.使用嵌入式js时,会阻塞所有内容的呈现。

4.当在加载过程中遇到标签时,浏览器会发1个request去请求CSS或image,然后继续执行下面的转换,而不需要等待request的返回,当request返回后,只需要把返回的内容放入到DOM树中对应的位置就OK,所以正常来说CSS并不会诸塞页面。

但是也有例外:

当CSS后面跟着嵌入的JS的时候,该CSS就会出现阻塞后面资源下载的情况。

原因:

因为浏览器会维持html中css和js的顺序,样式表必须在嵌入的JS执行前先加载、解析完。而嵌入的JS会阻塞后面的资源加载,所以就会出现上面CSS阻塞下载的情况。

JS

1.变量的生命周期

VUE

1.实现v-model

子组件

<template>
    <input :value="value" @input="dataChange" />
</template>

<script>
export default {
    props: {
        value: {
            type: [String, Number],
            default: '',
            require: true
        }
    },
    model: { // 自定义v-model的格式
        prop: '', // 代表 v-model 绑定的prop名 
        event: '' // 代码 v-model 通知父组件更新属性的事件名
    },
    methods: {
        dataChange(e) {
            console.log(e);
            this.$emit('input', e.target.value)
        }
    }
}
</script>

父组件

<template>
  <Index v-model="data" />
</template>

<script>
import Index from './components/v-model'
export default {
    components: {
        Index
    },
    data() {
        return {
            data: '父组件值'
        }
    }
}
</script>

2.props 给Object Array默认值的时候 为什么需要使用到函数工厂

参考
和Vue 中的data类似
组件中的 data 写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新的 data,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。而单纯的写成对象形式,就使得所有组件实例共用了一份 data,就会造成一个变了全都会变的结果