Bootstrap

【2024最新版】Vue前端面试篇,看这一篇就够了

在这里插入图片描述


更多相关内容可查看

以下面试内容皆为2024年各大网站的面经题目,答案均为自己或gpt整理,并会不断补充

Vue常用的指令都有哪些

Vue.js提供了一些内置的指令,可以在模板中使用,以下是一些常用的Vue指令:

  1. v-bind:用于绑定元素属性和数据对象的属性。例如:v-bind:classv-bind:style

  2. v-model:用于在表单控件或者组件上创建双向数据绑定。

  3. v-show:根据表达式之真假值,切换元素的显示/隐藏状态。

  4. v-ifv-elsev-else-if:用于条件渲染,根据表达式的值的真假来决定是否渲染元素。

  5. v-for:用于渲染列表,基于源数据多次渲染元素或模板块。

  6. v-on:用于监听DOM事件,可以用来触发方法。例如:v-on:click

  7. v-text:更新元素的 textContent

  8. v-html:更新元素的 innerHTML

  9. v-pre:跳过这个元素和它的子元素的编译过程。

  10. v-cloak:这个指令保持在元素上直到关联实例结束编译。

  11. v-once:只渲染元素和组件一次。

这些指令可以帮助你创建动态和响应式的Web应用。

v-bind和v-model的区别

v-bindv-model 都是 Vue.js 中的指令,用于创建数据和 DOM 元素之间的绑定。但是,它们之间有一些重要的区别:

  1. v-bind:这个指令用于单向数据绑定,它将数据从 Vue 实例绑定到 DOM 元素。当 Vue 实例中的数据变化时,这些变化会自动反映到 DOM 元素上。但是,如果用户在浏览器中更改了 DOM 元素(例如,通过输入框输入文本),这些更改不会反映回 Vue 实例。v-bind 可以用于任何类型的 HTML 属性,如 classstylesrc 等。

  2. v-model:这个指令用于实现双向数据绑定,主要用于表单元素。它不仅将数据从 Vue 实例绑定到 DOM 元素,而且还将数据从 DOM 元素绑定回 Vue 实例。这意味着,如果用户在浏览器中更改了 DOM 元素(例如,通过输入框输入文本),这些更改会自动反映回 Vue 实例。v-model 只能用于表单元素。

总的来说,v-bind 用于单向数据绑定,而 v-model 用于双向数据绑定。

Vue2的生命周期有哪些

Vue实例从创建到销毁的过程,就是生命周期。从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,我们称之为Vue的生命周期。具体可以分为以下几个阶段:

  1. beforeCreate:在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。

  2. created:在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。

  3. beforeMount:在挂载开始之前被调用:相关的 render 函数首次被调用。

  4. mounted:el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el 也在文档内。

  5. beforeUpdate:数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。

  6. updated:由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。

  7. beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。

  8. destroyed:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

这些生命周期钩子提供了在不同阶段添加自己的代码的机会。

Vue3的生命周期有哪些

在 Vue 3 中,由于引入了 Composition API,生命周期钩子的名称有所改变,以适应新的 API。以下是 Vue 3 的生命周期钩子:

  1. beforeCreatecreated 在 Vue 3 中被替换为 setup

  2. beforeMount:在挂载开始之前被调用,对应 Vue 2 中的 beforeMount。在 Vue 3 中,使用 onBeforeMount

  3. mounted:在挂载完成后被调用,对应 Vue 2 中的 mounted。在 Vue 3 中,使用 onMounted

  4. beforeUpdate:在数据更新之前被调用,对应 Vue 2 中的 beforeUpdate。在 Vue 3 中,使用 onBeforeUpdate

  5. updated:在数据更新后被调用,对应 Vue 2 中的 updated。在 Vue 3 中,使用 onUpdated

  6. beforeUnmount:在卸载组件之前被调用,对应 Vue 2 中的 beforeDestroy。在 Vue 3 中,使用 onBeforeUnmount

  7. unmounted:在卸载组件后被调用,对应 Vue 2 中的 destroyed。在 Vue 3 中,使用 onUnmounted

  8. activateddeactivated:这两个钩子函数主要用在 keep-alive 组件中,当组件被激活和停用时分别调用。

  9. errorCaptured:当捕获一个来自子孙组件的错误时被调用。

  10. renderTrackedrenderTriggered:这两个新的调试钩子函数在追踪和触发组件的重新渲染时被调用。

