前端基础面试题(二)

摘要:最近,看了下慕课2周刷完n道面试题,记录下...

1. offsetHeight scrollHeight clientHeight 区别

        计算规则:

        offsetHeight offsetWidth : border + padding + content

        clientHeight clientWidth: padding + content

        scrollHeight scrollWidth: padding + 实际内容尺寸(当显示滚动条时,就大于content尺寸)

2. HTMLCollection 和 NodeList区别

        Node 和Element

        DOM是一棵树,所有的节点都是Node

        Node是Element的基类

        Element是其他HTML元素的基类,如HTMLDivElement

        HTMLCollection是Element的集合;NodeList是Node的集合

        注:获取Node和Element的返回结果可能不一样

        如果elem.childNode和elem.children不一样

        前者包含Text和Comment等节点,后者不包含

        扩展:HTMLCollection和NodeLIst都是类数组,将类数组转换为数组的几种方式

const arr1 = Array.from(list)
const arr2 = Array.prototype.slice.call(list)
const arr3 = [...list]

3. Vue computed和watch的区别

        两者用途不同

        computed用于计算产生新的数据;watch用于监听现有数据;

        另外,computed有缓存,method没缓存

4. Vue组件通讯有几种方式,尽量全面

        Vue组件间通讯分为不同场景的:

  • 父子组件
  • 上下级组件(跨多级)通讯
  • 全局组件

        几种组件通讯方式:

props和Event

        父组件通过 props 向子组件传递数据,子组件通过 events 向父组件发送消息;

