前端面试题

前端方向

一.普通部分

1、css中的布局有哪几种,有哪些是常用的

常见的css布局方式有

(1)标准流布局:

最基本的布局方式,元素按照其在HTML文档中的顺序依次排列;主要依赖margin和padding等属性进行布局调整.

(2)浮动布局

通过设置元素的float属性来实现元素的左右浮动,常用于实现多栏布局,需要清除浮动,以避免对后续布局的影响.

(3)定位布局

使用position属性(如static,relative,absolute,fixed,sticky)来定位元素;

(4)弹性布局:

通过display:flex;或display:infine-flex来启用弹性布局

(5)Grid

CSS Grid布局是一种二维布局系统,用于通过创建行和列来构建网页布局。

通过display: grid;display: inline-grid;在容器上启用Grid布局。

(6)多列布局

多列布局允许将文本内容分成多列,类似于报纸或杂志的排版方式。

主要通过column-countcolumn-gap等属性来实现。

2、Bfc是什么

BFC是Web页面CSS渲染中的一个重要概念,它通过创建一个独立的布局环境来约束块级盒子的布局,并提供了一系列有用的特性和作用来帮助开发者更好地控制页面布局。

BFC在Web布局中有着广泛的应用,比如解决浮动元素引起的布局问题、防止margin重叠、实现两栏或三栏布局等。通过合理利用BFC的特性,可以更加灵活地控制页面布局,提高开发效率。

3、Html5的新特性

(1)语义化标签

新增了许多语义化标签如<article>,<nav>,<header>,<footer>等

(2)表单增强

为<inout>元素增加了多种新的输入类型,如datetimeemailnumberrangesearchtelurl等表单属性,进一步增强了表单的验证和用户体验;

新增了如placeholderrequiredpatternminmaxstep等表单属性

(3)HTML5提供了<video><audio>元素

(4)HTML5引入了<canvas><svg>两个标签,使得在网页上创建和展示矢量图形、位图图形以及动画变得更加容易。

(5)HTML5提供了Web存储API,包括localStoragesessionStorage。这两个API允许在浏览器中存储数据,并在不同页面和会话中保持数据一致性。

(6)后台处理

HTML5中的Web Workers允许在后台运行JavaScript代码,而不会阻塞页面的其他操作。

(7)地理位置定位

HTML5中的Geolocation API可以获取用户的地理位置信息(在用户允许的情况下)。

4.CSS3的新特性

1.选择器

属性选择器:允许选择具有特定属性的元素,attr=value

伪类选择器:为特定状态的元素添加样式,如:hover.:active.:visited

伪元素选择器:选择元素的特定部分,如:::before,::afte

多重选择器:使用逗号分隔来同时选择多个元素,如element1, element2

2.盒模型

Box-sizing:改变了默认的CSS盒模型,使得布局更加简单和直观。

3.边框和阴影

边框圆角:通过border-radius属性为元素的边框添加圆角,创建圆形、椭圆形或具有不同角度的矩形边框。

盒阴影:使用box-shadow属性为元素添加阴影效果,包括阴影的颜色、大小、模糊度和偏移量等。

4.背景

background-size允许您更改背景图像的大小;background-repeat使您能够更改背景图像的重复行为;background-position允许您在水平和垂直方向上移动背景图像;background-image允许多背景图像同时使用。

5. 文本效果

文本阴影text-shadow属性为文本添加阴影效果,提升文本的视觉效果。

文本溢出text-overflow属性处理溢出文本的显示方式,如使用省略号表示。

6. 布局

Flexbox:一种用于一维布局的CSS3新布局模型,通过定义容器和项目之间的关系,实现更简洁和可伸缩的布局方式。

Grid:一种用于二维布局的CSS3新布局模型,它允许将页面分割为行和列,控制项目在网格中的位置和大小,实现灵活的网格布局。

多列布局:通过column-countcolumn-width等属性,将文本内容分成多列显示,类似报纸或杂志的版面布局。

7. 动画和过渡

过渡:使用transition属性,在元素状态改变时平滑地过渡属性值,如颜色、大小、位置等。

