⚠️温馨提示: 文档中包含【1个】暂不支持的区域,请通过搜索关键字【暂不支持的文档区域】进行后续处理

vue3-sourcecode-notes.zip

很多同学可能第一次来,我分享了那摩多干货公开课,不允许你不知道!都在这里,需要 文档和配套视频找咨询老师 领取~

【飞书文档】备战金九银十,进阶大前端,涨薪全突破!

【飞书文档】项目没有难点亮点?字节大佬带你前端项目弯道超车

【飞书文档】字节大佬带你弯道超车,深入剖析大厂面试真题~

【飞书文档】面试被算法干吐了?字节大佬带你突破极限,冲击 30K+ 必掌握算法与 WebAssembly 技术

【飞书文档】高级前端专家如何做性能优化?特邀字节大佬细数飞书应用优化细节【超详细内培版】

【飞书文档】高级前端专家如何做项目架构与工程化设计? 特邀字节大佬细数字节开源项目架构细节【超详细内培版】

【飞书文档】小小微前端,轻松拿捏,特邀字节大佬开讲微前端架构与源码剖析【内部培训版】 35K+ 同学必看

【飞书文档】高级前端专家如何做性能优化?特邀字节大佬细数飞书应用优化细节(二)【内部培训版】

【飞书文档】前端破局 AI 应用开发,特邀字节大佬分享字节系 AI 场景落地应用与 AI 引擎编排流程

【飞书文档】React18 源码深度剖析,字节面试官教你轻松拿捏高级前端专家面试框架原理题

  1. 自顶向下粗略了解思想:整体项目架构
  2. 关键包与职责:compiler-core、compiler-dom、compiler-sfc、reactivity、runtime-core、runtime-dom
  3. 核心过程:编译时 -> 运行时 -> 响应式数据 -> dom 渲染
  4. 数据结构与算法:WeakMap、位运算(patch、shape、slot)等
  • 交代问题的背景,或者是发展的历史

  • 给出对应解决方案

  • 具体方案落地

  • 反思与优化

  • 初中级 】面试官:请说说你对 Vue3 响应式的理解

  • 中高级 】面试官:结合 Vue3 Composition API 说说你对函数式编程思想的理解

  • 专家级 】面试官:说说 Vue3 编译,还有 Vue Vine 原理

初中级 】面试官:请说说你对 Vue3 响应式的理解

早期没有诸如 React、Vue 这类库时,我们都采用事件驱动的实现方式开发功能,即:用户触发事件,修改变量,而后操作 dom 将变量值反映到页面上。

事件驱动

假设我们有一个按钮,点击按钮后会在页面上添加一个新的段落。

HTML:

<!DOCTYPE html>
<html>
<head>
  <title>DOM 操作示例</title>
</head>
<body>
  <button id="add-paragraph">添加段落</button>
  <div id="content"></div>

  <script src="script.js"></script>
</body>
</html>

JavaScript (script.js):

document.getElementById('add-paragraph').addEventListener('click', function() {
  const newParagraph = document.createElement('p');
  newParagraph.textContent = '妙码学院——让进取的人更具职业价值';
  document.getElementById('content').appendChild(newParagraph);
});

在这个例子中,我们直接通过 DOM API 操作页面元素。这种方式在项目规模较小、页面逻辑较简单时比较方便,但当页面变得复杂时,手动管理 DOM 会变得繁琐且容易出错。

状态驱动

同样的功能,我们使用 Vue3 来实现。

<template>
  <div>
    <button @click="addParagraph">添加段落</button>
    <div id="content">
      <p v-for="(paragraph, index) in paragraphs" :key="index">{{ paragraph }}</p>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue';

const paragraphs = ref([]);

const addParagraph = () => {
  paragraphs.value.push('妙码学院——让进取的人更具职业价值');
};
</script>

<style scoped>
button {
  margin-bottom: 10px;
}
</style>

在这个例子中,我们使用 React 来构建 UI。React 使用组件来管理页面的状态和渲染逻辑。

区别与优势对比

代码结构与可维护性

DOM 操作

  • 代码结构 :直接操作 DOM 的代码往往是命令式的,需要明确地告诉浏览器每一步应该做什么。这种代码结构可能会变得复杂和难以管理,特别是当应用变得庞大时。
  • 可维护性 :由于直接操作 DOM 的代码缺乏结构化,代码的可维护性较差。任何对页面结构的更改都需要在多个地方同步修改,容易导致错误。

Vue

  • 代码结构 :Vue 提供了声明式的代码风格,开发者只需描述最终的状态,Vue 会自动处理 DOM 操作。组件化的设计使代码结构清晰,每个组件负责特定的功能。
  • 可维护性 :组件化和声明式代码使得 Vue 的代码更易于维护。修改一个组件不会影响其他组件,且组件之间的依赖关系明确,维护成本低。

状态管理

DOM 操作

  • 状态管理 :在直接操作 DOM 的情况下,状态管理通常依赖于全局变量或者在 DOM 元素上存储数据。随着状态的复杂度增加,管理这些状态变得非常困难。
  • 同步问题 :手动管理状态同步可能会导致状态不一致和难以调试的问题。