<!--Home.vue-->
<template><HelloWorld msg="Welcome to your Vue.js App" @showMsg="showMsg"/>
</template>
<script>import HelloWorld from '@/component/HelloWorld.vue'export defult {name: 'Home',components: {HelloWorld,},methods: {showMsg(msg) {console.log(msg)}}}
</script><!--HelloWorld.vue-->
<template><h1 @click="clickHandler"> {{msg}} </h1>
</template>
<script>export default {name: 'HelloWorld',props: {msg: String},emits: ['showMsg'],  // Vue3新增属性methods: {clickHandler() {this.$emit('showMsg', 'hello world')}}}
</script>

自定义事件

        Vue 实例可以通过 $on 方法监听自定义事件,通过 $emit 触发自定义事件,从而实现组件之间的通讯。自定定义事件常用于兄弟组件,跨多级通讯,灵活但容易用乱。

<!--ParentComponent.vue-->
<template><CustomEvent1/><CustomEvent2/>
</template>
<script>import CoustomEvent1 from '@/component/CoustomEvent1.vue'import CoustomEvent1 from '@/component/CoustomEvent2.vue'export defult {name: 'Home',components: {CustomEvent1,CustomEvent2},methods: {showMsg(msg) {console.log(msg)}}}
</script><!--CustomEvent1.vue 接收方-->
<template><p> recive coustom event</p>
</template>
<script>
import event from '../utils/event.js'  //引入event发布订阅的总线
export default {name: 'CustomEvent1',methods: {showMsg(msg) {console.log(msg)    }},mounted() {event.on('showMsg', this.showMsg)  // 监听},// vue 2.x beforeDestroy 需要销毁避免内存泄漏beforeUnmount() {event.off('showMsg', this.showMsg)  // 销毁;监听和销毁要写函数名字,处理同一个函数}
}
</script><!--CustomEvent2.vue 发送方-->
<template><p><button @click="trigger">trigger coustom event<button></p>
</template>
<script>
import event from '../utils/event.js'  //引入event发布订阅的总线
export default {name: 'CustomEvent2',methods: {trigger() {event.emit('showMsg', 'hello coustom event')}},
}
</script>//event.js
import ee from 'event-emitter'
// Vue2 : new Vue()就是 event
// Vue3 : 引入第三方库
const event = ee()export default event

$attrs

        之前资料$attrs 和 $listeners比较多,但是后者在Vue3中已经移除;子组件可以通过 $attrs 获取父组件传递的非 prop 和emits特性。

<!--ParentComponent.vue-->
<template><AttrsDome/>
</template>
<script>import AttrsDome from '@/component/AttrsAndListeners/Level1.vue' //主需要引用Level1export defult {name: 'Home',components: {AttrsDome,},methods: {showMsg(msg) {console.log(msg)}}}
</script><!--Level1-->
<template><p>Level1</p><Level2  :a="a" :b="b" :c="c" @getA="getA" @getB="getB" @getC="getC"></Level2>
</template>
<script>
import Level2 from './Level2'
export default {name: 'Level1'components: {Level2},date() {return {a: 'aaa',b: 'bbb',c: 'ccc'}},methods: {getA(){return this.a},getB(){return this.b},getC(){return this.c}}
}
</script><!--Level2-->
<template><p>Level2</p><Level3  :x="x" :y="y" :z="z" @getX="getx" @getY="gety" @getZ="getz"></Level3>v-bind="$attrs"  //将attrs传入下一级Level3,
</template>
<script>
import Level3 from './Level3'
export default {name: 'Level2'components: {Level3},// 只接受Level1传入的a和getAprops: ['a'],   // Vue2中属性在$attrs,方法在$listener中emits: ['getA']date() {return {x: 'xxx',y: 'yyy',z: 'zzz'}},methods: {getX(){return this.x},getY(){return this.y},getZ(){return this.z}},created() {console.log('level2', Object.keys(this.$attrs))  // ['b', 'c','onGetB', 'onGetC']// 也就是说,Level1传入的属性,没有被包含在props和$emits,就会放在attrs中;是前两者的后补}
}
</script><!--Level3-->
<template><p>Level3</p>
</template>
<script>
export default {name: 'Level3',// 只接受Levelx传入的a和getXprops: ['x'],emits: ['getX']inheritAttrs: false,// 避免属性继承date() {return {}},mounted() {console.log('Level3 $attrs', Object.keys(this.$attrs))//['y','z','onGetY','onGetZ']// Level2中增加v-bind传入attrs后,上面输出为['y','z','onGetY','onGetZ','b', 'c','onGetB', 'onGetC']}
}
</script>

$parent和 $refs

        Vue2中可以通过 $parent 和 children 直接访问父组件和子组件的实例,进行直接的组件通讯(父子组件通讯);Vue3中children建议用$refs来获取,可以使用 $refs 获取对子组件实例的引用,从而直接调用子组件的方法或访问子组件的数据。

        上例子中Level3,可以通过$parent直接获取父节点,获取属性调用方法都可以;

<!--Level3-->
<template><p>Level3</p><!--添加子组件HelloWorld的ref属性,为读取是的名称--><HelloWorld msg="hello czh" ref="hello1"/>
</template>
<script>
import HelloWorld from '../HelloWorld'export default {name: 'Level3',components: {HelloWorld},// 只接受Levelx传入的a和getXprops: ['x'],emits: ['getX']inheritAttrs: false,// 避免属性继承date() {return {}},mounted() {console.log(this.$parent)  //父节点console.log(this.$parent.y)   //yyy   ,获取属性console.log(this.$parent.getX())   //xxx   ,调用方法console.log(this.refs.hello1.name)  // hello-world}
}
</script><!--HelloWorld.vue-->
<template><h1 @click="clickHandler"> {{msg}} </h1>
</template>
<script>export default {name: 'HelloWorld',props: {msg: String},emits: ['showMsg'],  // Vue3新增属性data() {    // 新增data中的name属性return {name: 'hello-world'}},methods: {clickHandler() {this.$emit('showMsg', 'hello world')}}}
</script>

        需要注意$parent 和 $refs获取父组件和子组件,需要在mounted中获取,因为created中组件还未渲染完成。

provide/inject

        provide/inject是多层级组件间通讯较完美的解决方案,父组件通过 provide 向子孙组件注入数据,子孙组件通过 inject 接收注入的数据(可以跨级接收注入的数据)。

<!--Level1-->
<template><p>Level1 :<input v-model=name></p><Level2></Level2>
</template>
<script>
import {computed} from 'vue'  // 传入data中响应式的数据需要使用computed包裹
import Level2 from './Level2'
export default {name: 'Level1'components: {Level2},date() {return {name: 'czh'}},// provide: {    // 传入数据为静态字符串//   info: 'aaa'// },provide () {   //传入data中响应式的数据return {info: computed(() => this.name)  // 使用computed包裹}}
}
</script><!--Level2-->
<template><p>Level2  {{info}}</p>   <!--使用注入的数据info--><Level3></Level3>
</template>
<script>
import Level3 from './Level3'
export default {name: 'Level2'components: {Level3},inject: ['info'],   // 接收注入的数据
}
</script><!--Level3-->
<template><p>Level3 {{info}}</p>   <!--使用注入的数据info-->
</template>
<script>
export default {name: 'Level3',inject: ['info'],   // 接收注入的数据
}

Vuex

        使用 Vuex 来进行状态管理,实现组件之间共享状态和通信。

5. Vuex 中mutation和action的区别

        mutation:原子操作,必须是同步代码;action: 可包含多个mutation,可包含异步代码;

         具体来说:

        mutation:

  • mutation 是 Vuex 中用于修改状态的唯一途径;
  • mutation 必须是同步函数,用于直接改变状态;
  • 在组件中通过 commit 方法来触发 mutation;
  • 由于 mutation 是同步执行的,因此可以更容易地追踪状态的变化和调试。

        action:

  • action 类似于 Mutation,但是可以包含任意异步操作;
  • action 可以包含业务逻辑、异步请求等操作,并且最终提交 mutation 来修改状态;
  • 在组件中通过 dispatch 方法来触发 action;
  • action 可以处理复杂的逻辑,例如异步请求、多个 mutation 的组合等。

6. JS严格模式有什么特点

7. HTTP跨域时为何要发送option请求

未完待续……

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/495671.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

zk和etcd的读一致性对比

背景 zk和etcd都是日常我们用到的分布式一致性的组件集群&#xff0c;不过他们在读一致性上还是有一些差别的&#xff0c;本文就来对比一下 zk和etcd的读一致性对比 如果读客户端没有通过zk或者etcd自带的watcher监听的方式监听某个写客户端写入的内容&#xff0c;而是依赖写…

前端架构: 脚手架命令行交互核心实现之inquirer和readline的应用教程

命令行交互核心实现 核心目标&#xff1a;实现命令行行交互&#xff0c;如List命令行的交互呢比命令行的渲难度要更大&#xff0c;因为它涉及的技术点会会更多它涉及以下技术点 键盘输入的一个监听 (这里通过 readline来实现)计算命令行窗口的尺寸清屏光标的移动输出流的静默 …

详解Kotlin中run、with、let、also与apply的使用和区别

Kotlin作为一种现代、静态类型的编程语言&#xff0c;不仅提供了丰富的特性&#xff0c;还提供了极具表现力的函数&#xff1a;run, with, let, also, 和 apply。理解这些函数的不同之处对于编写高效、易于维护的代码至关重要。 函数对比表 函数对象引用返回值使用场景runthi…

Flutter(三):Stack、Positioned、屏幕相关尺寸、Navigator路由跳转

页面尺寸 通知栏高度&#xff1a;MediaQuery.of(context).padding.top顶部导航高度&#xff1a;kToolbarHeight底部导航高度&#xff1a;kBottomNavigationBarHeight屏幕宽&#xff1a;MediaQuery.of(context).size.width屏幕高&#xff1a;MediaQuery.of(context).size.height…

Rust调用同级目录中的rs文件和调用下级目录中的rs文件

一、Rust调用同级目录中的rs文件 Rust新建工程demo02&#xff0c;src文件夹下面新建test.rs文件&#xff0c;这样main.rs文件与它属于同级目录中。 关键点&#xff1a;导入test文件和test文件中的Ellipse模块 mod test;//导入test模块&#xff08;文件&#xff09; use test…

flutter 加密安全

前言&#xff1a;数据安全 数据的加密解密操作在 日常网络交互中经常会用到&#xff0c;现在密码的安全主要在于 秘钥的安全&#xff0c;如论 DES 3DES AES 还是 RSA, 秘钥的算法&#xff08;计算秘钥不固定&#xff09; 和 保存&#xff0c;都决定了你的数据安全&#xff1b;…

在CentOS上使用Docker搭建Halo博客并实现远程访问的详细指南

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;网络奇遇记、数据结构 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. Docker部署Halo1.1 检查Docker版本1.2 在Docker中部署Halo 二. Linux安装Cpol…

C++:list容器(非原生指针迭代器的实现)

本章是STL容器 list 的模拟实现。 之前已经使用 C语言 对带头双向循环链表 进行实现&#xff0c;详见数据结构: 线性表(带头双向循环链表实现), 相较于之前的实现&#xff0c;C 下多了对迭代器以及模板等相关语法特性。下面将着重讲解这些新知识。 文章目录 一. list 的基本框架…

【JavaEE】_前端POST请求使用json向后端传参

目录 1. 关于json 2. 通过Maven仓库&#xff0c;将Jackson下载导入到项目中 3. 使用Jackson 3.1 关于readValue方法 3.2 关于Request.class类对象 3.3 关于request对象的属性类型 3.4 关于writeValueAsString 前端向后端传递参数通常有三种方法&#xff1a; 第一种&…

学生成绩管理系统

用单链表数据结构完成c的学生成绩管理系统&#xff0c;此系统的具体功能如下&#xff1a; 本人小萌新一个&#xff0c;遇到BUG是正常现象。并且类与对象写的不太理想。- 写了一个Database存放所有数据&#xff0c;但这肯定浪费资源&#xff0c;你们看着改改吧。 class DataBase…

【主题广范|见刊快】2024年电力电气与机械,能源工程国际会议(ICPEMEE 2024)

【主题广范|见刊快】2024年电力电气与机械&#xff0c;能源工程国际会议&#xff08;ICPEMEE 2024&#xff09; 重要信息 会议官网&#xff1a;http://www.icpemee.com会议地址&#xff1a;合肥截稿日期&#xff1a;2024.03.10召开日期&#xff1a;2024.03.20 &#xff08;先投…

Linux下性能分析的可视化图表工具

1 sar 和sadf 1.1 简介 sar命令可以记录系统下的常见活动信息&#xff0c;例如CPU使用率、网络统计数据、Block I/O数据、内存使用情况 等。 sar命令的“-o [file_name]”参数可以将系统活动数据记录到file_name文件&#xff0c;然后通过sadf来解析&#xff0c;sadf命令的“-g…