动画:通过@keyframes规则创建复杂的动画效果,定义关键帧和过渡细节来控制动画的执行。

8. 其他新特性

颜色:CSS3增加了对透明度的支持,使用rgba()hsla()opacity来设置。CSS3还提供了新的颜色空间,如RGBA、HSL和HSLA。

@font-face:允许引入自定义字体文件,为网页提供更加丰富的字体选择。

媒体查询:允许根据设备的特性和屏幕尺寸来适应不同的样式和布局,创建响应式网页设计。

CSS变量:使用--*声明变量,并在CSS中使用var()函数引用这些变量,使得CSS代码更加灵活和可维护。

aspect-ratio:定义元素的宽高比,简化了视频、图片等元素宽高比的设置。

margin-inlinetext-underline-offset、**outline-offset**等逻辑属性:这些属性简化了布局和样式设置,提高了开发效率。

5、rem相关(px,vw等)

px(像素)是屏幕上的固定单位,它代表屏幕上的一个点。

rem(root em)是一个相对单位,它相对于根元素(即<html>元素)的字体大小。默认情况下,根元素的字体大小是16px(但这可能会因浏览器或用户设置而异)。

vw(viewport width)是一个视口单位,它表示视口宽度的百分比。

6、es6常用的新特性

1. 块级作用域变量声明(let/const)

  • let:用于声明块级作用域的局部变量,解决了var关键字带来的变量提升和重复声明问题。
  • const:用于声明一个只读的常量,一旦声明,其值就不能被重新赋值(但如果是对象或数组,可以修改其内部属性或元素)。

2. 箭头函数(Arrow Functions)

  • 箭头函数提供了一种更简洁的函数书写方式,并且不绑定自己的this,arguments,super,或new.target。这些函数表达式更适用于非方法函数,并且它们不能用作构造函数。

3. 模板字符串(Template Strings)

  • 模板字符串允许嵌入表达式,并且可以通过${}来包裹JavaScript表达式,从而进行字符串的拼接和处理,使得字符串的拼接更加简洁和灵活。

4. 解构赋值(Destructuring Assignment)

  • 解构赋值允许从数组或对象中提取数据,并将其赋值给声明的变量,从而简化了数据提取的过程。

5. 默认参数(Default Parameters)

  • 在函数定义时,可以为参数指定默认值,如果调用函数时没有提供这些参数,则使用默认值。

6. 剩余参数(Rest Parameters)

  • 剩余参数语法允许我们将一个不定数量的参数表示为一个数组,这在使用函数时非常有用,特别是当你不确定会有多少个参数传递给函数时。

7. 扩展运算符(Spread Operator)

  • 扩展运算符允许一个表达式在某处展开为多个元素(在函数调用时)或在多个地方展开为单独的项(在数组字面量或解构赋值时)。

8. 类(Classes)

  • ES6引入了基于原型的类,使得JavaScript的面向对象编程更加规范和易于理解。类提供了一种更清晰、更易于管理的方式来创建对象和处理继承。

9. 模块(Modules)

  • ES6引入了模块的概念,使得JavaScript代码可以更加模块化,便于组织和管理。通过import和export语句,可以方便地导入和导出模块中的变量、函数、类等。

10. Promise

  • Promise是异步编程的一种解决方案,它代表了一个最终可能完成或失败的操作及其结果值。通过使用Promise,可以更加优雅地处理异步操作,避免回调地狱的问题。

11. Symbol

  • Symbol是一种新的原始数据类型,表示独一无二的值。Symbol类型的值可以作为对象的属性名,从而避免属性名的冲突。

12. Set和Map

  • Set和Map是ES6中新增的两种集合类型,它们提供了更加强大和灵活的数据结构来存储和操作数据。Set用于存储任何类型的唯一值,而Map则用于存储键值对。

13. for...of循环

  • for...of循环提供了一种遍历可迭代对象(如数组、字符串、Map、Set等)的方式,使得遍历过程更加简洁和直观。

7、Map和set

Map 是一种键值对的集合,其中每个元素都是一个键值对。Map 中的键可以是任意类型(包括函数、对象或任何原始类型)