Vue

  • 状态管理 :Vue 提供了响应式的数据绑定,数据和视图自动同步。使用 refreactive 等工具,开发者可以轻松管理组件内部状态。
  • 全局状态管理 :Vue 生态系统中还有 Vuex 这样的状态管理库,方便管理全局状态,并且提供了时间旅行调试等高级功能。

性能

DOM 操作

  • 性能优化 :直接操作 DOM 的性能取决于实现的具体细节。高频繁的 DOM 操作会导致重排和重绘,影响性能。
  • 细粒度控制 :开发者可以对每一个 DOM 操作进行细粒度的优化,但需要较高的开发成本和经验。

Vue

  • 性能优化 :Vue 通过响应式减少了直接 DOM 操作的次数,提高了性能。Vue 的 diff 算法可以高效地比较新旧虚拟 DOM,最小化更新范围。
  • 自动优化 :Vue 提供了许多性能优化机制,如懒加载、异步组件等,开发者无需过多关注底层优化细节。

开发效率

DOM 操作

  • 开发效率 :直接操作 DOM 通常需要编写大量的样板代码,开发效率较低。特别是在复杂的应用中,开发和调试过程可能会非常繁琐。
  • 调试困难 :由于缺乏结构化和工具支持,调试和查找问题变得困难。

Vue

  • 开发效率 :Vue 提供了许多开发工具,如 Vue CLI、Vue DevTools 等,大大提高了开发效率。组件化开发模式和模板语法简化了代码编写。
  • 生态系统 :Vue 生态系统丰富,提供了许多开箱即用的库和插件,进一步提升了开发效率。

结论

综上所述,使用 Vue 进行开发相比直接操作 DOM 有着显著的优势:

  • 代码结构与可维护性 :Vue 的组件化和声明式编程使得代码结构更清晰,维护更简单。
  • 状态管理 :Vue 的响应式数据绑定和 Pinia 等状态管理工具使状态管理变得简单且高效。
  • 性能 :Vue 的虚拟 DOM 技术和内置优化机制使得应用性能更高。
  • 开发效率 :Vue 提供了强大的开发工具和丰富的生态系统,大幅提高了开发效率。

手写实现简版 Vue3 核心源码

💡 储备知识:

  • Proxy
  • Reflect
  • Set
  • 发布订阅模式

依赖追踪系统

首先,我们需要一个依赖追踪系统,用于追踪依赖并在数据变化时通知相关副作用函数。

class Dep {
  constructor() {
    this.subscribers = new Set();
  }

  depend() {
    if (activeEffect) {
      this.subscribers.add(activeEffect);
    }
  }

  notify() {
    this.subscribers.forEach(effect => effect.update());
  }
}

Watcher 实现

Watcher 类用于管理副作用函数,并在数据变化时重新执行副作用函数。

let activeEffect = null;

class Watcher {
  constructor(effect) {
    this.effect = effect;
    this.run();
  }

  run() {
    activeEffect = this;
    this.effect();
    activeEffect = null;
  }

  update() {
    this.run();
  }
}

function effect(eff) {
  new Watcher(eff);
}

创建响应式对象

实现一个 reactive 函数,将一个普通对象转换为一个响应式对象。我们使用 Proxy 来拦截对象的 getset 操作,从而实现依赖收集和通知。

const targetMap = new WeakMap();

function getDep(target, key) {
  let depsMap = targetMap.get(target);
  if (!depsMap) {
    depsMap = new Map();
    targetMap.set(target, depsMap);
  }

  let dep = depsMap.get(key);
  if (!dep) {
    dep = new Dep();
    depsMap.set(key, dep);
  }

  return dep;
}

function reactive(target) {
  const handler = {
    get(target, key, receiver) {
      const dep = getDep(target, key);
      dep.depend();
      return Reflect.get(target, key, receiver);
    },
    set(target, key, value, receiver) {
      const result = Reflect.set(target, key, value, receiver);
      const dep = getDep(target, key);
      dep.notify();
      return result;
    }
  };
  return new Proxy(target, handler);
}

更新 DOM 视图

我们需要一个 render 函数来更新 DOM 视图。当响应式数据发生变化时,这个函数将重新渲染视图。

function render() {
  document.getElementById('count-display').innerText = `count is: ${state.count}`;
}

完整实现

现在我们将所有部分整合起来,通过 effect 函数来监控响应式数据的变化,并在数据变化时调用 render 函数更新视图。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Reactive System with Vue 3</title>
</head>
<body>
  <div id="app">
    <p id="count-display"></p>
    <button id="increment-btn">Increment</button>
  </div>

  <script>
    // 简单的依赖追踪系统
    class Dep {
      constructor() {
        this.subscribers = new Set();
      }

      depend() {
        if (activeEffect) {
          this.subscribers.add(activeEffect);
        }
      }

      notify() {
        this.subscribers.forEach(effect => effect.update());
      }
    }

    let activeEffect = null;

    class Watcher {
      constructor(effect) {
        this.effect = effect;
        this.run();
      }

      run() {
        activeEffect = this;
        this.effect();
        activeEffect = null;
      }

      update() {
        this.run();
      }
    }

    function effect(eff) {
      new Watcher(eff);
    }

    const targetMap = new WeakMap();

    function getDep(target, key) {
      let depsMap = targetMap.get(target);
      if (!depsMap) {
        depsMap = new Map();
        targetMap.set(target, depsMap);
      }

      let dep = depsMap.get(key);
      if (!dep) {
        dep = new Dep();
        depsMap.set(key, dep);
      }

      return dep;
    }

    function reactive(target) {
      const handler = {
        get(target, key, receiver) {
          const dep = getDep(target, key);
          dep.depend();
          return Reflect.get(target, key, receiver);
        },
        set(target, key, value, receiver) {
          const result = Reflect.set(target, key, value, receiver);
          const dep = getDep(target, key);
          dep.notify();
          return result;
        }
      };
      return new Proxy(target, handler);
    }

    // 使用实现的响应式系统
    const state = reactive({
      count: 0
    });

    // 渲染函数
    function render() {
      document.getElementById('count-display').innerText = `count is: ${state.count}`;
    }

    // 注册副作用函数
    effect(() => {
      render();
    });

    // 按钮点击事件
    document.getElementById('increment-btn').addEventListener('click', () => {
      state.count++;
    });
  </script>
