54 CHEN

后端工程师现代前端快速手册

大多数后端老人都会错过Node这一波的技术变化,还停留在JQuery的时代无法自拔,但实际上,前端发展已经日新月异,本文将从React和Vue的历史背景、基础原理、项目重要文件、常用知识等几个角度进行由潜入深的介绍,目的是使任何一位拥有后端开发经验的同学都可以快速上手前端开发,成为一名全栈开发人员。

历史背景

回首前端技术的历史,Node.js的崛起是一座里程碑。它不仅使JavaScript在服务器端大放异彩,也为前后端的深度融合创造了有利条件。

React,由Facebook团队打造,以其强调组件化开发的特点而备受推崇。回顾React的演进历程,其基础原理包括虚拟DOM、组件生命周期等核心概念。这些一起决定为何React成为当今前端领域的瑰宝。

Vue,由尤雨溪创造,以其简单易用的API和渐进式的特点而广受欢迎。我们将揭开Vue的面纱,了解其背后的设计哲学,以及与React的异同之处。Vue的灵活性和直观性如何带来开发的愉悦感,值得深入品味。

基础原理

早期的浏览器不支持JS模块,大型网页项目只能先合并成单一脚本再执行。Nodejs的模块系统是基于CommonJS规范实现的,而浏览器端的模块系统则是基于ES6模块规范实现的。CommonJS规范是为了JS在服务器端的模块化而制定的,而ES6模块规范则是为了JS在浏览器端的模块化而制定的。于是就有了打包工具,负责把JS打包成浏览器能识别的代码,比如Webpack、Rollup、Parcel等。我们常用的Vite使用了Rollup作为打包工具。而React的babel,则可以将JSX转换成相应标准的JS代码。

与JQuery时代的前端相比,虚拟DOM的出现使得现代前端的开发效率大大提高。虚拟DOM是React和Vue的核心,它是对真实DOM的抽象,是一个JS对象,用来描述真实DOM。虚拟DOM的出现使得前端开发者不再需要关心DOM操作,只需要关心数据的变化,虚拟DOM会自动帮我们更新DOM。

在Vue3中,其核心使用了AST抽象语法树,将模板转换成JS代码,再通过JS代码生成虚拟DOM。这样做的好处是,模板的编译工作可以提前完成,而不是在运行时完成,这样可以提高运行时的性能。AST之后,还有一个tranform过程,将虚拟DOM转换成真实DOM。而React则是直接将JSX转换成虚拟DOM,再通过虚拟DOM转换成真实DOM。稍微不同的是React有四大组件,相对应React是把VDOM区分成4种,与Vue的数量稍有不同。同时React有一个diff算法,用来比较新旧虚拟DOM的差异,从而减少DOM操作,提高性能。

项目重要文件

不论是Vue还是React都是Node项目,其项目结构都是类似的。我们以Vue3为例,介绍其项目结构。

├── public
│   ├── favicon.ico
│   └── index.html
├── src
│   ├── App.vue
│   ├── assets
│   │   └── logo.png
│   ├── components
│   │   └── HelloWorld.vue
│   └── main.js
├── babel.config.js
├── package-lock.json
├── package.json
└── vite.config.js

其中,public目录下的index.html是整个项目的入口文件,src目录下的main.js是整个项目的入口JS文件,App.vue是整个项目的根组件,其余的文件都是为了实现这个根组件而存在的。其中,assets目录下的文件是为了实现根组件的样式而存在的,components目录下的文件是为了实现根组件的功能而存在的。而babel.config.js、package-lock.json、package.json、vite.config.js这几个文件都是为了实现整个项目的打包而存在的。

其中要注意的是,根目录下的json文件往往都可以重新定义这些默认的文件位置,比如说把index.html放到root下。

js与ts