Set 类似于数组,但它仅存储唯一的值,即 Set 中的每个值都只能出现一次,且值是唯一的。Set 的值可以是任何类型,无论是原始值还是对象引用。

8.数组去重的方法

1.set

const arr = [1,2,3,4,4,5];
const newarr = [...new Set(arr)];
console.log(newarr);//[1,2,3,4,5]

2.map

const arr = [1,2,3,4,4,5];
const newarr = Array.from(new Map(array.map(item => [item,item])).value());
console.log(newarr);//[1,2,3,4,5]

3.fliter和indexOf()

const array = [1, 2, 2, 3, 4, 4, 5];  
const Array = array.filter((item, index) 
//查找item在array中首次出现的索引
=> {  
//检查indexOf返回的索引是否与当前元素的索引index相同
  return array.indexOf(item) === index;  
//如果相同,说明 item 在当前位置是首次出现,回调函数返回 true,item 被包含在结果数组中。
//如果不同,说明 item 在之前的某个位置已经出现过,回调函数返回 false,item 被排除在结果数组之外。
});  
console.log(Array); // [1, 2, 3, 4, 5]

9、缓存相关问题

10、Dom树的结构了解

定义:DOM树是指根据HTML、XML或XHTML文档的层次结构对文档进行组织和表示的一种树形结构。它将整个文档表示为一个由节点(nodes)组成的层次结构,每个节点都代表文档中的一个元素、属性、文本或注释。

根节点:DOM树的根节点是整个文档的表示节点,对于HTML文档来说,根节点通常是<html>元素。

  • document.getElementById(id):根据ID获取元素节点。
  • document.getElementsByTagName(name):根据标签名获取元素节点集合。
  • document.createElement(name):创建新的元素节点。
  • parentNode.appendChild(node):向子节点列表末尾添加一个节点。
  • parentNode.insertBefore(newNode, referenceNode):将newNode插入到parentNode的子节点列表中,位于referenceNode之前。
  • parentNode.removeChild(node):从子节点列表中移除一个节点。
  • element.innerHTML:设置或获取元素内部的HTML或XML标记。
  • element.style:设置或获取元素的样式信息。element.setAttribute(name, value)
  • element.getAttribute(name):设置或获取元素的属性值。

11、怎么实现前端数据的实时更新

12、Vue的生命周期、响应式、监听器

1. Vue生命周期

Vue实例从创建到销毁的过程,就是Vue的生命周期。在这个过程中,Vue提供了多个钩子函数(或称为生命周期钩子),允许我们在不同的阶段添加自己的代码。这些钩子主要包括:

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

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

beforeMount:在挂载开始之前被调用:相关的 render 函数首次被调用。该钩子在服务器端渲染期间不被调用。

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

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

updated:由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用这个钩子。当这个钩子被调用时,组件 DOM 已经更新,所以现在可以执行依赖于 DOM 的操作。

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

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

2. Vue的响应式系统

Vue的响应式系统基于ES5的Object.defineProperty(Vue 3.x中使用了Proxy),使得当Vue实例的data中的属性发生变化时,视图会自动更新。其基本原理如下:

Vue在初始化时会遍历data中的所有属性,并使用Object.defineProperty将它们转化为getter/setter。

当访问这些属性时,会触发getter,Vue会依赖收集(Dependency Collection),即收集依赖这个属性的Watcher(观察者)。

当属性被修改时,会触发setter,setter通知之前收集的Watcher,告诉它们属性值已经改变了。

Watcher会重新计算,并导致关联的DOM更新。

3. Vue的监听器

Vue提供了多种监听数据变化的方式:

计算属性(Computed Properties):基于它们的响应式依赖进行缓存。只有当相关响应式依赖发生改变时它们才会重新求值。

侦听器(Watchers):允许你执行异步操作或开销较大的操作,使用watch选项或vm.$watch方法。

事件监听:Vue实例在创建时,$on可以用来监听事件,$emit可以用来触发事件。这在组件间的通信中非常有用。

13、Vue各个生命周期可以干什么