</body>
</html>

通过以上步骤,我们实现了一个简单的 Vue3 响应式系统,并在响应数据变化时自动更新 DOM 视图。通过 effect 监控响应式数据,结合 render 函数实现视图更新,当按钮点击时修改 state.count ,视图会自动重新渲染。

Vue2 与 Vue3 响应式实现对比

如果要回答 Vue3 与 Vue2 的响应式实现区别,请讲 ProxyObject.defineProperty 进行详细对比。

Vue2 响应式实现

在 Vue2 中,响应式系统是基于 Object.defineProperty 和依赖追踪来实现的。每个响应式对象的属性通过 gettersetter 方法来进行拦截。

  1. 依赖追踪 (Dep)

    • Vue2 使用 Dep 类来管理依赖收集和通知。
    • 每个响应式对象的属性都会有一个对应的 Dep 实例。
    • getter 中收集依赖,在 setter 中通知依赖。
  2. Observer

    • Vue2 使用 Observer 类来将对象的每个属性转换为响应式。
    • 通过递归的方式,将对象的每一层都转换为响应式。
  3. Watcher

    • Watcher 是响应式系统的核心,负责依赖收集和响应式更新。
    • 每个组件实例化时,都会创建相应的 Watcher 实例。
class Dep {
  constructor() {
    this.subs = [];
  }

  addSub(sub) {
    this.subs.push(sub);
  }

  notify() {
    this.subs.forEach(sub => sub.update());
  }
}

class Watcher {
  constructor(vm, expOrFn, cb) {
    this.vm = vm;
    this.expOrFn = expOrFn;
    this.cb = cb;
    this.value = this.get();
  }

  get() {
    Dep.target = this;
    const value = this.vm[this.expOrFn];
    Dep.target = null;
    return value;
  }

  update() {
    const newValue = this.vm[this.expOrFn];
    const oldValue = this.value;
    this.value = newValue;
    this.cb.call(this.vm, newValue, oldValue);
  }
}

function defineReactive(obj, key, val) {
  const dep = new Dep();

  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get() {
      if (Dep.target) {
        dep.addSub(Dep.target);
      }
      return val;
    },
    set(newVal) {
      if (newVal === val) return;
      val = newVal;
      dep.notify();
    }
  });
}

function observer(value) {
  if (!value || typeof value !== 'object') {
    return;
  }

  Object.keys(value).forEach(key => {
    defineReactive(value, key, value[key]);
  });
}

class Vue {
  constructor(options) {
    this.data = options.data;
    observer(this.data);
    new Watcher(this, 'data.message', function (value) {
      console.log('Data changed: ', value);
    });
  }
}

const vm = new Vue({
  data: {
    message: '妙码学院'
  }
});

vm.data.message = '妙码学院——让进取的人更具职业价值';  // Console: Data changed: Hello World

Vue3 的响应式实现

在 Vue3 中,响应式系统是基于 ES6 的 Proxy 对象实现的,这使得其更强大和灵活。

  1. 依赖追踪 (Dep)

    • 和 Vue2 类似,Vue3 也使用 Dep 类来管理依赖收集和通知,但其实现更加简洁。
    • 每个响应式对象的属性通过 Proxy 拦截。
  2. Reactive 和 Effect

    • Vue3 使用 reactive 函数将普通对象转换为响应式对象。
    • effect 函数用于注册副作用函数,当响应式对象的属性变化时,自动重新运行该副作用函数。
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Reactive System with Vue 3</title>
</head>
<body>
  <div id="app">
    <p id="count-display"></p>
    <button id="increment-btn">Increment</button>
  </div>

  <script>
    // 简单的依赖追踪系统
    class Dep {
      constructor() {
        this.subscribers = new Set();
      }

      depend() {
        if (activeEffect) {
          this.subscribers.add(activeEffect);
        }
      }

      notify() {
        this.subscribers.forEach(effect => effect.update());
      }
    }

    let activeEffect = null;

    class Watcher {
      constructor(effect) {
        this.effect = effect;
        this.run();
      }

      run() {
        activeEffect = this;
        this.effect();
        activeEffect = null;
      }

      update() {
        this.run();
      }
    }

    function effect(eff) {
      new Watcher(eff);
    }

    const targetMap = new WeakMap();

    function getDep(target, key) {
      let depsMap = targetMap.get(target);
      if (!depsMap) {
        depsMap = new Map();
        targetMap.set(target, depsMap);
      }

      let dep = depsMap.get(key);
      if (!dep) {
        dep = new Dep();
        depsMap.set(key, dep);
      }

      return dep;
    }

    function reactive(target) {
      const handler = {
        get(target, key, receiver) {
          const dep = getDep(target, key);
          dep.depend();
          return Reflect.get(target, key, receiver);
        },
        set(target, key, value, receiver) {
          const result = Reflect.set(target, key, value, receiver);
          const dep = getDep(target, key);
          dep.notify();
          return result;
        }
      };
      return new Proxy(target, handler);
    }

    // 使用实现的响应式系统
    const state = reactive({
      count: 0
    });

    // 渲染函数
    function render() {
      document.getElementById('count-display').innerText = `count is: ${state.count}`;
    }

    // 注册副作用函数
    effect(() => {
      render();
    });

    // 按钮点击事件
    document.getElementById('increment-btn').addEventListener('click', () => {
      state.count++;
    });
  </script>