以上就是 Vue 3 中的生命周期钩子。

vue3中创建响应式变量的方法

在 Vue 3 中,创建响应式变量的主要方法是使用 refreactive

  1. ref:创建一个响应式的数据对象。ref 会返回一个响应式对象,其中包含一个 .value 属性用于获取或设置该响应式变量的值。
import { ref } from 'vue';

export default {
  setup() {
    const count = ref(0);  // 创建一个响应式变量 count,初始值为 0

    return {
      count
    };
  }
};

在模板中,可以直接使用 count,Vue 会自动处理 .value

<template>
  <div>{{ count }}</div>
</template>
  1. reactive:创建一个响应式的对象。reactive 会返回一个新的响应式对象,该对象与原始对象具有相同的属性和值,但是所有的属性都是响应式的。
import { reactive } from 'vue';

export default {
  setup() {
    const state = reactive({ count: 0 });  // 创建一个响应式对象 state,包含一个 count 属性,初始值为 0

    return {
      state
    };
  }
};

在模板中,可以直接使用 state.count

<template>
  <div>{{ state.count }}</div>
</template>

需要注意的是,refreactive 创建的响应式变量或对象,只有在 setup 函数中返回后,才能在模板中使用。

ref和reactive原理

Vue 3 使用了 Proxy 对象来实现响应式系统,这是一个 ES6 的新特性。Proxy 可以拦截对象的各种操作,包括属性读取、属性设置、属性删除等,这使得 Vue 3 的响应式系统能够更好地跟踪和响应状态的变化。

  1. refref 函数会创建一个包含 .value 属性的对象,并且这个对象是响应式的。当我们获取 .value 属性时,ref 会使用 Proxy 的 get 拦截器来跟踪这个依赖;当我们设置 .value 属性时,ref 会使用 Proxy 的 set 拦截器来触发更新。
function ref(value) {
  return reactive({ value });
}
  1. reactivereactive 函数会创建一个新的 Proxy 对象,这个 Proxy 对象会拦截所有的属性操作。当我们获取属性时,reactive 会使用 Proxy 的 get 拦截器来跟踪这个依赖;当我们设置属性时,reactive 会使用 Proxy 的 set 拦截器来触发更新。
function reactive(target) {
  return new Proxy(target, {
    get(target, prop) {
      // 跟踪依赖
      track(target, prop);
      return target[prop];
    },
    set(target, prop, value) {
      target[prop] = value;
      // 触发更新
      trigger(target, prop);
      return true;
    }
  });
}

在 Vue 3 的响应式系统中,track 函数用于跟踪依赖,trigger 函数用于触发更新。当我们访问响应式对象的属性时,track 函数会把当前的副作用函数(即依赖于这个属性的函数)添加到这个属性的依赖列表中;当我们修改响应式对象的属性时,trigger 函数会运行这个属性的依赖列表中的所有副作用函数,从而实现状态的响应式更新。

vuex有哪些方法

Vuex 主要包含以下几个部分:

  1. State:Vuex 使用单一状态树,用一个对象就包含了全部的应用层级状态。每个应用将仅仅包含一个 store 实例。

  2. Getters:有时候我们需要从 store 中的 state 中派生出一些状态,例如对列表进行过滤并计数。Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。

  3. Mutations:更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件,每个 mutation 都有一个字符串的事件类型 (type) 和一个回调函数 (handler)。

  4. Actions:Action 类似于 mutation,不同在于,Action 提交的是 mutation,而不是直接变更状态。Action 可以包含任意异步操作。

  5. Modules:随着应用复杂度的增加,store 对象就可能变得相当臃肿。为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter,甚至是嵌套子模块。

以下是 Vuex 的基本使用方法:

// 创建一个 store
const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  }
})

// 在组件中使用
new Vue({
  el: '#app',
  computed: {
    count () {
      return store.state.count
    }
  },
  methods: {
    increment () {
      store.commit('increment')
    }
  }
})

在这个例子中,我们首先创建了一个包含 count 状态和 increment mutation 的 store,然后在 Vue 组件中使用这个 store。我们可以通过 store.state.count 来访问状态,通过 store.commit('increment') 来提交 mutation。

vue-router生命周期钩子