1. beforeCreate

  • 阶段描述:在实例初始化之后,数据观测(data observer) 和事件配置(event/watcher setup) 之前被调用。
  • 可执行操作
    • 因为此时data和methods都未初始化,所以一般不做任何操作。
    • 可以添加一些在数据加载前的全局loading效果。

2. created

  • 阶段描述:在实例创建完成后被调用。此时可以访问到实例的数据,并进行初始化操作。
  • 可执行操作
    • 初始化数据。
    • 调用API获取数据(如异步请求)。
    • 访问和修改data中的属性。
    • 初始化事件监听。
    • 停止全局loading效果。

3. beforeMount

  • 阶段描述:在模板编译/挂载之前被调用。此时虚拟DOM已经创建完成,但尚未挂载到真实DOM上。
  • 可执行操作
    • 最后一次修改数据的机会,这些修改不会触发渲染过程。
    • 通常在这个阶段不需要进行太多操作,因为DOM尚未挂载。

4. mounted

  • 阶段描述:在实例挂载到DOM后被调用。此时可以访问到挂载的DOM元素。
  • 可执行操作
    • 访问和操作DOM元素。
    • 初始化DOM相关的库(如jQuery插件、图表库等)。
    • 使用vm.$nextTick来确保所有的子组件都已经被渲染完成。

5. beforeUpdate

  • 阶段描述:在数据更新之前,DOM 重新渲染之前被调用。
  • 可执行操作
    • 在数据更新前访问现有的DOM,比如手动移除已添加的事件监听器。
    • 避免在这个阶段进行DOM操作,因为即将被更新。

6. updated

  • 阶段描述:在数据更新之后,DOM 重新渲染之后被调用。
  • 可执行操作
    • 访问和修改更新后的DOM。
    • 需要注意的是,updated不会保证所有的子组件也都被重新渲染完毕,如果需要等待整个视图都渲染完毕,可以在updated里使用vm.$nextTick

7. beforeDestroy

  • 阶段描述:在实例销毁之前被调用。
  • 可执行操作
    • 进行清理工作,如清除定时器、解绑事件监听器等。
    • 调用实例上的方法或访问实例的data等。

8. destroyed

  • 阶段描述:在实例销毁后被调用。此时实例上的所有指令和事件监听器都会被移除。
  • 可执行操作
    • 进行最后的清理工作,虽然在这个阶段实例已经不可用了,但可以用于日志记录等。

14、Vue2和vue3的区别在哪里

1. 区别

        (1)双向数据绑定原理不同,vue2利用了ES5的API Object.defineProperty(),vue3利用ES6的API Proxy

 详细:vue2利用Object.defineProperty()对数据进行劫持,并且结合发布订阅模式来实现,vue3利用了Proxy对数据代理

 优点:Object.defineProperty()只能监听某个属性,不能对全对象进行监听

    可以省去for in,闭包等内容来提升效率(直接绑定整个对象即可)

    可以监听数组,不用再去对数组进行特异性操作,vue3可以检测到数组内部数据的变化

         (2)vue3支持碎片,vue2不支持

    详细:vue3组件可以有多个根节点,vue2只能有一个

  (3)vue3使用合成型API(Composition API),vue2使用的是选项型API(Options API)

    详细:vue2的选项型API在代码里分割了不同的属性(data,computed,methods等),vue3的合成型API能让我们用方法(function)来分割,相比于vue2的使用属性来分组,vue3代码会更加简便和整洁

  (4)建立数据,vue3使用setup()方法,vue2直接把数据放在data属性中

    详细:vue2中数据直接放在data里,vue3中我们用setup()方法,此方法在组件初始化构造的时候触发,

      vue3建立反应性数据的步骤:

      1)从vue3中引入reactive

      2)使用reactive()方法来声明我们的数据为响应性数据

      3)使用setup方法来返回我们的响应性数据

  (5)生命周期勾子

vue2,vue3生命周期勾子对比

