【前端面经】云智慧一面

发布于:2025-06-03 ⋅ 阅读:(25) ⋅ 点赞:(0)

写在前面:面经只是记录博主遇到的题目。每题的答案在编写文档的时候已经有问过deepseek,它只是一种比较普世的答案,要学得深入还是靠自己

Q:手撕代码,两个有序数组排序
A:

function mysort(arr1, arr2) {
    let i = 0;
    let j = 0;
    let res = [];
    while (i < arr1.length && j < arr2.length) {
        if (arr1[i] <= arr2[j]) {
            res.push(arr1[i])
            i++
        } else {
            res.push(arr2[j])
            j++
        }
    }
    return [...res, ...arr1.slice(i), ...arr2.slice(j)];
}

Q:Vue里emit和on如何实现“发起然后更新”这样一个过程
A:

  • $emit: 用于触发/发起一个自定义事件
  • $on: 用于监听/订阅一个自定义事件

父子组件之间:子组件发起(emit),父组件监听(on)并更新

<!-- 子组件 Child.vue -->
<template>
  <button @click="sendMessage">发送消息</button>
</template>

<script>
export default {
  methods: {
    sendMessage() {
      // 发起/触发一个名为'message-sent'的事件,并附带数据
      this.$emit('message-sent', { text: 'Hello from child!' });
    }
  }
}
</script>
<!-- 父组件 Parent.vue -->
<template>
  <div>
    <child @message-sent="handleMessage"></child>
    <p>收到的消息: {{ receivedMessage }}</p>
  </div>
</template>

<script>
import Child from './Child.vue';

export default {
  components: { Child },
  data() {
    return {
      receivedMessage: ''
    };
  },
  methods: {
    // 监听/处理子组件发出的事件
    handleMessage(payload) {
      this.receivedMessage = payload.text; // 更新数据
      console.log('收到消息:', payload.text);
    }
  }
}
</script>

Q:一个平铺数组如何变成树
A:

const flatArray = [
    { id: 1, pid: 0, children: [{ id: 2, pid: 1, children: null }] },
    { id: 3, pid: 0, children: null }
];

function normalizeTree(node) {
    if (node.children === null) {
        node.children = [];
    } else if (Array.isArray(node.children)) {
        node.children.forEach(normalizeTree);
    }
    return node;
}

const tree = flatArray.map(normalizeTree);
console.log(tree);

Q:Nuxt.js有了解吗
A:一个基于Vue.js的SSR服务端渲染和静态站点生成的SSG框架,用于构建高性能、SEO友好的现代web应用,它简化了Vue.js的开发流程。
核心:多种渲染模式,服务端渲染,静态站点生成,单页应用,混合渲染。
无需手动vue-router,内置代码分割,预加载,支持HMR。
适合博客、电商、后台管理系统、全栈应用。

Q:代码分割是为了什么,在什么场景下用
A:

  • ESM代码分割:() => import(组件),实现动态引入。
  • WebPack代码分割:需要性能优化的场景下使用,减少包体积,给浏览器缓存,包分得多了,如果只改一部分js代码,就不需要整个js重新加载。
    WebPack分割配置:
// webpack.config.js
module.exports = {
    // ...
    optimization: {
        splitChunks: {
            chunks: 'all', // 对所有模块进行优化(包括同步和异步)
            minSize: 20000, // 生成 chunk 的最小体积(20KB)
            minRemainingSize: 0,
            minChunks: 1, // 被引用次数 >=1 才会被拆分
            maxAsyncRequests: 30, // 最大异步请求数(默认 30)
            maxInitialRequests: 30, // 入口点的最大并行请求数(默认 30)
            enforceSizeThreshold: 50000, // 强制拆分阈值(50KB)
            cacheGroups: {
                // 拆分第三方库(node_modules)
                vendors: {
                    test: /[\\/]node_modules[\\/]/,
                    priority: -10, // 优先级
                    reuseExistingChunk: true,
                    name: 'vendors', // 输出文件名(如 vendors.js)
                },
                // 拆分公共代码(被多个入口引用)
                common: {
                    minChunks: 2, // 至少被 2 个入口引用
                    priority: -20,
                    reuseExistingChunk: true,
                    name: 'common', // 输出文件名(如 common.js)
                },
            },
        },
    },
};

Q:v-model如何实现的
A:它实现了表单输入和应用状态之间的双向数据绑定。本质上是语法糖,结合了数据绑定和事件监听。

<custom-input v-model="message"></custom-input>
// 相当于是 v-bind + v-on 的语法糖
<custom-input 
  :value="message"  // 将 value 属性绑定到 Vue 实例的 message 数据
  @input="message = $event.target.value" // 监听 input 事件,当输入值变化时更新 message
></custom-input>

// 组件内部需要:
// 接收 value 这个prop
// 在值变化时触发 input 事件
Vue.component('custom-input', {
    props: ['value'],
    template: `
      <input
        :value="value"
        @input="$emit('input', $event.target.value)"
      >
    `
  })

底层实现机制:
模板编译:Vue 编译器将模板中的 v-model 转换为 v-bind:value 和 v-on:input
AST 转换:生成抽象语法树时处理 v-model 指令
数据绑定:通过 Object.defineProperty 或 Proxy 实现响应式
事件监听:建立事件监听器,在事件触发时更新数据


网站公告

今日签到

点亮在社区的每一天
去签到