React 和 Vue 的核心设计理念

   首先我们要知道,react,和vue的设计理念,区分框架的基本

          react的核心思想是“单向数据流”,

          vue的核心是双向绑定

        我们了解单向和双向,非常容易

        react单向数据量,从字面上来讲,指的是,数据是单向,且不可回,就像水流一样,奔流到海不复回,不可能再让水倒流回来吧。

在react代码中,大到组件传参,小到变量声明,都遵守这单向

               javascript 当中 定义变量 有 let const var

                react hooks  创建变量 ,是由  const [data,setData]=useState() hooks来声明

               data 是我们创建的变量, setData 是我们修改变量的方法函数,这里注意 setData就是一个函数,react 要求状态更新必须通过 setData 完成,直接修改 data(如 data.push(...))不会触发渲染 这样就好比如 我想直接 通过 data=‘123’ 这种 调用修改的方式 是不存在的.不同于 vue 中 可以this.data=123,可以直接用ref reactive声明的数据 ,两者的框架逻辑,底层也是不一致的

其实说到这里,讲他们的设计理念,也牵扯到 渲染原理,触发机制,框架底层监听,就好比与你修改了变量,那视图更不更新?

    vue通过 this.data=**** 因为是双向绑定 ,你变化了就更新试图,这是vue的设计模式mvvm 

react 就不会 ,react 必须要通过 hooks setData的形式 才可以 这也是react框架要求的

我们再说到到组件层次 ,

  • React
    • 子组件绝对不能直接修改父组件传递的props,必须通过回调函数(如父组件传递的setState函数)来通知父组件更新状态。
    • 这种设计强制单向数据流,确保数据变化可预测,避免副作用。
  • Vue
    • 双向同步能力:通过v-model.sync修饰符实现父组件与子组件的双向绑定。子组件可通过$emit触发事件通知父组件更新数据,同时父组件数据变化自动同步到子组件。
    • 反模式警告:虽然技术上子组件可直接修改props(如Vue 2的this.prop = newValue),但Vue官方强烈反对,因其破坏单向数据流。Vue 3通过响应式系统检测props修改并发出警告,推荐使用emitcomputed属性

框架的应用不仅仅是框架的特点等等,同是跟项目类型,开发效率,开发周期,后期优化等

这篇文章有很深的见解从0到1:一名前端程序员的项目沉思录-CSDN博客,

虚拟dom

              react,vue 都是 通过真实dom构建虚拟dom,页面修改变量,函数,不会去直接去修改真实dom,而是去改变虚拟dom,然后虚拟dom 和真实dom 之间通过 diff 算法,来对比差异. 这就像 去写协同编辑,在线编辑,对比差异 ,差异算法,

  • React(Fiber架构 + 单向递归)
    • 分层比较:仅对比同层级节点,不跨层级移动节点(如节点从A层移到B层会销毁重建)。
    • Key机制:依赖唯一key标识列表元素,通过key匹配节点以优化移动、添加或删除操作。无key时按索引顺序比较,可能导致列表头部插入时后续节点全部重建。
    • Fiber架构:将Diff过程分解为多个阶段(如协调、提交),支持异步渲染和优先级调度,适合处理复杂UI和频繁更新(如动画、高频交互)。
  • Vue(双端比较 + 静态优化)
    • 双端指针法:从新旧节点的头尾同时开始比较(头头、尾尾、头尾、尾头),优先复用两端相同的节点,减少中间部分的更新。
    • 静态标记(Patch Flags):编译时标记静态节点(如无绑定的纯文本),跳过运行时Diff,减少对比开销。
    • 最长递增子序列(LIS):在列表操作中(如移动、插入)通过LIS算法确定最小移动路径,减少DOM操作次数(例如列表反转仅需1次移动)

 React Hooks 全面解析

        

// 基础hooks 


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

// useState - 状态管理
function Counter() {
  const [count, setCount] = useState(0);
  const [user, setUser] = useState({ name: '', age: 0 });

  // 函数式更新
  const increment = () => setCount(prev => prev + 1);
  
  return <button onClick={increment}>{count}</button>;
}

// useEffect - 副作用处理
function DataFetcher({ id }) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    let isMounted = true;
    
    const fetchData = async () => {
      try {
        const response = await fetch(`/api/data/${id}`);
        const result = await response.json();
        if (isMounted) {
          setData(result);
          setLoading(false);
        }
      } catch (error) {
        if (isMounted) setLoading(false);
      }
    };

    fetchData();

    // 清理函数
    return () => {
      isMounted = false;
      // 取消请求或其他清理操作
    };
  }, [id]); // 依赖数组

  return loading ? <div>Loading...</div> : <div>{data}</div>;
}

// useContext - 跨组件数据传递
const ThemeContext = React.createContext('light');

function ThemedButton() {
  const theme = useContext(ThemeContext);
  return <button className={theme}>Click me</button>;
}

高级 hooks





import React, { useReducer, useCallback, useMemo, useRef, useImperativeHandle } from 'react';

// useReducer - 复杂状态逻辑
function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    case 'reset':
      return { count: 0 };
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, { count: 0 });
  
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
    </>
  );
}