vue2                        vue3                    说明
beforeCreate          ->    setup()                 组件创建之前执行的函数
created               ->    setup()                 组件创建完成执行的函数
beforeMount           ->    onBeforeMount           组件挂载到节点上之前执行的函数
mounted               ->    onMounted               组件挂载完成后执行的函数
beforeUpdate          ->    onBeforeUpdate          组件更新之前执行的函数
updated               ->    onUpdated               组件更新完成之后执行的函数
beforeDestroy         ->    onBeforeUnmount         组件卸载之前执行的函数
destroyed             ->    onUnmounted             组件卸载完成后执行的函数
----------------<keep-alive>独有的两个勾子-------------------
activated             ->    onActivated             组件被激活时执行的函数
deactivated           ->    onDeactivated           组件离开时执行的函数       

(6)父子传参不同,setup()函数特性

    详细:

      1)setup()函数,接收两个参数(props, context(包含 attrs, slots, emit))

      2)setup函数是处在 befortCreate和created两个勾子之前的函数,执行 setup() 时,组件尚未被创建,所以this并不是指向vue,Vue为了避免错误的使用,直接将setup函数内部的this改成了undefined

      3)vue3.2之前,在setup() 函数中定义的 变量和方法最后都是需要return出去的,不然无法在模版中使用

      4)使用渲染函数:返回一个渲染函数,可以直接用在同一作用域中生命的响应式状态

    注意事项:

      1)setup() 中不能使用this

      2)setup() 中的 props 是响应式的,props更新时,因为是响应式的,所以不能用ES6去解构,因为会消除props的响应式,如果需要解构,需要使用vue 中的toRefs 来完成

      3)vue3传参

import { toRefs } from 'vue'

setup(props, { arrts, slots, emit }) {
  // 父传子 props,解构用 toRefs
  const { title } = toRefs(props)

  // 子传父 直接用setup第二个参数中包含的emit
  const login = () => {
    emit('login', {
      username: state.username,
      password: state.password
    })
  }
}

  4)setup() 中使用响应性数据的时候,需要通过 .value 使用数据,但是setup()返回的对象上的property返回在模版中使用的时候,将自动展开内部值,不需要在模版中追加.value

import { ref, toRefs } from 'vue'

setup(props, { arrts, slots, emit }) {
  const num = ref(0)
  console.log(num.value)
}

 5)setup() 只能同步不能异步

  (7)vue3有Teleport组件,vue2没有。

    详细:vue3有瞬移组件,也是一个独立组件,可以把你写的组件挂在到任何你想挂载的DOM上,所以也称为独立组件

      如果以之前vue2的方式引入,他跟普通的组件是一样的,但是父组件的DOM结构和css都可能对组件产生影响,为了解决这种问题,我们要用Teleport,像是一个传送门,把组件传送到任何地方。

    使用方法:

      1)在根目录下的index.html文件中添加一个id节点

<div id="model"></div>

                2)使用 to属性 挂在到DOM节点下面

<template to="#model"></template>

15、Vue组件之间的通信方式

1. Props & Events(父子组件通信)

  • Props:父组件通过属性(props)传递数据给子组件。这是单向数据流,子组件不能直接修改props中的值。
  • Events:子组件通过$emit触发事件,父组件监听这些事件并做出响应。这实现了子组件向父组件的通信。

2. refs和children

  • **refs∗∗:父组件可以使用‘refs访问子组件的实例,从而调用其方法或访问其属性。这需要在子组件上设置ref`属性。
  • **children∗∗:通过‘children可以访问当前实例的直接子组件。注意,$children`是一个包含所有子组件实例的数组,需要通过索引来访问特定的子组件。

3. Event Bus(兄弟组件或非直接父子组件通信)

当组件之间没有直接的父子关系时,可以使用全局事件总线(Event Bus)来进行通信。Event Bus是一个空的Vue实例,用于触发和监听事件。组件通过$emit触发事件,并通过$on监听事件。

4. Vuex

对于大型应用,组件间共享状态管理变得尤为重要。Vuex是一个专为Vue.js应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex通过statemutationsactionsgetters来管理应用的状态。

5. attrs和listeners

  • **attrs∗∗:包含了父作用域中不被认为(且不预期为)props的特性绑定(class和style除外),并且可以通过‘v−bind="attrs"`传入内部组件。这主要用于多层嵌套组件时,避免逐层手动传递props。
  • **listeners∗∗:包含了父作用域中的(不含.native修饰符)v−on事件监听器。它可以通过‘v−on="listeners"`传入内部组件,使得子组件可以继承父组件的事件监听器。