</body>
</html>

区别对比总结

  1. 实现方式

    • Vue2 :使用 Object.defineProperty 实现响应式,只能拦截对象已有的属性,不能处理新添加的属性或删除属性。所以源码中重写了数组与对象操作原型方法。
    • Vue3 :使用 Proxy 实现响应式,可以拦截对象的任意操作,包括动态添加和删除属性。
  2. 性能和灵活性

    • Vue2 :由于 Object.defineProperty 的限制,对象深层嵌套结构和数组的处理相对复杂,性能也受到一定影响。
    • Vue3Proxy 提供了更高的性能和灵活性,能够处理更多场景,并且对深层嵌套对象和数组的处理更为高效。
  3. API 设计

    • Vue2 :响应式 API 较为有限,主要通过 data 选项和 watch 选项实现。
    • Vue3 :引入了 reactiverefcomputedeffect 等更丰富的 API,使得响应式系统更易于使用和扩展,支持更灵活的组合式 API。
  4. 对数组和嵌套对象的处理

    • Vue2 :需要特殊处理数组和嵌套对象,复杂性较高。
    • Vue3Proxy 使得对数组和嵌套对象的处理更为简单和高效。

中高级 】面试官:结合 Vue3 Composition API 说说你对函数式编程思想的理解

在回答这个问题时,你要搞清楚,这不是一个问题,这是两个!

其一 :函数式编程思想,FP

其二 :Composition API 设计

函数式编程思想

函数式编程(Functional Programming,FP)是一种编程范式,它将计算过程视为数学函数的计算,并且强调不变性和纯函数。FP 的核心思想包括:

  1. 纯函数 :函数的输出只依赖于输入参数,并且不产生副作用。
  2. 不可变性 :数据不可变,所有的数据修改都会产生新的数据副本。
  3. 高阶函数 :可以将函数作为参数传递给另一个函数,或者将函数作为返回值返回。
  4. 函数组合 :通过将小的函数组合在一起,构建更复杂的功能。

最经典的一个面试考题,也是 redux 源码中的一个函数,compose,这个函数太重要了,在你实现中间件、拦截器颇为有用。

function compose(...funcs) {
  if (funcs.length === 0) {
    return arg => arg;
  }

  if (funcs.length === 1) {
    return funcs[0];
  }

  return funcs.reduce((a, b) => (...args) => a(b(...args)));
}

// 示例用法
const add = x => x + 1;
const multiply = x => x * 2;
const subtract = x => x - 3;

const composedFunction = compose(add, multiply, subtract);

console.log(composedFunction(5)); // 输出: 7

Vue 3 Composition API 与函数式编程

Vue 3 引入了 Composition API,它提供了一种更灵活的方式来组合和复用逻辑,这种方式与函数式编程的思想非常契合。

纯函数与计算属性

Composition API 中的 computed 是一个纯函数的例子。计算属性的值完全依赖于它的依赖项,并且不会产生副作用:

import { ref, computed } from 'vue';

const count = ref(0);
const doubleCount = computed(() => count.value * 2);

不可变性与状态管理

在 Vue 3 中,我们可以使用 refreactive 创建响应式状态。尽管 Vue 的响应式系统本身是可变的,我们仍可以通过合理的状态管理策略来保持状态的不可变性。例如,在状态更新时生成新的状态对象,而不是直接修改原始状态:

import { reactive } from 'vue';

const state = reactive({ count: 0 });

function increment() {
  state.count += 1;
}

高阶函数与组合函数

Vue 3 的 Composition API 非常适合高阶函数和组合函数的使用。例如,我们可以创建一个自定义 Hook,它接收一个参数并返回一个组合了特定逻辑的响应式状态:

import { ref, onMounted } from 'vue';

function useFetch(url) {
  const data = ref(null);
  const error = ref(null);

  onMounted(async () => {
    try {
      const response = await fetch(url);
      data.value = await response.json();
    } catch (err) {
      error.value = err;
    }
  });

  return { data, error };
}

const { data, error } = useFetch('https://api.example.com/data');

函数组合与逻辑复用

通过组合多个小函数,可以构建更复杂的逻辑。例如,使用多个自定义 Hook 来复用逻辑:

function useCounter() {
  const count = ref(0);
  const increment = () => count.value++;
  return { count, increment };
}

function useDoubleCounter() {
  const { count, increment } = useCounter();
  const doubleCount = computed(() => count.value * 2);
  return { count, doubleCount, increment };
}