Vue Router 提供了一些导航守卫(也称为路由生命周期钩子),可以在路由导航过程中进行一些操作。以下是 Vue Router 提供的导航守卫:

  1. 全局前置守卫router.beforeEach,这是最常用的导航守卫,它会在路由发生变化之前被调用:

    const router = new VueRouter({ ... })
    
    router.beforeEach((to, from, next) => {
      // 在这里进行一些操作,例如检查用户是否已登录
      if (to.path === '/login' || isLoggedIn()) {
        next()
      } else {
        next('/login')
      }
    })
    
  2. 全局解析守卫router.beforeResolve,这个守卫会在路由被确认之前,但是在组件被解析之后被调用:

    router.beforeResolve((to, from, next) => {
      // 在这里进行一些操作
      next()
    })
    
  3. 全局后置钩子router.afterEach,这个钩子没有 next 函数,也不能改变导航:

    router.afterEach((to, from) => {
      // 在这里进行一些操作,例如更新页面标题
      document.title = to.meta.title
    })
    
  4. 路由独享的守卫:在路由配置上直接定义 beforeEnter

    const router = new VueRouter({
      routes: [
        {
          path: '/foo',
          component: Foo,
          beforeEnter: (to, from, next) => {
            // 在这里进行一些操作
            next()
          }
        }
      ]
    })
    
  5. 组件内的守卫:在路由组件内部直接定义以下三个方法:

    • beforeRouteEnter
    • beforeRouteUpdate(2.2 新增)
    • beforeRouteLeave
    const Foo = {
      template: `...`,
      beforeRouteEnter (to, from, next) {
        // 在渲染该组件的对应路由被 confirm 前调用
        // 不!能!获取组件实例 `this`
        // 因为当守卫执行前,组件实例还没被创建
      },
      beforeRouteUpdate (to, from, next) {
        // 在当前路由改变,但是该组件被复用时调用
        // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,由于会渲染同样的 Foo 组件,因此组件实例会被复用
        // 而这个钩子就会在这个情况下被调用
        // 可以访问组件实例 `this`
      },
      beforeRouteLeave (to, from, next) {
        // 导航离开该组件的对应路由时调用
        // 可以访问组件实例 `this`
      }
    }
    

以上就是 Vue Router 提供的导航守卫,可以根据需要选择使用。

vue框架和原生JavaScript有什么区别

Vue.js是一个JavaScript框架,它是用来构建用户界面的。与原生JavaScript相比,Vue.js提供了许多高级功能和工具,可以帮助开发者更快速、更有效地开发复杂的单页应用。以下是Vue.js和原生JavaScript的一些主要区别:

  1. 数据绑定:Vue.js提供了数据绑定功能,可以让开发者在JavaScript和HTML之间建立数据绑定,当数据发生变化时,视图会自动更新。而在原生JavaScript中,开发者需要手动操作DOM来更新视图。

  2. 组件化:Vue.js支持组件化开发,开发者可以创建可复用的组件,这可以提高代码的可维护性和可读性。而在原生JavaScript中,开发者需要手动管理代码的结构和复用性。

  3. 指令:Vue.js提供了一些内置的指令,如v-if、v-for、v-bind等,这些指令可以让开发者更方便地操作DOM。而在原生JavaScript中,开发者需要手动编写这些操作。

  4. 生命周期钩子:Vue.js提供了生命周期钩子函数,开发者可以在特定的时间点执行特定的操作。而在原生JavaScript中,开发者需要自己管理这些操作的执行时机。

  5. 虚拟DOM:Vue.js使用虚拟DOM来提高性能,只有当数据发生变化时,才会更新对应的DOM元素。而在原生JavaScript中,任何对DOM的操作都会立即反映在视图上,这可能会导致性能问题。

  6. 工具和插件:Vue.js有许多相关的工具和插件,如Vue Router、Vuex等,这些工具和插件可以帮助开发者更方便地开发复杂的应用。而在原生JavaScript中,开发者需要自己寻找或者开发这些工具和插件。

总的来说,Vue.js和原生JavaScript的主要区别在于,Vue.js提供了许多高级功能和工具,可以帮助开发者更方便、更高效地开发复杂的应用。而原生JavaScript更灵活,但是需要开发者自己管理更多的细节。

对于提升项目加载速度和运行效率是怎么做的

