2025年01月03日美蜥(杭州普瑞兼职)一面

目录

  1. vue2 vue3 的区别
  2. react 性能优化
  3. react 组件传值
  4. v-for 和 v-if 的优先级
  5. react 中多个接口请求的数据,需要渲染到一个列表上怎么处理
  6. 百万条数据怎么渲染
  7. vue2、vue3 的响应式原理
  8. 微前端了解吗
  9. git 版本控制
  10. git mearge 和 git rebase 的区别
  11. 垂直水平居中
  12. react 中实现 KeepAlive
  13. 哈希路由和浏览器路由的区别
  14. 数组的常用方法
  15. 如何判断一个对象是空

1. vue2 vue3 的区别

Vue 2 和 Vue 3 在多个方面存在区别,以下从架构设计、语法与 API、性能、生态系统等方面进行详细介绍:

架构设计
  • 响应式系统
    • Vue 2:基于 Object.defineProperty() 实现响应式。这种方式有一定局限性,例如无法检测对象属性的添加和删除,对于数组,部分方法(如通过索引修改元素)也不能触发响应式更新。
    • Vue 3:采用 Proxy 对象实现响应式系统。Proxy 可以劫持整个对象,并能拦截更多操作,解决了 Vue 2 中响应式的一些限制,能更好地检测对象属性的变化,包括属性的添加、删除以及数组元素的修改等。
  • 代码组织
    • Vue 2:主要使用选项式 API(Options API),将不同的逻辑(如数据、方法、生命周期钩子等)分散在不同的选项中,在处理复杂组件时,可能会导致代码碎片化,逻辑分散难以维护。
    • Vue 3:引入了组合式 API(Composition API),允许开发者根据逻辑关注点来组织代码,将相关的逻辑封装在一起,提高了代码的复用性和可维护性,尤其适合大型项目。
语法与 API
  • 组件定义
    • Vue 2:使用 Vue.extend() 或单文件组件(SFC)来定义组件,通过 export default 导出一个包含各种选项的对象。
    • Vue 3:仍然支持单文件组件,但在组合式 API 中,可以使用
      • 生命周期钩子
        • Vue 2:有 beforeCreatecreatedbeforeMountmountedbeforeUpdateupdatedbeforeDestroydestroyed 等生命周期钩子。
        • Vue 3:部分钩子名称发生了变化,beforeDestroy 改为 beforeUnmountdestroyed 改为 unmounted,并且在组合式 API 中可以使用 onBeforeMountonMounted 等函数来注册生命周期钩子。
      // Vue 2 生命周期钩子
      export default {
        created() {
          console.log('Vue 2: Component created');
        }
      };
      
      // Vue 3 组合式 API 生命周期钩子
      import { onMounted } from 'vue';
      
      export default {
        setup() {
          onMounted(() => {
            console.log('Vue 3: Component mounted');
          });
        }
      };
      
      • 响应式数据定义
        • Vue 2:在 data 选项中定义响应式数据,使用 this 来访问。
        • Vue 3:使用 ref()reactive() 函数来创建响应式数据。ref() 用于创建单个值的响应式数据,reactive() 用于创建对象的响应式数据。
      // Vue 2 响应式数据定义
      export default {
        data() {
          return {
            count: 0
          };
        },
        methods: {
          increment() {
            this.count++;
          }
        }
      };
      
      // Vue 3 响应式数据定义
      import { ref } from 'vue';
      
      export default {
        setup() {
          const count = ref(0);
          const increment = () => {
            count.value++;
          };
          return {
            count,
            increment
          };
        }
      };
      
      性能
      • 渲染性能
        • Vue 2:渲染器在更新 DOM 时,使用虚拟 DOM 进行比较和更新,在处理大型组件树时,可能会有一定的性能开销。
        • Vue 3:重写了渲染器,采用了静态提升、PatchFlag 等优化技术,减少了虚拟 DOM 的比较范围,提高了渲染性能,尤其是在处理大型组件和频繁更新的场景下表现更优。
      • 内存占用
        • Vue 2:由于响应式系统的实现方式,在创建大量响应式对象时,可能会占用较多的内存。
        • Vue 3:Proxy 实现的响应式系统在内存使用上更加高效,减少了不必要的内存开销。
      生态系统
      • 插件兼容性
        • Vue 2:拥有丰富的插件生态系统,但部分插件可能需要进行适配才能在 Vue 3 中使用。
        • Vue 3:随着时间的推移,越来越多的插件开始支持 Vue 3,但在过渡期间,可能会面临一些插件兼容性问题。
      • 工具链支持
        • Vue 2:与之配套的工具链(如 Vue CLI)已经非常成熟。
        • Vue 3:官方推出了 Vite 作为构建工具,它具有更快的冷启动和热更新速度,更适合现代前端开发。

      2. react 性能优化

      在 React 里,性能优化是一个关键环节,下面为你介绍几种常见的优化方法:

      1. 使用 React.memo 进行组件记忆

      React.memo 是一个高阶组件,它能够对组件的 props 进行浅比较。若 props 没有变化,就不会重新渲染组件。

      import React from 'react';
      
      const MyComponent = React.memo((props) => {
        return 
      {props.message}
      ; }); export default MyComponent;
      2. 使用 useMemo 缓存计算结果

      useMemo 能够缓存计算结果,避免在每次渲染时都进行重复计算。

      import React, { useMemo } from 'react';
      
      const MyComponent = (props) => {
        const expensiveValue = useMemo(() => {
          // 进行复杂计算
          return props.num1 + props.num2;
        }, [props.num1, props.num2]);
      
        return 
      {expensiveValue}
      ; }; export default MyComponent;
      3. 使用 useCallback 缓存函数

      useCallback 可缓存函数,防止在每次渲染时都创建新的函数实例。

      import React, { useCallback } from 'react';
      
      const MyComponent = (props) => {
        const handleClick = useCallback(() => {
          console.log('Button clicked');
        }, []);
      
        return ;
      };
      
      export default MyComponent;
      
      4. 代码分割

      使用 React.lazy 和 Suspense 进行代码分割,这样可以按需加载组件,从而减少初始加载时间。

      import React, { lazy, Suspense } from 'react';
      
      const LazyComponent = lazy(() => import('./LazyComponent'));
      
      const App = () => {
        return (
          
      Loading...
      }>
); }; export default App;
5. 避免在渲染过程中触发不必要的状态更新