const { count, doubleCount, increment } = useDoubleCounter();

专家级 】面试官:说说 Vue3 编译,还有 Vue Vine 原理

我们使用接近 Vue3 官方的编译器原理,来为大家演示 Vue3 编译核心。

编译器主要包含:

  • tokenizer(tokens)
  • parser(ast)
  • traverse(target ast)
  • generator(new code)

官方使用状态机与 tokens 机制,严格按照编译原理实现了 Vue3 编译器内容,要知道在早期,Vue2 都还是使用正则表达式匹配形式完成这项工作。

SFC 编译器实现

定义 tokens

首先,我们定义不同类型的令牌,用于表示 SFC 文件中的不同部分。

const TokenType = {
    TEMPLATE_START: 'TEMPLATE_START',
    TEMPLATE_END: 'TEMPLATE_END',
    SCRIPT_START: 'SCRIPT_START',
    SCRIPT_END: 'SCRIPT_END',
    STYLE_START: 'STYLE_START',
    STYLE_END: 'STYLE_END',
    CONTENT: 'CONTENT'
};

实现 tokenizer

令牌化器负责将输入字符串转换为一系列令牌。

function tokenize(source) {
    const tokens = [];
    const len = source.length;
    let i = 0;

    while (i < len) {
        if (source.startsWith('<template>', i)) {
            tokens.push({ type: TokenType.TEMPLATE_START });
            i += '<template>'.length;
        } else if (source.startsWith('</template>', i)) {
            tokens.push({ type: TokenType.TEMPLATE_END });
            i += '</template>'.length;
        } else if (source.startsWith('<script>', i)) {
            tokens.push({ type: TokenType.SCRIPT_START });
            i += '<script>'.length;
        } else if (source.startsWith('</script>', i)) {
            tokens.push({ type: TokenType.SCRIPT_END });
            i += '</script>'.length;
        } else if (source.startsWith('<style>', i)) {
            tokens.push({ type: TokenType.STYLE_START });
            i += '<style>'.length;
        } else if (source.startsWith('</style>', i)) {
            tokens.push({ type: TokenType.STYLE_END });
            i += '</style>'.length;
        } else {
            let content = '';
            while (i < len && !source.startsWith('<', i)) {
                content += source[i++];
            }
            if (content.trim()) {
                tokens.push({ type: TokenType.CONTENT, value: content });
            }
        }
    }

    return tokens;
}

实现 parser

解析器使用令牌化器生成的令牌来构建一个描述 SFC 结构的对象。

function parse(tokens) {
    const sfc = {
        template: '',
        script: '',
        style: ''
    };

    let current = null;

    for (const token of tokens) {
        switch (token.type) {
            case TokenType.TEMPLATE_START:
                current = 'template';
                break;
            case TokenType.TEMPLATE_END:
                current = null;
                break;
            case TokenType.SCRIPT_START:
                current = 'script';
                break;
            case TokenType.SCRIPT_END:
                current = null;
                break;
            case TokenType.STYLE_START:
                current = 'style';
                break;
            case TokenType.STYLE_END:
                current = null;
                break;
            case TokenType.CONTENT:
                if (current) {
                    sfc[current] += token.value;
                }
                break;
        }
    }

    return sfc;
}

编译各部分

编译器将解析后的模板、脚本和样式转换为可以直接使用的代码。

function compileTemplate(template) {
    return `function render() {
        with (this) {
            return \`${template.replace(/`/g, '\\`')}\`;
        }
    }`;
}

function compileScript(script) {
    return script;
}

function compileStyle(style) {
    return `<style>${style}</style>`;
}

组合编译结果

将所有编译后的部分组合成最终的输出。

function compileSFC(filename) {
    const source = fs.readFileSync(filename, 'utf-8');
    const tokens = tokenize(source);
    const { template, script, style } = parse(tokens);

    const compiledTemplate = compileTemplate(template);
    const compiledScript = compileScript(script);
    const compiledStyle = compileStyle(style);

    const result = `
        ${compiledStyle}
        <script>
        ${compiledScript}
        export default {
            render: ${compiledTemplate}
        };
        </script>
    `;
    return result;
}

const filename = 'path/to/your/component.vue';
const compiledCode = compileSFC(filename);
console.log(compiledCode);

进一步拥抱函数式(进一步抄 React jsx 🙈🙈🙈)

7.6 号大家去参加了 VueConf 吗?新发布的 Vue Vine 有没有了解?

如果没去,没了解,那我给大家演示一下,敢相信这是新的 Vue 用法吗?

新用法

其实还是因为 Vue3 整体设计受限,如果要进一步拥抱 jsx,只能另辟蹊径,这里作者借用了标签函数(大家熟知的模板字符串形式)

function MyComponent() {
  const name = '妙码学院'

  return miaoma`<div>Hello ${name}</div>`
}

实现原理

具体实现标签函数,重点关注模板字符串,与模板字符串中需要被替换的内容。

import { h } from 'vue';

function miaoma(strings, ...values) {
    const template = strings.reduce((result, string, i) => {
        return result + string + (values[i] !== undefined ? values[i] : '');
    }, '');

    return function render() {
        const div = document.createElement('div');
        div.innerHTML = template;
        const vnode = h('div', {}, div.innerHTML);
        return vnode;
    };
}