提升项目加载速度和运行效率是前端开发中的重要任务。以下是一些常见的优化策略和方法:

  1. 代码压缩和合并:通过工具如UglifyJS和webpack等,可以压缩JavaScript和CSS代码,去除空格、注释、缩短变量名等,减小文件大小。合并多个文件为一个,减少HTTP请求次数。

  2. 使用CDN:使用内容分发网络(CDN)可以将静态资源分布到全球的各个数据中心,用户可以从最近的服务器获取资源,减少延迟。

  3. 图片优化:对图片进行压缩,减小文件大小。使用CSS Sprite技术,将多个小图标合并为一张大图,减少HTTP请求次数。对于大图片,可以考虑使用懒加载技术。

  4. 使用缓存:利用浏览器缓存机制,对静态资源进行缓存,减少重复的HTTP请求。对于动态内容,可以考虑使用应用级别的缓存,如Redis。

  5. 代码分割和异步加载:通过webpack等工具,可以将代码分割为多个小的模块,按需异步加载,减少首屏加载时间。

  6. 优化CSS:将关键CSS(渲染首屏需要的CSS)内联在HTML中,减少阻塞渲染的时间。避免使用耗性能的CSS属性,如高级选择器、box-shadow等。

  7. 使用SSR或预渲染:对于首屏渲染性能要求高的应用,可以考虑使用服务器端渲染(SSR)或预渲染技术。

  8. 优化JavaScript执行:避免使用耗性能的JavaScript操作,如大量的DOM操作、大数据的计算等。对于复杂的操作,可以考虑使用Web Worker在后台线程中执行。

  9. 使用PWA技术:通过Service Worker和Cache API,可以实现离线缓存和网络优先的策略,提高加载速度。

  10. Tree Shaking:利用Tree Shaking技术,去除没有使用的代码,减小打包后的文件大小。

以上是一些常见的优化策略和方法,具体使用哪种方法,需要根据项目的具体情况来决定。

webpack能做什么优化,具体的优化是什么

Webpack是一个强大的模块打包工具,它可以对项目进行许多优化。以下是一些常见的Webpack优化策略:

  1. 代码压缩:Webpack内置了UglifyJS插件,可以自动压缩生成的JavaScript代码。对于CSS和HTML,也有相应的插件如cssnano和html-minifier。

  2. 代码分割:Webpack支持代码分割,可以将代码分割为多个小的模块,按需加载,减少首屏加载时间。

  3. Tree Shaking:Webpack支持Tree Shaking,可以自动去除没有使用的代码,减小打包后的文件大小。

  4. 提取公共代码:Webpack可以将多个模块中的公共代码提取出来,生成一个公共的模块,减少代码的重复。

  5. 懒加载:Webpack支持懒加载,可以将不常用的功能进行懒加载,只有在需要的时候才加载,提高首屏加载速度。

  6. 模块热替换:Webpack的模块热替换功能可以在不刷新页面的情况下替换、添加或删除模块,提高开发效率。

  7. 使用Loader:Webpack的Loader机制可以处理各种类型的资源,如CSS、图片、字体等,并将它们转化为模块。

  8. 使用插件:Webpack有许多插件,可以完成各种各样的任务,如生成HTML文件、清理输出目录、自动刷新浏览器等。

  9. 优化解析速度:Webpack可以通过配置resolve.alias来缩短查找路径,提高解析速度。

  10. Scope Hoisting:Webpack的Scope Hoisting可以减少函数声明的数量和内存占用,提高运行速度。

以上是Webpack的一些常见优化策略,具体使用哪种优化策略,需要根据项目的具体需求来决定。

webpack和vite的区别

Webpack和Vite都是前端构建工具,但它们在设计理念和使用方式上有一些区别:

  1. 开发环境下的模块热更新:Webpack在开发环境下,当一个文件发生变化时,会重新构建整个应用,然后通过HMR(Hot Module Replacement)更新改变的部分。这在大型项目中可能会导致重新构建的时间较长。而Vite则采用了一种不同的方式,它在开发环境下利用原生的ES Module进行模块加载,当一个文件发生变化时,只需要重新请求改变的文件,因此更新速度更快。

  2. 构建速度:Webpack使用JavaScript进行编译,而Vite则使用esbuild进行编译。esbuild是用Go语言编写的,编译速度比Webpack快很多。

  3. 配置:Webpack的配置相对复杂,有许多选项可以配置。而Vite的配置相对简单,更易于上手。

  4. 插件系统:Webpack有一个成熟的插件系统,有许多社区提供的插件可以使用。Vite也有插件系统,但相对来说还不如Webpack成熟。

  5. 兼容性:Webpack由于历史更久,对旧版浏览器的兼容性更好。而Vite主要针对现代浏览器,对旧版浏览器的兼容性不如Webpack。

  6. 开箱即用的特性:Vite内置了对Vue、React、Preact、lit-element等现代框架的支持,以及对TypeScript、CSS Modules、PostCSS等现代语言特性的支持,开箱即用。