JavaScript 由 Netscape 公司的 Brendan Eich 在1995年创造。起初被设计为在浏览器中提供动态交互的脚本语言。 1997年,ECMAScript(简称 ES)被提出,目的是标准化 JavaScript 语言规范,确保各浏览器实现的兼容性。 JavaScript 的重要性在 Web 2.0 时代进一步凸显,Ajax 技术的兴起使得异步通信和动态页面更新成为可能。 Ryan Dahl 在2009年发布了 Node.js,使得 JavaScript 能够在服务器端运行,开发者可以使用同一语言构建整个应用栈。 Angular.js、React 和 Vue.js 等前端框架的出现使得 JavaScript 在构建复杂的单页应用(SPA)时更加高效和可维护。 ES6/ES2015 引入了类、箭头函数、模块化等新特性,进一步提高了 JavaScript 的开发体验。之后的年份也推出了 ES7、ES8 等版本,不断完善语言。

TypeScript 是由 Microsoft 开发的开源编程语言,首次公开亮相是在2012年。 TypeScript 是 JavaScript 的超集,意味着任何合法的 JavaScript 代码都是合法的 TypeScript 代码,但 TypeScript 提供了额外的静态类型系统和一些其他功能。 TypeScript 引入了静态类型检查,可以在开发阶段捕获一些潜在的错误,提高了代码的可维护性。 TypeScript 提供了对类、接口、模块等面向对象编程的支持,增强了代码的结构和可读性。 TypeScript 集成了丰富的工具支持,包括智能代码补全、跳转到定义、重构等,提高了开发效率。 TypeScript 在社区中得到了广泛的认可和支持,许多开源项目和框架都提供了 TypeScript 的声明文件。

npm, npx与yarn

npm 是 Node.js 的最常用的包管理工具,用于安装、卸载、更新和管理依赖包。另外还有npx yarn等工具,区别不大。

名称 创建时间 作用
npm 2010 年 1 月 Node.js 包管理器,用于安装、升级、删除和管理 Node.js 包。
npx 2017 年 7 月 Node 包执行工具,可用于运行临时的或者在项目中未安装的包。
Yarn 2016 年 10 月 快速、可靠、安全的 Node.js 依赖管理工具,与 npm 类似但有一些额外的特性。

Vue3常用知识

一个简单的Vue3模板示例

<template>
  <div>
    <h1>{{ greeting }}</h1>

    <p v-if="showMessage">Welcome to Vue 3!</p>

    <ul>
      <li v-for="item in items" :key="item.id">{{ item.name }}</li>
    </ul>

    <input v-model="inputValue" placeholder="Type something..." />

    <button @click="toggleMessage">Toggle Message</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      greeting: 'Hello, Vue 3!',
      showMessage: true,
      items: [
        { id: 1, name: 'Item 1' },
        { id: 2, name: 'Item 2' },
        { id: 3, name: 'Item 3' },
      ],
      inputValue: '',
    };
  },
  methods: {
    toggleMessage() {
      this.showMessage = !this.showMessage;
    },
  },
};
</script>

<style scoped>
h1 {
  color: blue;
}

ul {
  list-style-type: none;
  padding: 0;
}

li {
  margin-bottom: 5px;
}

input {
  margin-top: 10px;
  padding: 5px;
}
</style>

这个例子包括以下内容:

插值表达式: 使用 {{ greeting }} 在模板中插入变量的值。

条件渲染: 使用 v-if 根据条件来渲染元素,通过按钮点击切换显示消息。

列表渲染: 使用 v-for 遍历数组,并用 :key 提供唯一标识。

双向绑定: 使用 v-model 实现输入框的双向绑定。

事件处理: 使用 @click 处理按钮的点击事件。

样式作用域: 使用 scoped 属性,确保样式只在当前组件中生效。

每个Vue的模板都遵循这个规则,包括三个部分:模板、脚本和样式。其中,模板是用来定义组件的结构,脚本是用来定义组件的行为,样式是用来定义组件的样式。

Composition API

Vue 3 引入了 Composition API,提供了一种更灵活和可组合的方式来组织组件逻辑。使用 setup 函数,可以将组件的数据、方法等进行逻辑组织,取代了以前的 data、methods 等。

  <script>
import { ref, onMounted } from 'vue';

export default {
  setup() {
    const count = ref(0);

    const increment = () => {
      count.value++;
    };

    onMounted(() => {
      console.log('Component mounted');
    });

    return {
      count,
      increment,
    };
  },
};
</script>

新的响应式 API