export default miaoma;

妙码学院全网独家项目实战矩阵

所有项目实战,均完全 从零到一手写纯原创 ,项目架构与编码规范真一线大厂级。

  • 微前端在分拆原子应用场景下的落地与实践

  • 协同编辑器从零到一架构实现

  • 推动团队基建落地

  • 数字孪生平台整体架构设计

  • 低代码平台设计与实现

    • 编排引擎
    • 流程引擎
    • 编辑器
    • 代码执行器与 JavaScript 沙箱
  • 用户行为分析 SDK 及监控可视化整体实现

  • 可视化渲染引擎设计与实现

  • 基于 RAG / Agent 前端 AI 应用流程编排平台

简历优化(30K+ 简历样板)

技能描述

  • 熟练掌握 HTML、CSS、JavaScript、Typescript 以及 OOP、FP、 AOP 等设计思想

  • 掌握样式体系构建与落地,对 css 预编译、css in js、module css 以及 utility-first CSS 有深入研究,并从零改良过样式体系以支持 SSR、SSG

  • 熟悉 React、Vue 相关技术栈,熟悉 React、Vue 及相关技术框架的实现原理

  • 掌握构建工具 Webpack、Vite 等,掌握编译工具 Babel,并深入理解其原理,并参与 Rspack 构建

  • 丰富的数据可视化经验,熟悉 Canvas、svg 开发范式,理解 Echarts、Antv 原理,能根据业务需求基于 d3、zrender 开发自定义渲染引擎

  • 丰富的跨端开发经验,熟练使用 Taro、Flutter、React-Native 开发跨端应用,对构建 hybird App 有丰富经验,深入理解跨端开发编译原理

  • 基于 Node.js 开发脚手架、打包构建优化工具及中间件服务

  • 掌握常用设计模式、算法与安全知识,追求开发高质量、高可维护性代码,追求极致产品体验

  • 团队管理经验,并在项目架构设计与性能优化方面具有丰富经验

  • 算法与编程技术

    • 精通各种算法题的分类及解决方法,包括排序与查找、数据结构、动态规划、贪心算法、回溯算法、分治算法、图论算法、数学算法等。
    • 重点掌握动态规划的基本概念、解题步骤和经典题目。
  • 3D 数字孪生平台开发经验

    • 熟练使用 WebGL 和 WebAssembly 技术,开发高效的 3D 渲染引擎。
    • 精通正射影像和倾斜摄影技术,具备 Tile 和模型(包括白膜和精模)的处理经验,能够使用 Blender 进行模型制作。
    • 熟悉材质、光效和粒子系统的实现与优化。
  • 全面性能优化能力

    • 具备打包构建优化经验,熟练使用 Webpack 进行模块打包,掌握 chunk、treeshaking、happypack、cache-loader 等优化技巧,并使用 Webpack Module Federation 进行模块联邦管理。
    • 精通资源优化,能够有效进行图片、字体压缩,管理请求队列,并通过 OSS 和 CDN 提升资源加载速度。
    • 具有应用性能优化经验,包括数据结构优化和应用模块更新。
    • 深入了解缓存机制,熟悉强缓存(Expiration、Cache-Control)、协商缓存(Etag)和策略缓存(Service-Worker)的配置与管理。

项目描述

这个环节至关重要,很多同学不重视,简历随便写一写就开始投递了,结果投出去几百份可能一家公司面试都没有,结果就在怀疑前端行情出问题了

STAR 法则:

  • 遇到了什么问题 question,需求
  • 怎么评估解决方案,方案对比,方案落地 react 状态管理(redux、mobx、jotai、recoil)Vue3 -> Pinia
  • 具体方案落地
  • 结果反思,细节优化思考

大家先看这段描述:

技术栈:Java、Vue2、echarts、WEui、BaiduMap、JavaScript 、HTTP数据库:MySQL管理工具:SVN

责任描述:

1)产品前端研发负责人,主要负责整体样式沟通,样式调配实现;门户、管理平台、移动端、智端、可视化等前端内容实现;

2)实现组织管理、人员管理、党员关系转接、待办通知、绩效考核(复杂功能算法实现)、发展党员(25个流程)、可视化等主体功能,兼容性优化、适配1920*1080屏幕以及响应式布局实现;

3)相关功能开发,包含前后端、数据库;

4)门户框架搭建、门户整体设计、后端接口、门户前端 UI 实现等;

5)微信小程序框架搭建、小程序页面设计及开发、知识图谱技术预演;

6 )项目经理工作辅助,包含需求沟通、UI设计沟通、交付材料项目经历整理、前端代码质量管理、部分功能设计。

深度优化一下

工作内容和成果

  • 架构设计 】参与智慧管理平台整体架构设计、技术选型与方案评审,担任全栈开发,完成相关核心模块
  • 企微开发 】对接企业微信生态,基于企微 SDK 完成平台支付、消息推送、机器人等功能开发
  • 可视化 】主导完成平台可视化渲染引擎(可视化图表的组件,数据协议)设计与开发,基于 echarts (svgRenderer、canvasRenderer 一千万行数据的表格渲染【不能使用 虚拟滚动 】 canvas table,chunk)封装业务图表库,服务于平台可视化场景
  • 地图开发 】使用百度地图 SDK,封装业务地图渲染器(MapRenderer),包含:地图撒点、地区数据下钻等功能
  • 小程序与App 】基于 uniapp 实现智慧党建用户端多端开发落地,产物编译为 H5、微信小程序两端应用
  • 团队基建 】推进团队业务组件库、图表库与基础库沉淀,完成 10+ 个业务组件沉淀,以此提升了团队协同开发效率
  • 优化 】设计产品响应式系统,基于 media query 设计响应式端点规则,适配不同端应用的展示
  • 自研 OA 打通 】...