总的来说,Webpack和Vite各有优势,选择哪个工具需要根据项目的具体需求来决定。

nodejs用来干什么,作用是什么

Node.js是一个基于Chrome V8引擎的JavaScript运行环境。它使得JavaScript可以脱离浏览器环境,在服务器端运行,从而使得JavaScript成为一种全栈开发语言。以下是Node.js的一些主要用途和作用:

  1. 构建Web服务器:Node.js可以用来构建高性能的Web服务器。由于其事件驱动和非阻塞I/O模型,Node.js非常适合处理高并发的请求。

  2. 后端API开发:Node.js可以用来开发RESTful API,提供数据给前端应用。它可以配合Express、Koa等Web框架进行开发。

  3. 实时应用:Node.js非常适合开发实时应用,如即时通讯、实时数据推送等。它可以配合Socket.IO等库进行开发。

  4. 全栈开发:Node.js可以配合前端框架如React、Vue等进行全栈开发,前后端都使用JavaScript,提高开发效率。

  5. 命令行工具:Node.js可以用来开发命令行工具,如脚手架工具、构建工具等。例如,Vue CLI、Webpack等就是用Node.js开发的。

  6. 服务器端渲染:Node.js可以配合React、Vue等前端框架进行服务器端渲染,提高首屏加载速度,优化SEO。

  7. 数据库操作:Node.js可以配合MongoDB、MySQL等数据库进行数据操作,进行增删改查等操作。

  8. 微服务架构:Node.js可以用来构建微服务架构,每个服务都是一个小的Node.js应用,通过API进行通信。

总的来说,Node.js是一个非常强大的工具,可以用来进行各种服务器端的开发。

Express模块可以做什么

Express是一个基于Node.js平台的极简、灵活的web应用开发框架,它提供一系列强大的特性来帮助创建各种Web和移动设备应用。

以下是Express模块的一些主要功能:

  1. 路由控制:Express提供了强大的路由API,可以方便地定义URL的路由规则,以及对应的处理函数。

  2. 中间件:Express的中间件机制可以方便地处理请求和响应,例如解析请求体、处理Cookie、记录日志、处理错误等。

  3. 模板引擎:Express支持多种模板引擎,如Pug、EJS等,可以方便地生成HTML。

  4. 静态文件服务:Express可以方便地提供静态文件服务,例如提供图片、CSS文件、JavaScript文件等。

  5. 错误处理:Express提供了错误处理机制,可以方便地捕获和处理错误。

  6. API开发:Express常常用于开发RESTful API,提供数据给前端应用。

  7. 集成数据库:Express可以方便地集成数据库,例如MongoDB、MySQL等,进行数据的增删改查操作。

  8. 服务器端渲染:Express可以配合前端框架如React、Vue等进行服务器端渲染。

总的来说,Express是一个非常强大的Web应用开发框架,可以帮助你快速地构建Web应用。

objext.defineproperty和proxy的原理和区别

Object.definePropertyProxy都是JavaScript中用来拦截和定义对象属性行为的方法,但它们的工作方式和能力有所不同。

Object.defineProperty

Object.defineProperty是ES5引入的方法,它可以在一个对象上定义一个新属性,或者修改一个对象的现有属性,然后返回这个对象。你可以指定这个属性的值,也可以指定这个属性的一些特性,例如是否可写、是否可枚举、是否可配置等。

Object.defineProperty的拦截能力相对有限,它只能拦截单个属性的读取和写入操作。例如:

var obj = {};
Object.defineProperty(obj, 'prop', {
  get: function() {
    console.log('get prop');
    return 'foo';
  },
  set: function(value) {
    console.log('set prop to ' + value);
  }
});

Proxy

Proxy是ES6引入的新特性,它可以在一个对象的操作上添加自定义行为。Proxy可以拦截对象的所有操作,包括读取、写入、删除属性,调用函数等。例如:

var obj = {};
var p = new Proxy(obj, {
  get: function(target, prop, receiver) {
    console.log('get ' + prop);
    return Reflect.get(target, prop, receiver);
  },
  set: function(target, prop, value, receiver) {
    console.log('set ' + prop + ' to ' + value);
    return Reflect.set(target, prop, value, receiver);
  }
});