6. Provide / Inject

  • Provide 和 Inject 主要用于高阶插件/组件库的开发。它们允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起始组件和注入组件之间建立起一个响应式链接。

7. 插槽(Slots)

虽然插槽主要用于内容分发,但也可以看作是一种组件间的通信方式。通过插槽,父组件可以将自己的模板传递给子组件,实现更灵活的组件组合和复用。

16、Vue的内置组件有哪些

1. <component>

  • 用途:用于渲染一个“元组件”为动态组件。根据is属性的值来动态决定渲染哪个组件。
  • Props
    • is:String | Component,指定要渲染的组件名称或组件对象。
  • 用法示例
    <component :is="componentName"></component>

    2. <transition>

  • 用途:为单个元素或组件提供动画过渡效果。
  • Props
    • name:String,用于自动生成CSS过渡类名。
    • mode:String,控制离开/进入过渡的时间序列,如"out-in"或"in-out"。
    • 其他属性如durationappear等用于进一步控制过渡效果。
  • 用法示例
    <transition name="fade" mode="out-in">  
      <div v-if="show">Hello</div>  
    </transition>

    3. <transition-group>

  • 用途:为列表中的多个元素或组件提供过渡效果。它渲染一个真实的DOM元素(默认为<span>),并允许对列表中的每个元素应用过渡效果。
  • Props
    • tag:String,指定渲染的根元素类型。
    • move-class:覆盖移动过渡期间应用的CSS类。
    • 其他属性与<transition>相似。
  • 用法示例
    <transition-group tag="ul" name="list">  
      <li v-for="item in items" :key="item.id">{{ item.text }}</li>  
    </transition-group>

    4. <keep-alive>

  • 用途:用于缓存包裹在其中的动态切换组件,避免在组件切换时重新渲染和销毁,从而提高性能。
  • Props
    • include:字符串、正则表达式或数组,只有名称匹配的组件会被缓存。
    • exclude:字符串、正则表达式或数组,任何名称匹配的组件都不会被缓存。
    • max:数字,最多可以缓存多少组件实例。
  • 用法示例
    <keep-alive :include="['ComponentA', 'ComponentB']">  
      <component :is="currentView"></component>  
    </keep-alive>

    5. <slot>

  • 用途:作为组件模板中的内容分发插槽。<slot>元素自身将被替换。
  • Props
    • name:String,指定插槽的名称,用于具名插槽。
  • 用法示例
  • <!-- 子组件 -->  
    <template>  
      <div>  
        <slot name="header"></slot>  
        <p>Main content</p>  
        <slot name="footer"></slot>  
      </div>  
    </template>  
    
    <!-- 父组件 -->  
    <child-component>  
      <template v-slot:header>  
        <h1>Header</h1>  
      </template>  
      <template v-slot:footer>  
        <p>Footer</p>  
      </template>  
    </child-component>

6. <teleport>

  • 用途:允许将组件的HTML结构移动到DOM中的另一个位置。这在开发弹窗、模态框等需要改变渲染位置的组件时特别有用。
  • Props
    • to:String,指定要移动到的目标位置的选择器。
  • 用法示例
<teleport to="body">  
  <div class="modal">  
    <!-- 弹窗内容 -->  
  </div>  
</teleport>

7. <suspense>