STAR

【技术栈】

  • Java、Vue2、ECharts、WEui、BaiduMap、JavaScript、HTTP
  • 数据库 :MySQL
  • 管理工具 :SVN

【产品前端研发负责人】

  • 情境 (Situation) :担任产品前端研发负责人,负责门户、管理平台、移动端、智端、可视化等前端内容的实现。
  • 任务 (Task) :主要任务是与设计团队沟通,调配和实现整体样式,确保产品界面的一致性和用户体验。
  • 行动 (Action) :我协调设计与开发团队,定期召开样式沟通会,亲自进行样式的调配与实现,并负责不同平台和设备的前端内容开发。
  • 结果 (Result) :成功实现了多个平台的前端开发工作,提升了产品的用户体验和一致性,获得了团队和用户的高度评价。

【实现复杂功能及优化】

  • 情境 (Situation) :项目需要实现复杂功能算法和大规模功能模块,包括组织管理、人员管理、党员关系转接、待办通知、绩效考核、发展党员(25个流程)和可视化功能。
  • 任务 (Task) :负责上述复杂功能的实现,并优化其兼容性和响应式布局。
  • 行动 (Action) :通过设计和实现复杂算法,确保各模块的功能性;进行兼容性优化,使系统适配1920*1080屏幕和响应式布局。
  • 结果 (Result) :成功实现并优化了所有复杂功能,系统在不同设备和分辨率下均表现良好,提高了用户操作的流畅度和满意度。

【全面功能开发】

  • 情境 (Situation) :需要进行前后端和数据库的全面开发,确保系统各功能模块的无缝集成。
  • 任务 (Task) :开发和实现相关功能,包括前端UI、后端接口和数据库交互。
  • 行动 (Action) :采用Java、Vue2等技术,开发并调试各功能模块,与后端团队密切合作,确保接口的准确性和数据的一致性。
  • 结果 (Result) :成功完成了所有功能模块的开发和集成,系统运行稳定,性能优异,受到了客户的好评。

【微信小程序开发与知识图谱预演】

  • 情境 (Situation) :项目需要开发微信小程序,并进行知识图谱技术的预演。
  • 任务 (Task) :负责小程序框架的搭建、页面设计及开发,同时进行知识图谱的技术预演。
  • 行动 (Action) :使用WEui、JavaScript等技术,设计并开发小程序页面,进行知识图谱的技术预演和验证。
  • 结果 (Result) :成功搭建了微信小程序框架,完成了页面设计和开发工作,知识图谱技术预演顺利,通过了技术验证。

【项目经理工作辅助】

  • 情境 (Situation) :在项目中辅助项目经理,确保项目需求沟通顺畅,UI设计协调到位,交付材料齐全,前端代码质量高。
  • 任务 (Task) :辅助项目经理进行需求沟通、UI设计沟通、交付材料整理、前端代码质量管理以及部分功能设计。
  • 行动 (Action) :积极参与需求和UI设计的沟通,整理和管理项目交付材料,进行代码审查和质量管理,并参与功能设计。
  • 结果 (Result) :成功辅助项目经理完成了项目的各项工作,提高了项目的开发效率和交付质量,确保了项目的顺利进行。

其实还不够,这些项目才是求职香饽饽

你可能不具备这些项目的实战经验,很多同学写了很多年管理系统,简单增删改查项目,如果不跳出这个圈子,很难在薪资上有非常大的突破!

  • 大厂 UI 组件库(Vue3)整体设计与开发实践(monorepo 架构)

  • 大厂业务 Hooks 库(React 18)整体设计与开发实践(从零到一的架构、规范流程)

  • 企业级脚手架工具开发实践

  • 企业级文档编辑器飞书文档开发实践

  • 前端性能、异常与行为监控

  • 3D 可视化数字孪生低代码实战 💥

    • 基于 cesium(arcGis、超图) 方案的 WebGIS 开发实践
    • 基于 openlayer、mapbox 开发
    • 基于 WebGL 3D 可视化开发实践

年包 50W+ 薪资长线规划