区别

  1. 拦截能力Proxy的拦截能力更强,它可以拦截对象的所有操作,而Object.defineProperty只能拦截单个属性的读取和写入操作。

  2. 适用对象Object.defineProperty只能对现有的对象属性进行操作,如果属性不存在,需要先定义。而Proxy则没有这个限制。

  3. 性能:由于Proxy可以拦截所有操作,所以在某些情况下,Proxy的性能可能会比Object.defineProperty差一些。

  4. 兼容性Proxy是ES6的新特性,它的浏览器兼容性不如Object.defineProperty。如果需要支持老版本的浏览器,可能需要使用Object.defineProperty

websocket的你是用来做什么,说说具体的做法

WebSocket是一种网络通信协议,它在单个TCP连接上提供全双工(双向)通信通道。WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

以下是WebSocket的一些主要用途:

  1. 实时通讯:例如聊天应用、多人在线游戏等需要实时交互的应用。

  2. 实时数据推送:例如股票交易信息、新闻更新、实时天气等需要实时更新的信息。

  3. 实时监控:例如系统监控、设备监控等需要实时反馈的场景。

以下是使用WebSocket的基本步骤:

  1. 创建WebSocket对象:在JavaScript中,可以使用new WebSocket(url)来创建一个WebSocket对象,其中url是WebSocket服务的URL。

    var socket = new WebSocket("ws://localhost:8080");
    
  2. 监听连接事件:可以监听open事件,当WebSocket连接成功时,该事件会被触发。

    socket.onopen = function(event) {
      console.log("WebSocket is open now.");
    };
    
  3. 发送数据:可以使用send方法来发送数据。

    socket.send("Hello WebSocket!");
    
  4. 接收数据:可以监听message事件,当收到服务器发送的数据时,该事件会被触发。

    socket.onmessage = function(event) {
      console.log("WebSocket message received: ", event.data);
    };
    
  5. 关闭连接:可以使用close方法来关闭WebSocket连接。

    socket.close();
    
  6. 监听关闭事件:可以监听close事件,当WebSocket连接关闭时,该事件会被触发。

    socket.onclose = function(event) {
      console.log("WebSocket is closed now.");
    };
    

注意:WebSocket是一种较新的技术,虽然大多数现代浏览器都支持,但是在一些老的浏览器中可能不支持。

websocket和http的区别

WebSocket和HTTP都是网络通信协议,但它们在设计上有一些重要的区别:

  1. 连接方式:HTTP是无状态的,每次请求都需要建立新的连接,请求完成后连接就会断开。而WebSocket则是持久连接,一旦建立连接,客户端和服务器就可以在任何时间点进行双向通信,直到连接被关闭。

  2. 数据传输方向:HTTP是单向的,客户端发送请求到服务器,服务器返回响应到客户端。而WebSocket是全双工的,客户端和服务器都可以主动发送数据。

  3. 数据传输效率:HTTP请求和响应都需要包含头部信息,而且每次请求都需要新的TCP连接,这会带来一定的开销。而WebSocket在建立连接后,数据传输只需要极少的头部信息,而且可以复用已有的TCP连接,所以数据传输效率更高。

  4. 实时性:由于WebSocket是全双工的,并且是持久连接,所以它可以更好地支持实时性要求高的应用,例如聊天应用、实时游戏等。而HTTP由于是请求/响应模式,实时性较差。

  5. 用途:HTTP是通用的数据传输协议,用于传输HTML、图片、JSON、XML等各种类型的资源。而WebSocket主要用于实时、交互性强的场景,例如实时通讯、实时数据推送等。

  6. 兼容性:HTTP协议几乎被所有的网络设备和服务器支持,而WebSocket是较新的技术,虽然现代浏览器都支持,但在一些老的浏览器或网络设备上可能不支持。

介绍下网页加载的过程