二、Vuex的优势

  • 用途:用于处理异步组件的加载状态,在等待异步组件加载时渲染一些额外内容,提高用户体验。
  • 用法示例
    <suspense>  
      <template #default>  
        <AsyncComponent />  
      </template>  
      <template #fallback>  
        Loading...  
      </template>  
    </suspense>

    17.VUEX

  • 一、Vuex的基本概念

  • 状态管理:Vuex通过将应用的状态存储在一个单一的地方(store),使得所有组件都能访问和修改这个状态,从而简化了组件之间的数据共享和通信。
  • 核心概念:Vuex的store通常包含以下几个核心概念:
    • state:用于存储应用的状态数据,类似于全局变量。
    • getters:类似于组件的计算属性,用于从state中派生出一些状态。
    • mutations:唯一允许更新state的方法是提交mutation,它是同步函数。
    • actions:用于处理异步操作,通过提交mutation来更新state。
  • 集中式的状态管理:Vuex将应用的状态存储在一个单一的地方,使得状态管理变得更加集中和清晰。
  • 可预测的状态变化:Vuex使用了单向数据流的概念,使得状态的变化变得可预测和可追踪。
  • 插件化的扩展性:Vuex提供了丰富的插件机制,可以方便地扩展和定制。
  • 更好的开发体验:使用Vuex可以让代码更具可维护性和可测试性,同时提供了强大的工具和插件(如Vue Devtools)来帮助开发者更好地调试和分析应用。

三、Vuex的使用场景

Vuex特别适用于大型Vue应用,其中组件之间的数据共享和通信可能会变得复杂和困难。通过使用Vuex,开发者可以更容易地组织、管理和共享应用的状态,从而提高开发效率和应用的可维护性。

四、Vuex的缺点及解决方案

五、Vuex的使用步骤

  • 缺点:刷新浏览器时,Vuex中的state会重新变为初始状态。这是因为Vuex的状态是存储在内存中的,而不是持久化存储。
  • 解决方案
    • 使用插件如vuex-persistedstate来持久化存储Vuex的状态。
    • 在刷新前将Vuex中的数据保存到浏览器缓存(如localStorage或sessionStorage)中,并在页面刷新后重新加载这些数据。
  • 使用vue脚手架工具构建好项目。
  • 利用npm包管理工具安装Vuex。
  • 新建一个store文件夹,并在文件夹下新建“store.js”文件。
  • 在store.js文件中引入Vue和Vuex,并使用Vue.use(Vuex)来安装Vuex。
  • 创建一个Vuex.Store实例,并传入state、getters、mutations和actions等选项。
  • 在main.js中引入store,并在创建Vue实例时将其传入。

六、Vuex的实例代码

// store.js  
import Vue from 'vue';  
import Vuex from 'vuex';  
  
Vue.use(Vuex);  
  
export default new Vuex.Store({  
  state: {  
    count: 0  
  },  
  mutations: {  
    increment(state) {  
      state.count++;  
    },  
    decrement(state) {  
      state.count--;  
    }  
  },  
  actions: {  
    incrementIfOdd({ commit, state }) {  
      if ((state.count % 2) === 1) {  
        commit('increment');  
      }  
    },  
    incrementAsync({ commit }) {  
      setTimeout(() => {  
        commit('increment');  
      }, 1000);  
    }  
  }  
});  
  
// 在组件中使用  
<template>  
  <div>  
    <p>{{ count }}</p>  
    <button @click="increment">Increment</button>  
    <button @click="incrementIfOdd">Increment if odd</button>  
    <button @click="incrementAsync">Increment async</button>  
  </div>  
</template>  
  
<script>  
import { mapState, mapMutations, mapActions } from 'vuex';  
  