核心要素

  1. 全面的技术储备

    1. Vue 经验、React 经验,Vue3 + Typescript,React18(Hooks、Concurrent)【框架基础】
    2. 框架原理,React 生态库原理(React-Router、Redux)、Vue 生态库原理
    3. 工程化(构建工具:Webpack、Vite、Rspack、ESBuild、swc)
    4. CI/CD 自动化,自动化构建、自动化部署
    5. 基建能力(Node、命令行工具开发 Cli),UI 库、图表库、工具库
    6. 业务方面(管理系统、图表类),衍生 -> 可视化、编辑器、云表格、低代码、SaaS 产品、数字孪生、三维可视化
  2. 至少参加过两个以上大型项目,并主导过一个复杂项目

    1. 管理系统,(项目搭建、方案、技术栈、CI/CD 等等)
    2. 可视化、编辑器、云表格、低代码、SaaS 产品、数字孪生、三维可视化
  3. 面试表现好

    1. 个人介绍【 打个草稿 】,基本信息、技术栈、项目重难点

    2. STAR:

      • 遇到了什么问题 question,需求
      • 怎么评估解决方案,方案对比,方案落地 react 状态管理(redux、mobx、jotai、recoil)Vue3 -> Pinia
      • 方案落地
      • 反思,优化
    • 面试过程中,重点去复习只是重难点(v8 内存管理、Promise A+ 规范、事件循环、this、面向对象编程原型)
    • 技术储备,由你的项目经验体验,技术怎样在你的项目中落地的
  4. 学历

    1. 大专,尽快考一个本科证(年限去掉)
    2. 民办
    3. 内推,学历问题、工作经历的问题

补足短板

  • 项目简单,管理后台一做就是大半年,天天 CRUD

    • 看开源项目(react-hook-form ts 类型、hook 处理、状态管理、架构 Provider,keyPath)
    • 找一些不错的项目练手
    • 拿好的项目,学习完放在简历里, 可视化、编辑器、云表格、低代码、SaaS 产品、数字孪生、三维可视化
    • 1.自研:15K, 2.外包:20K ,这个火坑, 灰(供需决定)
  • 技术栈掌握不深不广,只会用 Vue2 (Vue3 + Typescript),React18(React stack reconciler)

  • 架构、方案设计没碰过

    • React,create-react-app、umi,没有真正从零到一去设计初始化过一个项目
    • Vue,Vue CLI,Vite/Webpack。Vue2 CLI 创出来项目 1. webpack、2.vite
  • 没有专精的技能或业务

    • 自驱 (假定自己是 Leader),项目的赢利点、商业价值【 可视化、编辑器、白板、团队基建、AI产品
    • 与生俱来有些东西,好奇心、自驱力、清晰规划
    • 我:管理平台,HPE(官网、后台管理),云表格(维格表、飞书云表格)、云编辑器(CKEditor 老【html string】)(语雀、【石墨文档】)

妙码学院——全程陪跑、督学、内推

⚠️ 暂不支持的文档区域,【文档小组件】

  • 跨端开发 Taro(Taro 编译器 compiler、运行时 runtime)、uniapp
  • 协同编辑器(文档类、画板类)wangEditor、CKEditor
  • 团队基建工程(UI 库、图表库、Cli -> 产生产物 npm 包)
  • 3D 可视化数字孪生 bigdata
  • 低代码平台

课程体系 2.0 升级,除了基础知识夯实,融入了更多项目实战内容,包含:

  • 企业级脚手架工具开发实践

  • 企业级文档编辑器飞书文档开发实践

  • 大厂 UI 组件库(Vue3)整体设计与开发实践

  • 大厂业务 Hooks 库(React 18)整体设计与开发实践

  • 埋点与数据监控平台实战

  • 3D 可视化数字孪生实战 💥

    • 基于 cesium 方案的 WebGIS 开发实践
    • 基于 WebGL 3D 可视化开发实践

不同阶段对前端人的硬性要求

以下是对您提供的内容进行权威和专业化改写的建议:

1~3年

在此阶段,重点在于评估个人的基础知识和热情。对前端基础、计算机原理、网络通信和算法等领域的要求较高。由于在此阶段难以评估业务深度,因此更多关注基础知识的掌握程度。

  • 关键在于通过学术教育或网络资源加强基础知识;
  • 在简历中以多种方式展示对前端的热情,展现个人潜力;
  • 积极探索前沿技术,关注国内外技术动态;
  • 尝试开发小型项目或参与社区开源项目;
  • 建立技术博客,以输出促进知识吸收。

3~5年

此阶段通常是向成为独立工程师发展的关键时期,避免重复使用有限的经验。

  • 关注社区中关于进阶的资料和路线,强化基础知识;

  • 深入掌握常用框架的高级用法,探索其原理;

  • 在业务开发中不仅完成功能,还需考虑项目结构设计、封装基础工具、设计和开发基础组件;

  • 思考提高团队效率的方法,例如:

    • 集成代码检验和风格统一插件(如 eslint、stylelint、prettier、spellcheck);
    • 从工程化角度提高本地开发效率,优化webpack构建,探索esbuild、vite等工具;
    • 对于多项目开发,整理差异和统一部分,建立内部脚手架以减少重复工作;
    • 尝试搭建CI/CD平台,维护公司内部的通用npm包;
    • 培养软技能,如沟通协作,协调各角色共同推进目标。

5年以上

进入此阶段,可能朝技术专家或管理方向发展。期望您能够独立负责高复杂度项目,突破关键技术难题。

  • 负责技术调研,关注行业趋势,选择最优技术方案,具备决策能力;
  • 拥有丰富的技术经验和技术储备,能够解决遇到的困难,并有自己的方法论;
  • 协助或主导业务目标制定,合理推动项目达成预期效果;
  • 是否具有团队领导经验,能够协调跨团队项目,处理团队成员情绪问题,解决技能分布不平衡等问题;
  • 打造技术氛围,促进团队共同成长。

职业规划指导

评论区选取三位同学互动,其他同学也可以联系咨询老师,文字方式提供辅导解答。

【未知组件reminder】