网页加载的过程可以分为以下几个步骤:

  1. 输入URL:用户在浏览器的地址栏中输入网页的URL。

  2. DNS解析:浏览器会通过DNS(域名系统)将网页的域名解析为对应的IP地址。如果浏览器或操作系统已经缓存了这个域名的IP地址,则可以跳过这一步。

  3. 建立TCP连接:浏览器与服务器建立TCP连接,进行三次握手,确认连接已建立。

  4. 发送HTTP请求:浏览器向服务器发送HTTP请求,请求中包含了要访问的网页文件,如HTML文件。

  5. 服务器处理请求并返回HTTP响应:服务器处理浏览器的请求,然后返回一个HTTP响应,响应中包含了网页的HTML内容。

  6. 浏览器解析HTML:浏览器开始解析HTML文件,构建DOM树(文档对象模型)。在解析过程中,如果遇到CSS、JavaScript、图片等外部资源的链接,浏览器会再次发送HTTP请求获取这些资源。

  7. 构建CSSOM树:浏览器解析CSS文件,构建CSSOM树(CSS对象模型)。

  8. 执行JavaScript代码:如果HTML中包含JavaScript代码,浏览器会执行它。注意,JavaScript的执行可能会修改DOM树和CSSOM树。

  9. 渲染:浏览器根据DOM树和CSSOM树,计算出每个可见元素的布局和样式,然后绘制到屏幕上,这个过程称为渲染。

  10. 加载完成:当所有的CSS、JavaScript、图片等外部资源都加载完成,浏览器会触发load事件,表示网页加载完成。

以上是一个简化的网页加载过程,实际上在现代浏览器中,为了提高性能,很多步骤会并行进行。例如,浏览器在下载HTML的同时,就会开始解析和渲服务压力大,请稍后再试

flex布局的属性

Flex布局(Flexible Box)是CSS3引入的一种新的布局模式,设计目的是提供一种更加有效的方式来对容器中的项目进行对齐、方向和顺序的布局。

Flex布局涉及到的主要属性有:

  1. 容器属性:这些属性设置在flex容器上。

    • flex-direction:定义主轴的方向(即项目的排列方向)。可能的值有 row(默认值,水平方向,从左到右)、row-reverse(水平方向,从右到左)、column(垂直方向,从上到下)和 column-reverse(垂直方向,从下到上)。

    • flex-wrap:定义如果一条轴线排不下,如何换行。可能的值有 nowrap(默认值,不换行)、wrap(换行,第一行在上方)和 wrap-reverse(换行,第一行在下方)。

    • flex-flow:是flex-directionflex-wrap的简写形式,默认值为 row nowrap

    • justify-content:定义项目在主轴上的对齐方式。可能的值有 flex-start(默认值,左对齐)、flex-end(右对齐)、center(居中)、space-between(两端对齐,项目之间的间隔都相等)和 space-around(每个项目两侧的间隔相等)。

    • align-items:定义项目在交叉轴上如何对齐。可能的值有 flex-start(交叉轴的起点对齐)、flex-end(交叉轴的终点对齐)、center(交叉轴的中点对齐)、baseline(项目的第一行文字的基线对齐)和 stretch(默认值,如果项目未设置高度或设为auto,将占满整个容器的高度)。

    • align-content:定义多根轴线的对齐方式。可能的值与align-items类似。

  2. 项目属性:这些属性设置在flex项目上。

    • order:定义项目的排列顺序。数值越小,排列越靠前,默认为0。

    • flex-grow:定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。

    • flex-shrink:定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。

    • flex-basis:定义了在分配多余空间之前,项目占据的主轴空间。默认值为auto,即项目的本来大小。

    • flex:是flex-grow, flex-shrinkflex-basis的简写,默认值为0 1 auto。后两个属性可选。

    • align-self:允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。可能的值与align-items一致。

css选择器 优先级