// useCallback - 记忆函数
function Parent() {
  const [count, setCount] = useState(0);
  
  // 只有count变化时才会重新创建
  const handleClick = useCallback(() => {
    console.log('Count:', count);
  }, [count]);
  
  return <Child onClick={handleClick} />;
}

// useMemo - 记忆计算结果
function ExpensiveComponent({ list }) {
  const sortedList = useMemo(() => {
    return list.sort((a, b) => a.value - b.value);
  }, [list]); // 只有list变化时重新计算
  
  return <div>{sortedList.map(item => <div key={item.id}>{item.value}</div>)}</div>;
}

// useRef - DOM引用和可变值
function TextInput() {
  const inputRef = useRef(null);
  const intervalRef = useRef();
  
  useEffect(() => {
    // 存储定时器ID
    intervalRef.current = setInterval(() => {
      // 执行某些操作
    }, 1000);
    
    return () => clearInterval(intervalRef.current);
  }, []);
  
  const focusInput = () => {
    inputRef.current.focus();
  };
  
  return (
    <>
      <input ref={inputRef} type="text" />
      <button onClick={focusInput}>Focus</button>
    </>
  );
}

// useImperativeHandle - 暴露子组件方法
function FancyInput(props, ref) {
  const inputRef = useRef();
  
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    },
    scrollIntoView: () => {
      inputRef.current.scrollIntoView();
    }
  }));
  
  return <input ref={inputRef} />;
}

FancyInput = React.forwardRef(FancyInput);

React 高级特性

   

/ 创建Context
const UserContext = React.createContext({
  user: null,
  login: () => {},
  logout: () => {}
});

// Provider组件
function UserProvider({ children }) {
  const [user, setUser] = useState(null);
  
  const login = async (credentials) => {
    const userData = await loginAPI(credentials);
    setUser(userData);
  };
  
  const logout = () => {
    logoutAPI();
    setUser(null);
  };
  
  return (
    <UserContext.Provider value={{ user, login, logout }}>
      {children}
    </UserContext.Provider>
  );
}

// 消费Context
function UserProfile() {
  const { user, logout } = useContext(UserContext);
  
  return (
    <div>
      <h1>Welcome, {user.name}</h1>
      <button onClick={logout}>Logout</button>
    </div>
  );
}
Refs转发和DOM操作
// Refs转发
const CustomInput = React.forwardRef((props, ref) => {
  return <input ref={ref} {...props} />;
});

// 在父组件中使用
function Parent() {
  const inputRef = useRef(null);
  
  useEffect(() => {
    inputRef.current.focus();
  }, []);
  
  return <CustomInput ref={inputRef} />;
}

Vue 3 Composition API

        模板语法糖
<template>
  <!-- 条件渲染 -->
  <div v-if="isVisible">Visible</div>
  <div v-else>Not Visible</div>
  
  <!-- 列表渲染 -->
  <ul>
    <li v-for="(item, index) in items" :key="item.id">
      {{ item.name }}
    </li>
  </ul>
  
  <!-- 动态绑定 -->
  <div :class="{ active: isActive, 'text-danger': hasError }"></div>
  <button :disabled="isDisabled">Click</button>
  
  <!-- 事件处理 -->
  <button @click="handleClick">Click</button>
  <form @submit.prevent="handleSubmit"></form>
  
  <!-- 双向绑定 -->
  <input v-model="message">
  <input v-model.number="age" type="number">
  
  <!-- 插槽 -->
  <BaseLayout>
    <template #header>
      <h1>Header</h1>
    </template>
    <p>Main content</p>
  </BaseLayout>
</template>
组件通信

   

<!-- 父组件 -->
<template>
  <ChildComponent 
    :title="pageTitle"
    @update-title="pageTitle = $event"
  />
</template>

<!-- 子组件 -->
<script>
export default {
  props: {
    title: String
  },
  emits: ['update-title'],
  methods: {
    updateTitle(newTitle) {
      this.$emit('update-title', newTitle);
    }
  }
};
</script>

<!-- Provide/Inject 跨层级通信 -->
<script>
// 祖先组件
export default {
  provide() {
    return {
      theme: 'dark',
      user: reactive({ name: 'John' })
    };
  }
};

// 后代组件
export default {
  inject: ['theme', 'user']
};
</script>
自定义指令
// 全局指令
app.directive('focus', {
  mounted(el) {
    el.focus();
  }
});

// 局部指令
export default {
  directives: {
    highlight: {
      mounted(el, binding) {
        el.style.backgroundColor = binding.value || 'yellow';
      },
      updated(el, binding) {
        el.style.backgroundColor = binding.value;
      }
    }
  }
};

// 使用
<div v-highlight="'red'"></div>

特性

React

Vue

​设计理念​

函数式编程

渐进式框架

​学习曲线​

相对陡峭

相对平缓

​模板系统​

JSX

模板语法

​状态管理​

不可变状态

可变状态

​样式方案​

CSS-in-JS/CSS Modules

Scoped CSS/CSS Modules

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