文章目录
- Vue常用的指令都有哪些
- v-bind和v-model的区别
- Vue2的生命周期有哪些
- Vue3的生命周期有哪些
- vue3中创建响应式变量的方法
- ref和reactive原理
- vuex有哪些方法
- vue-router生命周期钩子
- vue框架和原生JavaScript有什么区别
- 对于提升项目加载速度和运行效率是怎么做的
- webpack能做什么优化,具体的优化是什么
- webpack和vite的区别
- nodejs用来干什么,作用是什么
- Express模块可以做什么
- objext.defineproperty和proxy的原理和区别
- websocket的你是用来做什么,说说具体的做法
- websocket和http的区别
- 介绍下网页加载的过程
- flex布局的属性
- css选择器 优先级
- display: none和 visibility: hidden的区别 ?
- 说一下跨域怎么处理的 ?jsonp说一下原理
- 说一下强缓存和协商缓存
- url输入到浏览器发生了什么
更多相关内容可查看
以下面试内容皆为2024年各大网站的面经题目,答案均为自己或gpt整理,并会不断补充
Vue常用的指令都有哪些
Vue.js提供了一些内置的指令,可以在模板中使用,以下是一些常用的Vue指令:
-
v-bind
:用于绑定元素属性和数据对象的属性。例如:v-bind:class
,v-bind:style
。 -
v-model
:用于在表单控件或者组件上创建双向数据绑定。 -
v-show
:根据表达式之真假值,切换元素的显示/隐藏状态。 -
v-if
、v-else
、v-else-if
:用于条件渲染,根据表达式的值的真假来决定是否渲染元素。 -
v-for
:用于渲染列表,基于源数据多次渲染元素或模板块。 -
v-on
:用于监听DOM事件,可以用来触发方法。例如:v-on:click
。 -
v-text
:更新元素的textContent
。 -
v-html
:更新元素的innerHTML
。 -
v-pre
:跳过这个元素和它的子元素的编译过程。 -
v-cloak
:这个指令保持在元素上直到关联实例结束编译。 -
v-once
:只渲染元素和组件一次。
这些指令可以帮助你创建动态和响应式的Web应用。
v-bind和v-model的区别
v-bind
和 v-model
都是 Vue.js 中的指令,用于创建数据和 DOM 元素之间的绑定。但是,它们之间有一些重要的区别:
-
v-bind
:这个指令用于单向数据绑定,它将数据从 Vue 实例绑定到 DOM 元素。当 Vue 实例中的数据变化时,这些变化会自动反映到 DOM 元素上。但是,如果用户在浏览器中更改了 DOM 元素(例如,通过输入框输入文本),这些更改不会反映回 Vue 实例。v-bind
可以用于任何类型的 HTML 属性,如class
,style
,src
等。 -
v-model
:这个指令用于实现双向数据绑定,主要用于表单元素。它不仅将数据从 Vue 实例绑定到 DOM 元素,而且还将数据从 DOM 元素绑定回 Vue 实例。这意味着,如果用户在浏览器中更改了 DOM 元素(例如,通过输入框输入文本),这些更改会自动反映回 Vue 实例。v-model
只能用于表单元素。
总的来说,v-bind
用于单向数据绑定,而 v-model
用于双向数据绑定。
Vue2的生命周期有哪些
Vue实例从创建到销毁的过程,就是生命周期。从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,我们称之为Vue的生命周期。具体可以分为以下几个阶段:
-
beforeCreate
:在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。 -
created
:在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。 -
beforeMount
:在挂载开始之前被调用:相关的 render 函数首次被调用。 -
mounted
:el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el
也在文档内。 -
beforeUpdate
:数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。 -
updated
:由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。 -
beforeDestroy
:实例销毁之前调用。在这一步,实例仍然完全可用。 -
destroyed
:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
这些生命周期钩子提供了在不同阶段添加自己的代码的机会。
Vue3的生命周期有哪些
在 Vue 3 中,由于引入了 Composition API,生命周期钩子的名称有所改变,以适应新的 API。以下是 Vue 3 的生命周期钩子:
-
beforeCreate
和created
在 Vue 3 中被替换为setup
。 -
beforeMount
:在挂载开始之前被调用,对应 Vue 2 中的beforeMount
。在 Vue 3 中,使用onBeforeMount
。 -
mounted
:在挂载完成后被调用,对应 Vue 2 中的mounted
。在 Vue 3 中,使用onMounted
。 -
beforeUpdate
:在数据更新之前被调用,对应 Vue 2 中的beforeUpdate
。在 Vue 3 中,使用onBeforeUpdate
。 -
updated
:在数据更新后被调用,对应 Vue 2 中的updated
。在 Vue 3 中,使用onUpdated
。 -
beforeUnmount
:在卸载组件之前被调用,对应 Vue 2 中的beforeDestroy
。在 Vue 3 中,使用onBeforeUnmount
。 -
unmounted
:在卸载组件后被调用,对应 Vue 2 中的destroyed
。在 Vue 3 中,使用onUnmounted
。 -
activated
和deactivated
:这两个钩子函数主要用在 keep-alive 组件中,当组件被激活和停用时分别调用。 -
errorCaptured
:当捕获一个来自子孙组件的错误时被调用。 -
renderTracked
和renderTriggered
:这两个新的调试钩子函数在追踪和触发组件的重新渲染时被调用。
以上就是 Vue 3 中的生命周期钩子。
vue3中创建响应式变量的方法
在 Vue 3 中,创建响应式变量的主要方法是使用 ref
和 reactive
。
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>
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>
需要注意的是,ref
和 reactive
创建的响应式变量或对象,只有在 setup
函数中返回后,才能在模板中使用。
ref和reactive原理
Vue 3 使用了 Proxy 对象来实现响应式系统,这是一个 ES6 的新特性。Proxy 可以拦截对象的各种操作,包括属性读取、属性设置、属性删除等,这使得 Vue 3 的响应式系统能够更好地跟踪和响应状态的变化。
ref
:ref
函数会创建一个包含.value
属性的对象,并且这个对象是响应式的。当我们获取.value
属性时,ref
会使用 Proxy 的get
拦截器来跟踪这个依赖;当我们设置.value
属性时,ref
会使用 Proxy 的set
拦截器来触发更新。
function ref(value) {
return reactive({ value });
}
reactive
:reactive
函数会创建一个新的 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 主要包含以下几个部分:
-
State:Vuex 使用单一状态树,用一个对象就包含了全部的应用层级状态。每个应用将仅仅包含一个 store 实例。
-
Getters:有时候我们需要从 store 中的 state 中派生出一些状态,例如对列表进行过滤并计数。Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。
-
Mutations:更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件,每个 mutation 都有一个字符串的事件类型 (type) 和一个回调函数 (handler)。
-
Actions:Action 类似于 mutation,不同在于,Action 提交的是 mutation,而不是直接变更状态。Action 可以包含任意异步操作。
-
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 提供的导航守卫:
-
全局前置守卫:
router.beforeEach
,这是最常用的导航守卫,它会在路由发生变化之前被调用:const router = new VueRouter({ ... }) router.beforeEach((to, from, next) => { // 在这里进行一些操作,例如检查用户是否已登录 if (to.path === '/login' || isLoggedIn()) { next() } else { next('/login') } })
-
全局解析守卫:
router.beforeResolve
,这个守卫会在路由被确认之前,但是在组件被解析之后被调用:router.beforeResolve((to, from, next) => { // 在这里进行一些操作 next() })
-
全局后置钩子:
router.afterEach
,这个钩子没有next
函数,也不能改变导航:router.afterEach((to, from) => { // 在这里进行一些操作,例如更新页面标题 document.title = to.meta.title })
-
路由独享的守卫:在路由配置上直接定义
beforeEnter
:const router = new VueRouter({ routes: [ { path: '/foo', component: Foo, beforeEnter: (to, from, next) => { // 在这里进行一些操作 next() } } ] })
-
组件内的守卫:在路由组件内部直接定义以下三个方法:
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的一些主要区别:
-
数据绑定:Vue.js提供了数据绑定功能,可以让开发者在JavaScript和HTML之间建立数据绑定,当数据发生变化时,视图会自动更新。而在原生JavaScript中,开发者需要手动操作DOM来更新视图。
-
组件化:Vue.js支持组件化开发,开发者可以创建可复用的组件,这可以提高代码的可维护性和可读性。而在原生JavaScript中,开发者需要手动管理代码的结构和复用性。
-
指令:Vue.js提供了一些内置的指令,如v-if、v-for、v-bind等,这些指令可以让开发者更方便地操作DOM。而在原生JavaScript中,开发者需要手动编写这些操作。
-
生命周期钩子:Vue.js提供了生命周期钩子函数,开发者可以在特定的时间点执行特定的操作。而在原生JavaScript中,开发者需要自己管理这些操作的执行时机。
-
虚拟DOM:Vue.js使用虚拟DOM来提高性能,只有当数据发生变化时,才会更新对应的DOM元素。而在原生JavaScript中,任何对DOM的操作都会立即反映在视图上,这可能会导致性能问题。
-
工具和插件:Vue.js有许多相关的工具和插件,如Vue Router、Vuex等,这些工具和插件可以帮助开发者更方便地开发复杂的应用。而在原生JavaScript中,开发者需要自己寻找或者开发这些工具和插件。
总的来说,Vue.js和原生JavaScript的主要区别在于,Vue.js提供了许多高级功能和工具,可以帮助开发者更方便、更高效地开发复杂的应用。而原生JavaScript更灵活,但是需要开发者自己管理更多的细节。
对于提升项目加载速度和运行效率是怎么做的
提升项目加载速度和运行效率是前端开发中的重要任务。以下是一些常见的优化策略和方法:
-
代码压缩和合并:通过工具如UglifyJS和webpack等,可以压缩JavaScript和CSS代码,去除空格、注释、缩短变量名等,减小文件大小。合并多个文件为一个,减少HTTP请求次数。
-
使用CDN:使用内容分发网络(CDN)可以将静态资源分布到全球的各个数据中心,用户可以从最近的服务器获取资源,减少延迟。
-
图片优化:对图片进行压缩,减小文件大小。使用CSS Sprite技术,将多个小图标合并为一张大图,减少HTTP请求次数。对于大图片,可以考虑使用懒加载技术。
-
使用缓存:利用浏览器缓存机制,对静态资源进行缓存,减少重复的HTTP请求。对于动态内容,可以考虑使用应用级别的缓存,如Redis。
-
代码分割和异步加载:通过webpack等工具,可以将代码分割为多个小的模块,按需异步加载,减少首屏加载时间。
-
优化CSS:将关键CSS(渲染首屏需要的CSS)内联在HTML中,减少阻塞渲染的时间。避免使用耗性能的CSS属性,如高级选择器、box-shadow等。
-
使用SSR或预渲染:对于首屏渲染性能要求高的应用,可以考虑使用服务器端渲染(SSR)或预渲染技术。
-
优化JavaScript执行:避免使用耗性能的JavaScript操作,如大量的DOM操作、大数据的计算等。对于复杂的操作,可以考虑使用Web Worker在后台线程中执行。
-
使用PWA技术:通过Service Worker和Cache API,可以实现离线缓存和网络优先的策略,提高加载速度。
-
Tree Shaking:利用Tree Shaking技术,去除没有使用的代码,减小打包后的文件大小。
以上是一些常见的优化策略和方法,具体使用哪种方法,需要根据项目的具体情况来决定。
webpack能做什么优化,具体的优化是什么
Webpack是一个强大的模块打包工具,它可以对项目进行许多优化。以下是一些常见的Webpack优化策略:
-
代码压缩:Webpack内置了UglifyJS插件,可以自动压缩生成的JavaScript代码。对于CSS和HTML,也有相应的插件如cssnano和html-minifier。
-
代码分割:Webpack支持代码分割,可以将代码分割为多个小的模块,按需加载,减少首屏加载时间。
-
Tree Shaking:Webpack支持Tree Shaking,可以自动去除没有使用的代码,减小打包后的文件大小。
-
提取公共代码:Webpack可以将多个模块中的公共代码提取出来,生成一个公共的模块,减少代码的重复。
-
懒加载:Webpack支持懒加载,可以将不常用的功能进行懒加载,只有在需要的时候才加载,提高首屏加载速度。
-
模块热替换:Webpack的模块热替换功能可以在不刷新页面的情况下替换、添加或删除模块,提高开发效率。
-
使用Loader:Webpack的Loader机制可以处理各种类型的资源,如CSS、图片、字体等,并将它们转化为模块。
-
使用插件:Webpack有许多插件,可以完成各种各样的任务,如生成HTML文件、清理输出目录、自动刷新浏览器等。
-
优化解析速度:Webpack可以通过配置resolve.alias来缩短查找路径,提高解析速度。
-
Scope Hoisting:Webpack的Scope Hoisting可以减少函数声明的数量和内存占用,提高运行速度。
以上是Webpack的一些常见优化策略,具体使用哪种优化策略,需要根据项目的具体需求来决定。
webpack和vite的区别
Webpack和Vite都是前端构建工具,但它们在设计理念和使用方式上有一些区别:
-
开发环境下的模块热更新:Webpack在开发环境下,当一个文件发生变化时,会重新构建整个应用,然后通过HMR(Hot Module Replacement)更新改变的部分。这在大型项目中可能会导致重新构建的时间较长。而Vite则采用了一种不同的方式,它在开发环境下利用原生的ES Module进行模块加载,当一个文件发生变化时,只需要重新请求改变的文件,因此更新速度更快。
-
构建速度:Webpack使用JavaScript进行编译,而Vite则使用esbuild进行编译。esbuild是用Go语言编写的,编译速度比Webpack快很多。
-
配置:Webpack的配置相对复杂,有许多选项可以配置。而Vite的配置相对简单,更易于上手。
-
插件系统:Webpack有一个成熟的插件系统,有许多社区提供的插件可以使用。Vite也有插件系统,但相对来说还不如Webpack成熟。
-
兼容性:Webpack由于历史更久,对旧版浏览器的兼容性更好。而Vite主要针对现代浏览器,对旧版浏览器的兼容性不如Webpack。
-
开箱即用的特性:Vite内置了对Vue、React、Preact、lit-element等现代框架的支持,以及对TypeScript、CSS Modules、PostCSS等现代语言特性的支持,开箱即用。
总的来说,Webpack和Vite各有优势,选择哪个工具需要根据项目的具体需求来决定。
nodejs用来干什么,作用是什么
Node.js是一个基于Chrome V8引擎的JavaScript运行环境。它使得JavaScript可以脱离浏览器环境,在服务器端运行,从而使得JavaScript成为一种全栈开发语言。以下是Node.js的一些主要用途和作用:
-
构建Web服务器:Node.js可以用来构建高性能的Web服务器。由于其事件驱动和非阻塞I/O模型,Node.js非常适合处理高并发的请求。
-
后端API开发:Node.js可以用来开发RESTful API,提供数据给前端应用。它可以配合Express、Koa等Web框架进行开发。
-
实时应用:Node.js非常适合开发实时应用,如即时通讯、实时数据推送等。它可以配合Socket.IO等库进行开发。
-
全栈开发:Node.js可以配合前端框架如React、Vue等进行全栈开发,前后端都使用JavaScript,提高开发效率。
-
命令行工具:Node.js可以用来开发命令行工具,如脚手架工具、构建工具等。例如,Vue CLI、Webpack等就是用Node.js开发的。
-
服务器端渲染:Node.js可以配合React、Vue等前端框架进行服务器端渲染,提高首屏加载速度,优化SEO。
-
数据库操作:Node.js可以配合MongoDB、MySQL等数据库进行数据操作,进行增删改查等操作。
-
微服务架构:Node.js可以用来构建微服务架构,每个服务都是一个小的Node.js应用,通过API进行通信。
总的来说,Node.js是一个非常强大的工具,可以用来进行各种服务器端的开发。
Express模块可以做什么
Express是一个基于Node.js平台的极简、灵活的web应用开发框架,它提供一系列强大的特性来帮助创建各种Web和移动设备应用。
以下是Express模块的一些主要功能:
-
路由控制:Express提供了强大的路由API,可以方便地定义URL的路由规则,以及对应的处理函数。
-
中间件:Express的中间件机制可以方便地处理请求和响应,例如解析请求体、处理Cookie、记录日志、处理错误等。
-
模板引擎:Express支持多种模板引擎,如Pug、EJS等,可以方便地生成HTML。
-
静态文件服务:Express可以方便地提供静态文件服务,例如提供图片、CSS文件、JavaScript文件等。
-
错误处理:Express提供了错误处理机制,可以方便地捕获和处理错误。
-
API开发:Express常常用于开发RESTful API,提供数据给前端应用。
-
集成数据库:Express可以方便地集成数据库,例如MongoDB、MySQL等,进行数据的增删改查操作。
-
服务器端渲染:Express可以配合前端框架如React、Vue等进行服务器端渲染。
总的来说,Express是一个非常强大的Web应用开发框架,可以帮助你快速地构建Web应用。
objext.defineproperty和proxy的原理和区别
Object.defineProperty
和Proxy
都是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);
}
});
区别
-
拦截能力:
Proxy
的拦截能力更强,它可以拦截对象的所有操作,而Object.defineProperty
只能拦截单个属性的读取和写入操作。 -
适用对象:
Object.defineProperty
只能对现有的对象属性进行操作,如果属性不存在,需要先定义。而Proxy
则没有这个限制。 -
性能:由于
Proxy
可以拦截所有操作,所以在某些情况下,Proxy
的性能可能会比Object.defineProperty
差一些。 -
兼容性:
Proxy
是ES6的新特性,它的浏览器兼容性不如Object.defineProperty
。如果需要支持老版本的浏览器,可能需要使用Object.defineProperty
。
websocket的你是用来做什么,说说具体的做法
WebSocket是一种网络通信协议,它在单个TCP连接上提供全双工(双向)通信通道。WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
以下是WebSocket的一些主要用途:
-
实时通讯:例如聊天应用、多人在线游戏等需要实时交互的应用。
-
实时数据推送:例如股票交易信息、新闻更新、实时天气等需要实时更新的信息。
-
实时监控:例如系统监控、设备监控等需要实时反馈的场景。
以下是使用WebSocket的基本步骤:
-
创建WebSocket对象:在JavaScript中,可以使用
new WebSocket(url)
来创建一个WebSocket对象,其中url是WebSocket服务的URL。var socket = new WebSocket("ws://localhost:8080");
-
监听连接事件:可以监听
open
事件,当WebSocket连接成功时,该事件会被触发。socket.onopen = function(event) { console.log("WebSocket is open now."); };
-
发送数据:可以使用
send
方法来发送数据。socket.send("Hello WebSocket!");
-
接收数据:可以监听
message
事件,当收到服务器发送的数据时,该事件会被触发。socket.onmessage = function(event) { console.log("WebSocket message received: ", event.data); };
-
关闭连接:可以使用
close
方法来关闭WebSocket连接。socket.close();
-
监听关闭事件:可以监听
close
事件,当WebSocket连接关闭时,该事件会被触发。socket.onclose = function(event) { console.log("WebSocket is closed now."); };
注意:WebSocket是一种较新的技术,虽然大多数现代浏览器都支持,但是在一些老的浏览器中可能不支持。
websocket和http的区别
WebSocket和HTTP都是网络通信协议,但它们在设计上有一些重要的区别:
-
连接方式:HTTP是无状态的,每次请求都需要建立新的连接,请求完成后连接就会断开。而WebSocket则是持久连接,一旦建立连接,客户端和服务器就可以在任何时间点进行双向通信,直到连接被关闭。
-
数据传输方向:HTTP是单向的,客户端发送请求到服务器,服务器返回响应到客户端。而WebSocket是全双工的,客户端和服务器都可以主动发送数据。
-
数据传输效率:HTTP请求和响应都需要包含头部信息,而且每次请求都需要新的TCP连接,这会带来一定的开销。而WebSocket在建立连接后,数据传输只需要极少的头部信息,而且可以复用已有的TCP连接,所以数据传输效率更高。
-
实时性:由于WebSocket是全双工的,并且是持久连接,所以它可以更好地支持实时性要求高的应用,例如聊天应用、实时游戏等。而HTTP由于是请求/响应模式,实时性较差。
-
用途:HTTP是通用的数据传输协议,用于传输HTML、图片、JSON、XML等各种类型的资源。而WebSocket主要用于实时、交互性强的场景,例如实时通讯、实时数据推送等。
-
兼容性:HTTP协议几乎被所有的网络设备和服务器支持,而WebSocket是较新的技术,虽然现代浏览器都支持,但在一些老的浏览器或网络设备上可能不支持。
介绍下网页加载的过程
网页加载的过程可以分为以下几个步骤:
-
输入URL:用户在浏览器的地址栏中输入网页的URL。
-
DNS解析:浏览器会通过DNS(域名系统)将网页的域名解析为对应的IP地址。如果浏览器或操作系统已经缓存了这个域名的IP地址,则可以跳过这一步。
-
建立TCP连接:浏览器与服务器建立TCP连接,进行三次握手,确认连接已建立。
-
发送HTTP请求:浏览器向服务器发送HTTP请求,请求中包含了要访问的网页文件,如HTML文件。
-
服务器处理请求并返回HTTP响应:服务器处理浏览器的请求,然后返回一个HTTP响应,响应中包含了网页的HTML内容。
-
浏览器解析HTML:浏览器开始解析HTML文件,构建DOM树(文档对象模型)。在解析过程中,如果遇到CSS、JavaScript、图片等外部资源的链接,浏览器会再次发送HTTP请求获取这些资源。
-
构建CSSOM树:浏览器解析CSS文件,构建CSSOM树(CSS对象模型)。
-
执行JavaScript代码:如果HTML中包含JavaScript代码,浏览器会执行它。注意,JavaScript的执行可能会修改DOM树和CSSOM树。
-
渲染:浏览器根据DOM树和CSSOM树,计算出每个可见元素的布局和样式,然后绘制到屏幕上,这个过程称为渲染。
-
加载完成:当所有的CSS、JavaScript、图片等外部资源都加载完成,浏览器会触发
load
事件,表示网页加载完成。
以上是一个简化的网页加载过程,实际上在现代浏览器中,为了提高性能,很多步骤会并行进行。例如,浏览器在下载HTML的同时,就会开始解析和渲服务压力大,请稍后再试
flex布局的属性
Flex布局(Flexible Box)是CSS3引入的一种新的布局模式,设计目的是提供一种更加有效的方式来对容器中的项目进行对齐、方向和顺序的布局。
Flex布局涉及到的主要属性有:
-
容器属性:这些属性设置在flex容器上。
-
flex-direction
:定义主轴的方向(即项目的排列方向)。可能的值有row
(默认值,水平方向,从左到右)、row-reverse
(水平方向,从右到左)、column
(垂直方向,从上到下)和column-reverse
(垂直方向,从下到上)。 -
flex-wrap
:定义如果一条轴线排不下,如何换行。可能的值有nowrap
(默认值,不换行)、wrap
(换行,第一行在上方)和wrap-reverse
(换行,第一行在下方)。 -
flex-flow
:是flex-direction
和flex-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
类似。
-
-
项目属性:这些属性设置在flex项目上。
-
order
:定义项目的排列顺序。数值越小,排列越靠前,默认为0。 -
flex-grow
:定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。 -
flex-shrink
:定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。 -
flex-basis
:定义了在分配多余空间之前,项目占据的主轴空间。默认值为auto
,即项目的本来大小。 -
flex
:是flex-grow
,flex-shrink
和flex-basis
的简写,默认值为0 1 auto。后两个属性可选。 -
align-self
:允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items
属性。可能的值与align-items
一致。
-
css选择器 优先级
CSS选择器的优先级是由选择器的各个部分来决定的。以下是从高到低的优先级顺序:
-
内联样式:在HTML元素内部使用"style"属性定义的样式。例如:
<div style="color: red;">
。 -
ID选择器:例如:
#example
。 -
类选择器、属性选择器和伪类:例如:
.example
,[type="text"]
,:hover
。 -
元素选择器和伪元素:例如:
div
,::before
。 -
通配符选择器(*)、关系选择器(+, ~, >, ’ ', ||)和否定伪类(:not()):这些选择器对优先级没有影响。
-
继承的样式:优先级最低。
注意:如果优先级相同,那么最后定义的样式会覆盖先前定义的样式。此外,无论任何规则的优先级如何,带有!important的样式总是最优先的。
在计算优先级时,我们可以将各种类型的选择器看作是一个“千位”系统:
- 内联样式的优先级可以看作是1000。
- ID选择器的优先级可以看作是100。
- 类选择器、属性选择器和伪类的优先级可以看作是10。
- 元素选择器和伪元素的优先级可以看作是1。
例如,对于选择器#id div.example
,它的优先级就是 111(1个ID选择器,1个类选择器,1个元素选择器)。
display: none和 visibility: hidden的区别 ?
display: none
和 visibility: hidden
都可以用来隐藏HTML元素,但它们之间存在一些重要的区别:
-
display: none
:这个属性会将元素完全从文档流中移除,就像它从未存在过一样。这意味着它不会占用任何空间,也不会影响到其他元素的布局。此外,使用display: none
的元素不会被屏幕阅读器读取,因此对于辅助技术来说,它们是不可访问的。 -
visibility: hidden
:这个属性只是使元素变得不可见,但它仍然存在于文档流中,并占用相应的空间。也就是说,它会影响到布局。另外,使用visibility: hidden
的元素仍然可以被屏幕阅读器读取,所以它们对于辅助技术来说是可访问的。
总的来说,如果你想完全隐藏一个元素,并且不希望它占用任何空间,你应该使用 display: none
。如果你只是想让元素变得不可见,但仍然占用空间,并且对屏幕阅读器可访问,你应该使用 visibility: hidden
。
说一下跨域怎么处理的 ?jsonp说一下原理
JSONP:JSONP是一种通过动态插入<script>
标签来实现跨域请求的方法。由于<script>
标签的src属性不受同源策略的限制,因此可以用来发送跨域请求。服务器会将数据嵌入到一个JavaScript函数调用中并返回,客户端在接收到数据后,可以立即执行这个函数。JSONP只支持GET请求。
说一下强缓存和协商缓存
强缓存和协商缓存是两种不同的HTTP缓存策略,用于控制浏览器如何从缓存中获取资源。
-
强缓存:强缓存不会向服务器发送请求,直接从缓存中读取资源。在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,表示资源会在多少秒后过期。
-
协商缓存:协商缓存是在强缓存失效后,浏览器与服务器通过某种机制来判断一个资源是否已经被修改,如果没有被修改,则直接从缓存中读取,如果已经被修改,则从服务器获取新的资源。主要的字段有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并按下回车键时,会发生以下一系列的过程:
-
浏览器查找域名的IP地址:这一步包括DNS预解析、DNS解析等步骤。首先,浏览器会查看缓存中是否有这个域名对应的IP地址,如果没有,就会向系统缓存要,系统缓存没有就向路由器缓存要,路由器缓存没有就向ISP DNS服务器要,最后如果ISP DNS服务器还没有就向根服务器要。
-
浏览器向服务器发起TCP连接:包括TCP三次握手,即浏览器向服务器发送连接请求,服务器确认并回应,然后浏览器再次回应。
-
发送HTTP请求:浏览器通过TCP连接向服务器发送HTTP请求,包括请求行、请求头和请求体。
-
服务器处理请求并返回HTTP报文:服务器接收到请求后,进行处理,然后返回一个HTTP响应给浏览器。
-
浏览器解析渲染页面:浏览器接收到服务器返回的HTTP响应后,会解析响应内容,然后根据HTML、CSS、JavaScript等文件渲染出页面。
-
连接结束:如果HTTP头信息中没有声明keep-alive,那么浏览器和服务器会断开连接,否则,它们会保持连接状态。