CSS选择器的优先级是由选择器的各个部分来决定的。以下是从高到低的优先级顺序:

  1. 内联样式:在HTML元素内部使用"style"属性定义的样式。例如:<div style="color: red;">

  2. ID选择器:例如:#example

  3. 类选择器、属性选择器和伪类:例如:.example[type="text"]:hover

  4. 元素选择器和伪元素:例如:div::before

  5. 通配符选择器(*)、关系选择器(+, ~, >, ’ ', ||)和否定伪类(:not()):这些选择器对优先级没有影响。

  6. 继承的样式:优先级最低。

注意:如果优先级相同,那么最后定义的样式会覆盖先前定义的样式。此外,无论任何规则的优先级如何,带有!important的样式总是最优先的。

在计算优先级时,我们可以将各种类型的选择器看作是一个“千位”系统:

  • 内联样式的优先级可以看作是1000。
  • ID选择器的优先级可以看作是100。
  • 类选择器、属性选择器和伪类的优先级可以看作是10。
  • 元素选择器和伪元素的优先级可以看作是1。

例如,对于选择器#id div.example,它的优先级就是 111(1个ID选择器,1个类选择器,1个元素选择器)。

display: none和 visibility: hidden的区别 ?

display: nonevisibility: hidden 都可以用来隐藏HTML元素,但它们之间存在一些重要的区别:

  1. display: none:这个属性会将元素完全从文档流中移除,就像它从未存在过一样。这意味着它不会占用任何空间,也不会影响到其他元素的布局。此外,使用 display: none 的元素不会被屏幕阅读器读取,因此对于辅助技术来说,它们是不可访问的。

  2. visibility: hidden:这个属性只是使元素变得不可见,但它仍然存在于文档流中,并占用相应的空间。也就是说,它会影响到布局。另外,使用 visibility: hidden 的元素仍然可以被屏幕阅读器读取,所以它们对于辅助技术来说是可访问的。

总的来说,如果你想完全隐藏一个元素,并且不希望它占用任何空间,你应该使用 display: none。如果你只是想让元素变得不可见,但仍然占用空间,并且对屏幕阅读器可访问,你应该使用 visibility: hidden

说一下跨域怎么处理的 ?jsonp说一下原理

JSONP:JSONP是一种通过动态插入<script>标签来实现跨域请求的方法。由于<script>标签的src属性不受同源策略的限制,因此可以用来发送跨域请求。服务器会将数据嵌入到一个JavaScript函数调用中并返回,客户端在接收到数据后,可以立即执行这个函数。JSONP只支持GET请求。

说一下强缓存和协商缓存

强缓存和协商缓存是两种不同的HTTP缓存策略,用于控制浏览器如何从缓存中获取资源。

  1. 强缓存:强缓存不会向服务器发送请求,直接从缓存中读取资源。在HTTP头信息中,与强缓存相关的字段有Expires和Cache-Control。Expires是HTTP/1.0的产物,表示资源会在这个时间点后过期,需要再次请求。而Cache-Control是HTTP/1.1的产物,优先级高于Expires。这个字段的参数有public、private、no-cache、no-store、max-age、s-maxage等,常用的是max-age,表示资源会在多少秒后过期。

  2. 协商缓存:协商缓存是在强缓存失效后,浏览器与服务器通过某种机制来判断一个资源是否已经被修改,如果没有被修改,则直接从缓存中读取,如果已经被修改,则从服务器获取新的资源。主要的字段有Last-Modified/If-Modified-Since和Etag/If-None-Match。Last-Modified和If-Modified-Since是HTTP/1.0的头字段,表示资源的最后修改时间。Etag和If-None-Match是HTTP/1.1的头字段,其中Etag表示资源的唯一标识,如果资源有变化,Etag也会随之变化。

总的来说,强缓存优先级高于协商缓存,当执行强缓存策略时,如果资源在缓存有效期内,则直接使用缓存的资源;如果资源已经过期,那么就会使用协商缓存策略,通过某种算法确认资源是否有更新,如果没有更新,则继续使用缓存的资源,如果有更新,则从服务器获取新的资源。

url输入到浏览器发生了什么

当在浏览器中输入URL并按下回车键时,会发生以下一系列的过程:

  1. 浏览器查找域名的IP地址:这一步包括DNS预解析、DNS解析等步骤。首先,浏览器会查看缓存中是否有这个域名对应的IP地址,如果没有,就会向系统缓存要,系统缓存没有就向路由器缓存要,路由器缓存没有就向ISP DNS服务器要,最后如果ISP DNS服务器还没有就向根服务器要。

  2. 浏览器向服务器发起TCP连接:包括TCP三次握手,即浏览器向服务器发送连接请求,服务器确认并回应,然后浏览器再次回应。

  3. 发送HTTP请求:浏览器通过TCP连接向服务器发送HTTP请求,包括请求行、请求头和请求体。

  4. 服务器处理请求并返回HTTP报文:服务器接收到请求后,进行处理,然后返回一个HTTP响应给浏览器。

  5. 浏览器解析渲染页面:浏览器接收到服务器返回的HTTP响应后,会解析响应内容,然后根据HTML、CSS、JavaScript等文件渲染出页面。

  6. 连接结束:如果HTTP头信息中没有声明keep-alive,那么浏览器和服务器会断开连接,否则,它们会保持连接状态。

;