export default {  
  computed: {  
    ...mapState([  
      'count'  
    ])  
  },  
  methods: {  
    ...mapMutations([  
      'increment' // 将 `this.increment()` 映射为 `this.$store.commit('increment')`  
    ]),  
    ...mapActions([  
      'incrementIfOdd', // 将 `this.incrementIfOdd()` 映射为 `this.$store.dispatch('incrementIfOdd')`  
      'incrementAsync' // 将 `this.incrementAsync()` 映射为 `this.$store.dispatch('incrementAsync')`  
    ])

18、Js数值计算是有浮动的,怎么清除这个浮动

在JavaScript中,由于JavaScript使用IEEE 754标准表示数字(包括整数和浮点数),因此在执行数学运算时,特别是涉及浮点数时,可能会遇到精度问题,导致出现微小的误差,这通常被称为“浮点数问题”或“精度丢失”。这种精度问题是由于浮点数在计算机中的表示方式决定的,而非JavaScript特有的问题。

要“清除”或“处理”这种浮点数误差,有几种常用的方法:

1. 使用固定小数位

对于很多应用场景,尤其是金融或需要精确控制小数点后几位的应用,可以使用JavaScript的toFixed()方法将数字转换为字符串,并保留固定的小数位数。但是,请注意,这会返回一个字符串,而不是数字。

let num = 0.1 + 0.2;  
let result = num.toFixed(2); // "0.30",注意这是字符串

如果需要回到数字类型,可以进一步使用parseFloat()Number()进行转换,但这样可能会重新引入精度问题(如果小数位之后有非零值被截断)。

2. 四舍五入

对于不需要精确到特定小数位,但希望减少误差的情况,可以使用Math.round()方法四舍五入到最接近的整数,或者使用Math.round(num * 10) / 10这样的技巧来四舍五入到小数点后一位。

let num = 0.1 + 0.2;  
let rounded = Math.round(num * 100) / 100; // 0.3

3. 使用库来处理精度

对于需要高精度计算的场景,如金融应用,可以使用专门的库来处理数值,如decimal.jsbignumber.jsmath.js等。这些库提供了高精度的数值类型,并支持复杂的数学运算,从而避免了JavaScript原生数值类型的精度问题。

4. 精确比较

当需要比较两个浮点数是否相等时,由于精度问题,直接比较往往不是一个好的选择。一种常用的方法是比较两个数的差的绝对值是否小于一个很小的数(epsilon,通常是一个很小的正数,如1e-9)。

function areAlmostEqual(num1, num2, epsilon = 1e-9) {  
  return Math.abs(num1 - num2) < epsilon;  
}  
  
let num1 = 0.1 + 0.2;  
let num2 = 0.3;  
console.log(areAlmostEqual(num1, num2)); // true

19、深拷贝和浅拷贝的区别

import copy  
  
# 浅拷贝示例  
list1 = [1, 2, [3, 4]]  
list2 = copy.copy(list1)  
list2[2].append(5)  
print(list1)  # [1, 2, [3, 4, 5]]  
print(list2)  # [1, 2, [3, 4, 5]]  
  
# 深拷贝示例  
list1 = [1, 2, [3, 4]]  
list2 = copy.deepcopy(list1)  
list2[2].append(5)  
print(list1)  # [1, 2, [3, 4]]  
print(list2)  # [1, 2, [3, 4, 5]]

20.Mysql你了解吗,你会写接口吗

  1. 后端服务
    • 使用一种后端技术(如Node.js、Python Flask/Django、Java Spring Boot等)创建一个服务。
    • 在这个服务中,编写代码来连接MySQL数据库并执行SQL查询。
    • 创建一个或多个API端点(endpoints),这些端点接受HTTP请求,执行数据库操作,并返回JSON格式的响应。
  2. 前端Vue应用
    • 在Vue组件中,使用fetchaxios或其他HTTP客户端库来调用后端服务的API端点。
    • 处理API响应,并在Vue组件的模板中显示数据。

示例

后端(使用Node.js和Express)

const express = require('express');  
const mysql = require('mysql');  
const app = express();  
const port = 3000;  
  
// MySQL连接配置  
const connection = mysql.createConnection({  
  host: 'localhost',  
  user: 'yourUsername',  
  password: 'yourPassword',  
  database: 'yourDatabase'  
});  
  
connection.connect();  
  
// API端点  
app.get('/api/users', (req, res) => {  
  connection.query('SELECT * FROM users', (error, results, fields) => {  
    if (error) throw error;  
    res.json(results);  
  });  
});  
  
app.listen(port, () => {  
  console.log(`Server running on port ${port}`);  
});

前端Vue组件

<template>  
  <div>  
    <ul>  
      <li v-for="user in users" :key="user.id">{{ user.username }}</li>  
    </ul>  
  </div>  
</template>  
  
<script>  
import axios from 'axios';  
  
export default {  
  data() {  
    return {  
      users: []  
    };  
  },  
  created() {  
    this.fetchUsers();  
  },  
  methods: {  
    async fetchUsers() {  
      try {  
        const response = await axios.get('http://localhost:3000/api/users');  
        this.users = response.data;  
      } catch (error) {  
        console.error('There was an error!', error);  
      }  
    }  
  }  
};  
</script>

  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值