前端面试拼图-前端基础(二)

news2024/12/26 11:50:41

摘要:最近,看了下慕课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 又称计算属性,它提供给开发者根据依赖数据动态生成派生值的计算方式,同时确保计算结果的缓存和更新机制。[1]

import { ref, computed } from 'vue';
const count1 = ref(0);
const count2 = ref(1);
// 创建只读计算属性
const double = computed(() => count1.value * 2);

// 创建可写计算属性
const plusOne = computed({
  get: () => count2.value + 1,
  set: (val) => {
    count2.value = val - 1;
  }
});

// Vue 3的computed函数可以根据计算函数的返回值自动推导类型
console.log(double.value); // 计算属性的值; 推导得到的类型:ComputedRef<number>
plusOne.value = 1; // 设置计算属性的值
console.log(count2.value); // 0

        watch 又称侦听器,开发者可以使用它监视响应式数据的变化,并执行自定义的逻辑。常用语监听多个数据源变化、异步任务和副作用操作。

import { ref, watch } from 'vue';

const count1 = ref(0);
const count2 = ref(0);
const double = ref(0);

// 创建单个数据源的侦听器
watch(count1, (newVal, oldVal) => {
  console.log(`count1变化:新值 - ${newVal}, 旧值 - ${oldVal}`);
});
// 创建多个数据源的侦听器
watch([count2, double], ([newCount, newDouble], [oldCount, oldDouble]) => {
  console.log(`count2变化:新值 - ${newCount}, 旧值 - ${oldCount}`);
  console.log(`double变化:新值 - ${newDouble}, 旧值 - ${oldDouble}`);
});

        此外,Vue 3 还引入了即时执行的侦听器watchEffect ,它无需指定侦听器的数据源。简单比较下这三者。