确保状态更新仅在必要时进行,防止组件不必要的重新渲染。

import React, { useState } from 'react';

const MyComponent = () => {
  const [count, setCount] = useState(0);

  const handleClick = () => {
    // 仅在满足条件时更新状态
    if (count < 10) {
      setCount(count + 1);
    }
  };

  return (
    

Count: {count}

); }; export default MyComponent;

这些方法能够有效地优化 React 应用的性能,不过在实际应用中,你需要依据具体情况选择合适的优化策略。

3. react 组件传值

在 React 里,组件传值是一项基础且重要的操作。下面为你详细介绍几种常见的组件传值方式:

1. 父组件向子组件传值

父组件可通过 props 向子组件传递数据。

// 子组件
const ChildComponent = (props) => {
  return 
{props.message}
; }; // 父组件 const ParentComponent = () => { const message = "Hello from parent"; return ; };
2. 子组件向父组件传值

子组件向父组件传值通常借助回调函数来实现。父组件把一个函数作为 props 传递给子组件,子组件调用该函数并传递数据。

// 子组件
const ChildComponent = (props) => {
  const handleClick = () => {
    props.onClick("Hello from child");
  };
  return ;
};

// 父组件
const ParentComponent = () => {
  const handleChildMessage = (message) => {
    console.log(message);
  };
  return ;
};

3. 跨级组件传值(Context API)

当需要在多个层级的组件间传递数据时,可使用 React 的 Context API

import React, { createContext, useContext, useState } from 'react';

// 创建一个 Context
const MyContext = createContext();

// 子组件
const GrandChildComponent = () => {
  const contextValue = useContext(MyContext);
  return 
{contextValue}
; }; const ChildComponent = () => { return ; }; // 父组件 const ParentComponent = () => { const [message, setMessage] = useState("Hello from context"); return ( ); };
4. 使用第三方库(如 Redux 或 MobX)

对于复杂的应用场景,可使用第三方状态管理库来实现组件间的数据共享。以 Redux 为例:

// 安装依赖
// npm install redux react-redux

import React from 'react';
import { createStore } from 'redux';
import { Provider, useSelector, useDispatch } from 'react-redux';

// 定义 reducer
const counterReducer = (state = { count: 0 }, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return { count: state.count + 1 };
    default:
      return state;
  }
};

// 创建 store
const store = createStore(counterReducer);

// 子组件
const CounterComponent = () => {
  const count = useSelector((state) => state.count);
  const dispatch = useDispatch();
  return (
    

Count: {count}

); }; // 父组件 const App = () => { return ( ); };

上述是 React 中常见的组件传值方式,你可根据具体的应用场景来选择合适的传值方法。

4. v-for 和 v-if 的优先级

Vue 2 中的优先级

在 Vue 2 中,v-for 的优先级高于 v-if。这意味着:

  1. 当两者用在同一个元素上时,v-for 会先执行,然后 v-if 会在每次迭代中运行
  2. 这种顺序会导致性能问题,因为即使你只想渲染部分项,Vue 也会先遍历整个列表

<div v-for="item in items" v-if="item.isActive">
  {{ item.name }}
div>

上面的代码在 Vue 2 中相当于:

this.items.map(function(item) {
  if (item.isActive) {
    return item.name
  }
})
Vue 3 中的优先级

在 Vue 3 中,v-if 的优先级高于 v-for。这意味着:

  1. 当两者用在同一个元素上时,v-if 会先执行
  2. 如果 v-if 的条件不成立,v-for 就不会执行
  3. 这种改变更符合开发者的直觉,但同时也意味着在同一个元素上使用两者时会导致错误

<div v-for="item in items" v-if="item.isActive">
  {{ item.name }}
div>

上面的代码在 Vue 3 中会抛出错误,因为 v-if 先执行时会尝试访问 item,但此时 item 还未通过 v-for 定义。

最佳实践

对于 Vue 2 和 Vue 3,官方都建议避免在同一个元素上同时使用 v-forv-if。替代方案:

  1. 使用计算属性过滤列表(推荐)
<div v-for="item in activeItems">
  {{ item.name }}
div>
computed: {
  activeItems() {
    return this.items.filter(item => item.isActive)
  }
}
  1. v-if 移到外层元素或