易忘,但常问的面试题(七)

41、说说Js中的预解析?

JS 引擎在运行一份代码的时候,会按照下面的步骤进行工作:

1.把变量的声明提升到当前作用域的最前面,只会提升声明,不会提升赋值

2.把函数的声明提升到当前作用域的最前面,只会提升声明,不会提升调用

3.先提升 function,在提升 var

注意:let、const声明的变量不会提升,var声明的变量在赋值前使用为undefined

42、对闭包有什么解析?

官方说法:闭包就是指有权访问另一个函数作用域中的变量的函数。

浏览器在加载页面会把代码放在栈内存( ECStack )中执行,函数进栈执行会产生一个私有上下文( EC ),此上下文能保护里面的使用变量( AO )不受外界干扰,并且如果当前执行上下文中的某些内容,被上下文以外的内容占用,当前上下文不会出栈释放,这样可以保存里面的变量和变量值,所以我认为闭包是一种保存和保护内部私有变量的机制。

闭包的作用

  • 闭包的第一个用途是使我们在函数外部能够访问到函数内部的变量。通过使用闭包,可以通过在外部调用闭包函数,从而在外部访问到函数内部的变量,可以使用这种方法来创建私有变量
  • 闭包的另一个用途是使已经运行结束的函数上下文中的变量对象继续留在内存中,因为闭包函数保留了这个变量对象的引用,所以这个变量对象不会被回收。

43、说说你对slot的理解?slot使用场景有哪些

是Web组件内的一个占位符

js 复制代码
<template id="element-details-template">
  <slot name="element-name">Slot template</slot>
</template>
<element-details>
  <span slot="element-name">1</span>
</element-details>
<element-details>
  <span slot="element-name">2</span>
</element-details>

solt在组件模板中占好了位置,当使用该组件标签时候,组件标签里面的内容就会自动填坑(替换组件模板中slot位置),作为承载分发内容的出口

使用场景

通过插槽可以让用户可以拓展组件,去更好地复用组件和对其做定制化处理,通过slot插槽向组件内部指定位置传递内容,完成这个复用组件在不同场景的应用,比如布局组件、表格列、下拉选、弹框显示内容等。

44、为什么要使用异步组件

  1. 节省打包出的结果,异步组件分开打包,采用jsonp的方式进行加载,有效解决文件过大的问题。
  2. 核心就是包组件定义变成一个函数,依赖import() 语法,可以实现文件的分割加载。

45、怎么实现路由懒加载呢

js 复制代码
// 将
// import UserDetails from './views/UserDetails'
// 替换为
const UserDetails = () => import('./views/UserDetails')
​
const router = createRouter({
  // ...
  routes: [{ path: '/users/:id', component: UserDetails }],
})
  1. 当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。利用路由懒加载我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样会更加高效,是一种优化手段

  2. 一般来说,对所有的路由都使用动态导入是个好主意

  3. component选项配置一个返回 Promise 组件的函数就可以定义懒加载路由。

46、组件中写name属性的好处

可以标识组件的具体名称方便调试和查找对应属性

47、Vue组件为什么只能有一个根元素

  1. vue2中组件确实只能有一个根,但vue3中组件已经可以多根节点了。

  2. 之所以需要这样是因为vdom是一颗单根树形结构,patch方法在遍历的时候从根节点开始遍历,它要求只有一个根节点。组件也会转换为一个vdom

  3. vue3中之所以可以写多个根节点,是因为引入了Fragment的概念,这是一个抽象的节点,如果发现组件是多根的,就创建一个Fragment节点,把多个根节点作为它的children。将来patch的时候,如果发现是一个Fragment节点,则直接遍历children创建或更新。

48、双向绑定的原理是什么

我们都知道 Vue 是数据双向绑定的框架,双向绑定由三个重要部分构成

  • 数据层(Model):应用的数据及业务逻辑
  • 视图层(View):应用的展示效果,各类UI组件
  • 业务逻辑层(ViewModel):框架封装的核心,它负责将数据与视图关联起来

而上面的这个分层的架构方案,可以用一个专业术语进行称呼:MVVM这里的控制层的核心功能便是 "数据双向绑定" 。自然,我们只需弄懂它是什么,便可以进一步了解数据绑定的原理

理解ViewModel

它的主要职责就是:

  • 数据变化后更新视图
  • 视图变化后更新数据

当然,它还有两个主要部分组成

  • 监听器(Observer):对所有数据的属性进行监听
  • 解析器(Compiler):对每个元素节点的指令进行扫描跟解析,根据指令模板替换数据,以及绑定相应的更新函数

49、子组件可以直接改变父组件的数据吗?

子组件不可以直接改变父组件的数据。这样做主要是为了维护父子组件的单向数据流。

Vue提倡单向数据流,即父级 props 的更新会流向子组件,但是反过来则不行。这是为了防止意外的改变父组件状态,使得应用的数据流变得难以理解,导致数据流混乱。如果破坏了单向数据流,当应用复杂时,debug 的成本会非常高。

50、vue-router中如何保护路由

路由守卫有三个级别:全局路由独享组件级。影响范围由大到小。

全局守卫:

js 复制代码
const router = createRouter({ ... })
​
router.beforeEach((to, from) => {
  // ...
  // 返回 false 以取消导航
  return false
})

路由独享守卫:

js 复制代码
const routes = [
  {
    path: '/users/:id',
    component: UserDetails,
    beforeEnter: (to, from) => {
      // reject the navigation
      return false
    },
  },
]

组件内的守卫:

js 复制代码
const UserDetails = {
  template: `...`,
  beforeRouteEnter(to, from) {
    // 在渲染该组件的对应路由被验证前调用
  },
  beforeRouteUpdate(to, from) {
    // 在当前路由改变,但是该组件被复用时调用
  },
  beforeRouteLeave(to, from) {
    // 在导航离开渲染该组件的对应路由时调用
  },
}
  1. vue-router中保护路由的方法叫做路由守卫,主要用来通过跳转或取消的方式守卫导航。

  2. 路由守卫有三个级别:全局路由独享组件级。影响范围由大到小,例如全局的router.beforeEach(),可以注册一个全局前置守卫,每次路由导航都会经过这个守卫,因此在其内部可以加入控制逻辑决定用户是否可以导航到目标路由;在路由注册的时候可以加入单路由独享的守卫,例如beforeEnter,守卫只在进入路由时触发,因此只会影响这个路由,控制更精确;我们还可以为路由组件添加守卫配置,例如beforeRouteEnter,会在渲染该组件的对应路由被验证前调用,控制的范围更精确了。

  3. 用户的任何导航行为都会走navigate方法,内部有个guards队列按顺序执行用户注册的守卫钩子函数,如果没有通过验证逻辑则会取消原有的导航。

相关推荐
虾球xz4 分钟前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇10 分钟前
HTML常用表格与标签
前端·html
疯狂的沙粒13 分钟前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员29 分钟前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
野槐31 分钟前
前端图像处理(一)
前端
程序猿阿伟39 分钟前
《智能指针频繁创建销毁:程序性能的“隐形杀手”》
java·开发语言·前端
疯狂的沙粒40 分钟前
对 TypeScript 中函数如何更好的理解及使用?与 JavaScript 函数有哪些区别?
前端·javascript·typescript
瑞雨溪1 小时前
AJAX的基本使用
前端·javascript·ajax
力透键背1 小时前
display: none和visibility: hidden的区别
开发语言·前端·javascript
程楠楠&M1 小时前
node.js第三方Express 框架
前端·javascript·node.js·express