Vue 3 引入了新的响应式 API,包括 ref、reactive、toRefs 等,提供更细粒度的响应式控制。

<script>
import { ref, reactive, toRefs } from 'vue';

export default {
  setup() {
    const count = ref(0);
    const state = reactive({
      message: 'Hello, Vue 3!',
    });

    const { message } = toRefs(state);

    return {
      count,
      message,
    };
  },
};
</script>
  1. ref: ref 用于创建一个包装过的响应式对象,将一个普通的 JavaScript 值转换为响应式数据。它返回一个带有 .value 属性的对象,访问和修改值时都需要使用 .value。
import { ref } from 'vue';

const count = ref(0);

console.log(count.value); // 访问值
count.value++; // 修改值
  1. reactive: reactive 用于创建一个包装过的响应式对象,将一个普通的 JavaScript 对象转换为响应式数据。与 ref 不同,reactive 可以包装整个对象,并且对象的所有属性都会变成响应式的。
import { reactive } from 'vue';

const state = reactive({
  count: 0,
  message: 'Hello, Vue 3!',
});

console.log(state.count); // 访问值
state.count++; // 修改值

模板语法

模板语法进行了一些改进,支持了一些新的特性,比如 v-if 和 v-for 支持了一起使用,以及 v-model 的语法糖。

<template>
  <div v-if="isVisible" v-for="item in list" :key="item.id">
    {{ item.name }}
  </div>
</template>

在表单元素上使用 v-model 可以轻松地实现双向绑定,将表单输入和组件的数据进行关联。这使得用户输入的变化会同步更新到组件的数据,反之亦然。

<template>
  <div>
    <input v-model="message" placeholder="Type something..." />
    <p>You typed: {{ message }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: '',
    };
  },
};
</script>

生命周期钩子

Vue 3 引入了一些新的生命周期钩子,例如 beforeUnmount,以提供更精细的控制。

<script>
export default {
  beforeUnmount() {
    console.log('Component will be unmounted');
  },
};
</script>

以下是常用的生命周期钩子:

名字 作用
beforeCreate 在实例被创建之前,完成了数据观测和初始化事件等配置。
created 在实例被创建后,完成了数据观测、属性和方法的运算以及 watch/event 事件的配置。
beforeMount 在挂载开始之前被调用:相关的 render 函数首次被调用。
mounted 在挂载完成之后被调用,这时实例已经完成了 DOM 的挂载。
beforeUpdate 在数据更新之前被调用,发生在虚拟 DOM 重新渲染和打补丁的前后。
updated 在由于数据更改导致的虚拟 DOM 重新渲染和打补丁后调用。
beforeUnmount 在卸载之前调用。在这一步,实例仍然完全可用。
unmounted 在卸载完成之后调用。这个时候,实例的所有指令都已经解绑,所有事件监听器都已经移除。
errorCaptured 会在子孙组件抛出错误后被调用。它会收到三个参数:错误对象、发生错误的组件实例、错误来源字符串。
onRenderTriggered 在渲染触发 Suspense 时调用。
onRenderTracked 在渲染跟踪 Suspense 时调用。

自定义模板

在 Vue 中,你可以通过使用 <template> 元素来引用一个自定义的模板。这通常用于在组件中定义多行的 HTML 模板,以提高可读性。以下是一个简单的示例:

<template>
  <div>
    <h1>Hello, Vue!</h1>
    <custom-template></custom-template>
  </div>
</template>

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

export default {
  components: {
    CustomTemplate,
  },
};
</script>

在上述示例中,<custom-template> 元素用于引用名为 CustomTemplate 的组件。你需要确保在 components 选项中注册了这个组件,以便 Vue 能够正确渲染它。

然后,在 CustomTemplate.vue 文件中定义你的自定义模板:

<template>
  <div>
    <p>This is a custom template.</p>
  </div>
</template>

<script>
export default {
  // 组件的逻辑代码
};
</script>

这样,你就可以在主组件中使用 <custom-template> 来引用你的自定义模板了。

References

https://vuejs.org/

https://react.dev/

https://github.com/vuejs/core

https://github.com/facebook/react

#Vue #React #Node