自动收集依赖否返回值是否可以赋值立即执行本质
computed自动可以class
watch需指定依赖对象不可以看参数function
watcheffect自动不可以function

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' //主需要引用Level1
  export 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和getA
  props: ['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和getX
  props: ['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和getX
  props: ['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严格模式有什么特点

        JavaScript 的严格模式(Strict Mode)是一种在 ECMAScript 5 中引入的特性,它对 JavaScript 解析和执行时的行为做了一些限制和改变。使用严格模式可以帮助开发者写出更加安全、规范的 JavaScript 代码开启严格模式:

'use strict'  //全局开启

function fn() {
  'use strict' // 某个函数开启
}

特点:

        全局变量必须先声明

'use strict'
m = 10;   //Uncaught ReferenceError: m is not defined

        禁止使用with

'use strict'
const obj = {x:100, y:200}
with(obj) {
  console.log(x, y)    // Strict mode code may not include a with statement
}

        创建eval作用域(eval有自己单独的作用域, 不推荐使用)

'use strict'
var x = 10;
eval(`var x = 20; console.log('in eval', x);`)
console.log('out eval', x);

        禁止this指向window

'use strict'
function fn() {
  console.log('this', this)   // undefined
}
fn()

        函数参数不能重名

'use strict'
function fn(x,x,y) {  // Duplicate parameter name not allowed in this context
}
fn(10,10,20)

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

        跨域请求是由于浏览器存在同源策略;

        同源策略一般限制Ajax网络请求,不能跨域请求sever

        不会限制<link> <img><script><iframe>加载第三方资源

        JSONP

        执行原理:利用<script>标签不存在跨域限制,aaa跨域请求bbb的接口。首先,定义全局函数onSuccess, 并将src设置为bbb接口(需要接口配合),这样可以获取bbb接口返回的字符串,该字符串将被作为js执行,调用onSuccess获取接口返回的数据

<!--www.aaa.com-->
<script>
  window.onsuccess = function (date) {
    console.log(data)
  }
</script>
<script src = "https://www.bbb.com/api/getData"></script>


//https://www.bbb.com/api/getData返回了一段字符串:
'onSuccess({erroeno:0, data:{/*数据内容*/}})'

        CORS

// CORS配置允许跨域(服务端)
response.setHeader("Access-Control-Allow-Origin", "允许跨域请求的地址") // 或者'*'
resopnse.setHeader("Access-Control-Allow-Headers", "X-Request-With")
resopnse.setHeader("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS")
resopnse.setHeader("Access-Control-Allow-Credentials", "true")   //允许跨域接受Cookie

        Options请求(预检请求)的主要目的是为了实现跨域资源共享(CORS)机制的安全性和规范性;

        通过预检请求可以检查服务器是否支持跨域请求、验证请求的安全与否、处理复杂请求(如带有自定义头部,非简单请求方法PUT DELETE或者需要身份认证)、有助于防止跨站点请求伪造(CSRF)等安全问题。

        Options请求浏览器自行发起,无需干涉,也不会影响实际的功能。

[1] 解锁Vue 3的神秘力量:深入理解computed和watch: https://juejin.cn/post/7308563909560549391?searchId=20240228083853714901F13DB2C63CCF19

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CIP通讯介绍(欧姆龙PLC)

什么是CIP CIP通信是Common Industrial Protocl(CIP)的简称&#xff0c;它是一个点到点的面向对象协议&#xff0c;能够实现工业器件&#xff08;传感器&#xff0c;执行器&#xff09;之间的连接&#xff0c;和高等级的控制器之间的连接。目前&#xff0c;有3种网络DeviceNet…

图像剪辑|Linux|ImageMagick的初步使用--素描,毛玻璃等特效

前言&#xff1a; ImageMagick在图像剪辑领域的地位基本等同于FFmpeg&#xff0c;和FFmpeg基本一样&#xff0c;在Linux下使用此工具的原因是该工具可以使用shell脚本批量剪辑&#xff0c;在Windows下就会比较麻烦一些了 那么&#xff0c;本文主要是记录一下ImageMagick的一些…

【python】python用户管理系统[简易版](源码+报告)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

VScode 单步断点调试Nodejs方法总结

目录 方法一 方法二 方法三 方法一 使用vscode开发nodejs程序,能够启动单步调试模式,在指定代码处添加断点,像chrome、firefox浏览器上一样进行JavaScript的调试。 新建一个nodejs的工程,编写代码后,配置代码调试的步骤: 1、切换到代码调试界面 2、界面提示,新建一…

rust多个mod文件引用和文件夹mod使用注意事项

如果mod文件都在同一级目录&#xff0c;则直接使用就可以&#xff0c;因为rust文件都是一个隐藏的mod&#xff0c;但是如果mod文件在另外一个目录下面&#xff0c;就需要在目录下面声明一个mod.rs文件&#xff0c;这样才能将那个目录识别为一个mod&#xff0c;可以在mod.rs里面…

数据结构学习(三)链表

链表 1. 概念 反转链表 给出3个指针&#xff0c;一个cur&#xff0c;用于遍历链表中的每个节点&#xff0c;一个prev&#xff0c;用于保存cur指向的节点的上一个节点地址&#xff0c;还有一个after&#xff0c;用于保存cur指向的节点的下一个节点地址&#xff0c;链表操作遵循…

linux 交叉编译curl(+openssl)

一、交叉编译openssl 参考博客&#xff1a;点击跳转 二、交叉编译curl 1、源码下载 地址&#xff1a;点击跳转 2、配置 CPPFLAGS"-I/home/gui/gui/openssl/build_arm/include" LDFLAGS"-L/home/gui/gui/openssl/build_arm/lib" LIBS"-ldl" \ …

webpack基础配置及使用

webpack是什么 是一个现代 JavaScript 应用程序的静态模块打包器。当webpack 处理应用程序时&#xff0c;它会递归地构建一个依赖关系图 &#xff0c;其中包含应用程序需要的每个模块&#xff0c;然后将所有这些模块打包成一个或多个 bundle 。主要有 五个核心概念&#xff1a…

数据服务安全的重要性

数据服务安全在当今信息化社会显得尤为重要。随着大数据、云计算、人工智能等技术的飞速发展&#xff0c;数据已经成为企业和组织的核心资产&#xff0c;数据服务安全也面临着前所未有的挑战。本文将从数据服务安全的重要性、常见威胁、防护策略以及未来发展趋势等方面进行探讨…

【学位论文】上海交通大学 研究生学位论文 本地保存

上海交大研究生学位论文网&#xff1a;http://thesis.lib.sjtu.edu.cn/ &#xff08;只能校内访问或SJTU VPN访问&#xff09; 如果希望下载论文&#xff0c;需要参考&#xff1a;https://github.com/olixu/SJTU_Thesis_Crawler 安装过程 安装过程的几个坑&#xff1a; &a…

day04-Maven-SpringBootWeb入门

文章目录 01. Maven1.1 课程安排1.2 什么是Maven1.3 Maven的作用1.4 Maven模型1.5 Maven仓库1.6 Maven安装1.6.1 下载1.6.2 安装步骤 2 IDEA集成Maven2.1 配置Maven环境2.1.1 当前工程设置2.1.2 全局设置 2.2 创建Maven项目2.3 POM配置详解2.4 Maven坐标详解2.5 导入Maven项目 …

带使能控制的锂电池充放电解决方案

一、产品概述 TP4594R 是一款集成线性充电管理、同步升压转换、电池电量指示和多种保护功能的单芯片电源管理 SOC&#xff0c;为锂电池的充放电提供完整的单芯片电源解决方案。 TP4594R 内部集成了线性充电管理模块、同步升压放电管理模块、电量检测与 LED 指示模块、保护模块…

失败与坚持

失败 很多计划和目标由于个人能力等问题&#xff0c;都失败了。 如果将最近十年规划的目标算一个总评的话&#xff0c;接近97%的目标都没有实现。 这主要原因就是脱离了自身实际制定了一些超出自身能力所及的目标&#xff0c;当然也有一些客观因素。 坚持 有擅长做的事情&am…

Redis集群(主从)

1.主从集群 集群结构: 一.单机安装redis 1.上传压缩包并解压&#xff0c;编译 tar -xzf redis-6.2.4.tar.gz cd redis-6.2.4 make && make install 2.修改redis.config的配置并启动redis # 绑定地址&#xff0c;默认是127.0.0.1&#xff0c;会导致只能在本地访问。…

技术面没过,居然是因为没用过Pytest框架

01 概述 pytest是一个非常成熟的全功能的Python测试框架&#xff0c;主要特点有以下几点&#xff1a; 简单灵活&#xff0c;容易上手&#xff0c;文档丰富&#xff1b; 支持参数化&#xff0c;可以细粒度地控制要测试的测试用例&#xff1b; 能够支持简单的单元测试和复杂的…

什么是网络安全、信息安全、计算机安全,有何区别?

这三个概念都存在&#xff0c;一般人可能会混为一谈。 究竟它们之间是什么关系&#xff1f;并列&#xff1f;交叉&#xff1f; 可能从广义上来说它们都可以用来表示安全security这样一个笼统的概念。 但如果从狭义上理解&#xff0c;它们应该是有区别的&#xff0c;区别在哪呢&…

HFSS仿真双频微带天线学习笔记

HFSS仿真双频微带天线 文章目录 HFSS仿真双频微带天线1、 求解器设置2、 建模3、 激励方式设置4、 边界条件设置5、 扫频设置6、 设计检查&#xff0c;仿真分析7、 数据后处理 这里重点关注HFSS软件的操作&#xff0c;关于理论知识将在后面的文章中进行更新。 设计要求&#xf…

Golang pprof 分析程序的使用内存和执行时间

一、分析程序执行的内存情况 package mainimport ("os""runtime/pprof" )func main() {// ... 你的程序逻辑 ...// 将 HeapProfile 写入文件f, err : os.Create("heap.prof")if err ! nil {panic(err)}defer f.Close()pprof.WriteHeapProfile(f…

React 模态框的设计(四)状态管理

最近忙的不可开交&#xff0c;每天恨不得把时间掰开使用&#xff0c;挣不到钱还没时间&#xff0c;有时候我在想我怎么混得这个样子。题外话不多说&#xff0c;从这节课开始&#xff0c;我把这个模态框的教程写完整。请看效果&#xff1a; 这个模态框功能相对比较完整&#x…

桂院校园导航 静态项目 二次开发教程 2.0

Gitee代码仓库&#xff1a;桂院校园导航小程序 GitHub代码仓库&#xff1a;GLU-Campus-Guide 静态项目 2.0版本 升级日志 序号 板块 详情 1 首页 重做了首页&#xff0c;界面更加高效和美观 2 校园页 新增了 “校园指南” 功能&#xff0c;可以搜索和浏览校园生活指南…