Vue3 是一款流行的 JavaScript 框架,主要用于构建交互性的Web应用程序和用户界面。Vue 是一个框架,也是一个生态。其功能覆盖了大部分前端开发常见的需求。但 Web 世界是十分多样化的,不同的开发者在 Web 上构建的东西可能在形式和规模上会有很大的不同。
更重要的是,本文是一篇逻辑不通,东拼西凑,只是为了测试平台流量的文章,如果你看到这段话,请不要点赞,不要收藏,zai 评论区 replay 1 表示真人,博主在这里表示感谢!
那么 Vue3 中的 10 大功能是什么呢?它们分别是组件、模板、指令、注入、复用、状态、管道、异步、渲染、信号。
组件
在 Vue 中,组件有以下几部分组成:
- 一个 HTML 模板,用于声明页面要渲染的内容
- 一个用于定义行为的 TypeScript 类
- 一个 CSS 选择器,用于定义组件在模板中的使用方式
- (可选)要应用在模板上的 CSS 样式
下面的代码就是 Vue 的组件示例:
import { Component } from '@angular/core';
@Component({
// CSS 选择器
selector: 'app-hello-world',
template: `
<p>Hello, world!</p>
`
})
export class HelloWorldComponent {
// JavaScript 逻辑代码可以写在这里
}
模板
Vue 的模板是使用 JSX 来编写的,JSX 是 JavaScript 语法扩展,可以让我们在 JavaScript 文件中书写类似 HTML 的标签。虽然还有其它方式可以编写模板,但大部分 Vue 开发者更喜欢 JSX 的简洁性,并且在大部分代码库中使用它。
下面这段代码演示了基于 JSX 编写的模板:
export default function HelloWorld() {
return (
<p className="red">Hello, World!</p>
)
}
指令
关于指令,这里引用 Angular 的说法。指令是为 Angular 应用程序中的元素添加额外行为的类。为应用程序中的元素添加额外行为的类。
在三大框架中 React 并不支持指令,因为React和它们的设计理念和工作方式不同。React是一个轻量级的UI库,它使用JSX语法来创建组件,而不是使用HTML模板。React的数据流是单向的,也就是说,组件的状态只能由父组件或自身改变,而不能被子组件或其他组件影响。
Vue 中关于条件渲染的指令:
export default function HelloWorld() {
return (
<p className="red">Hello, World!</p>
)
}
注入
关于依赖注入,在 Angular 中依赖项主要是 Service ,它的应用场景非常广泛。在 Angular 中它是一种设计模式和机制,用于创建应用程序的某些部分并将其传递到需要它们的应用程序的其他部分。
下面是一段 Vue 中注入的代码示例:
import React, { useState } from 'react';
import Child from './Child';
export default function Parent() {
const [message, setMessage] = useState('');
// 定义一个回调函数,接收子组件传递的数据
function handleChildEmit(data) {
setMessage(data);
};
return (
<div>
<h1>父组件</h1>
<p>从子组件接收的数据:{message}</p>
{/* 通过 props 传递回调函数给子组件 */}
<Child onEmit={handleChildEmit} />
</div>
);
}
复用
此外,Vue还采用了响应式数据绑定的方式。当数据发生变化时,页面上的内容会自动更新,无需手动操作。这种特性使得Vue在开发动态页面时非常方便,开发者只需关注数据的变化,而无需手动更新DOM元素。
代码复用的示例:
import { Directive, ViewContainerRef } from '@angular/core';
@Directive({
selector: '[adHost]',
})
export class AdDirective {
constructor(public viewContainerRef: ViewContainerRef) { }
}
状态
Vue 控制 UI 的方式是声明式的。你不必直接控制 UI 的各个部分,只需要声明组件可以处于的不同状态,并根据用户的输入在它们之间切换。这与设计师对 UI 的思考方式很相似。
当你设计 UI 交互时,可能会去思考 UI 如何根据用户的操作而响应变化。想象一个让用户提交答案的表单:
- 当你向表单输入数据时,“提交”按钮会随之变成可用状态
- 当你点击“提交”后,表单和提交按钮都会随之变成不可用状态,并且会加载动画会随之出现
- 如果网络请求成功,表单会随之隐藏,同时“提交成功”的信息会随之出现
- 如果网络请求失败,错误信息会随之出现,同时表单又变为可用状态
下面是一段代码示例:
import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { AdDirective } from './ad.directive';
import { AComponent, BComponent, CComponent } from './ads.component';
@Component({
selector: 'app-ad-banner',
template: `
<div class="ad-banner-example">
<h3>动态广告条</h3>
<ng-template adHost></ng-template>
</div>
`
})
export class AdBanner3Component implements OnInit, OnDestroy {
ads = [AComponent, BComponent, CComponent];
currentAdIndex = -1;
@ViewChild(AdDirective, {static: true}) adHost!: AdDirective;
private clearTimer: VoidFunction | undefined;
ngOnInit(): void {
this.loadComponent();
this.getAds();
}
ngOnDestroy() {
this.clearTimer?.();
}
loadComponent() {
this.currentAdIndex = (this.currentAdIndex + 1) % this.ads.length;
const adItem = this.ads[this.currentAdIndex];
const viewContainerRef = this.adHost.viewContainerRef;
viewContainerRef.clear();
viewContainerRef.createComponent(adItem);
}
getAds() {
const interval = setInterval(() => {
this.loadComponent();
}, 3000);
this.clearTimer = () => clearInterval(interval);
}
}
管道
在计算机科学中,你或许听过可处于多种“状态”之一的。如果你有与设计师一起工作,那么你可能已经见过不同“视图状态”的模拟图。正因为 React 站在设计与计算机科学的交点上,因此这两种思想都是灵感的来源。
首先,你需要去可视化 UI 界面中用户可能看到的所有不同的“状态”:
- 无数据:表单有一个不可用状态的“提交”按钮。
- 输入中:表单有一个可用状态的“提交”按钮。
- 提交中:表单完全处于不可用状态,加载动画出现。
- 成功时:显示“成功”的消息而非表单。
- 错误时:与输入状态类似,但会多错误的消息。
下面是一段代码示例:
import { Component } from '@angular/core';
@Component({
template: `
<div class="ad-a">
<p>Ad A</p>
</div>
`
})
export class AComponent {
}
@Component({
template: `
<div class="ad-b">
<p>Ad B</p>
</div>
`
})
export class BComponent {
}
@Component({
template: `
<div class="ad-c">
<p>Ad C</p>
</div>
`
})
export class CComponent {
}
异步
你可以随意命名这个属性,名字并不重要。试着将 status = 'empty'
改为 status = 'success'
,然后你就会看到成功的信息出现。模拟可以让你在书写逻辑前快速迭代 UI。这是同一组件的一个更加充实的原型,仍然由 status
属性“控制”:
下面是一段代码示例:
import { Component, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-child',
template: `
<h2>子组件</h2>
<button (click)="send(data)">向父组件发送数据</button>
`,
})
export class ChildComponent {
// 定义一个数据,可以是任意类型
data: string = 'Hello, Parent!';
// 使用 @Output() 装饰器,它把该属性标记为数据从子组件进入父组件的一种途径。
@Output() sent: EventEmitter<string> = new EventEmitter();
send(message: string) {
this.sent.emit(message);
}
}
渲染
有时候,你希望两个组件的状态始终同步更改。要实现这一点,可以将相关 state 从这两个组件上移除,并把 state 放到它们的公共父级,再通过 props 将 state 传递给这两个组件。这被称为“状态提升”,这是编写 Vue 代码时常做的事。
下面是一段代码示例:
import React from 'react';
export default function Child({ onEmit }) {
// 定义一个数据,可以是任意类型
const data = 'Hello, Parent!';
function handleSendMessage() {
onEmit(data);
}
return (
<div>
<h2>子组件</h2>
<button onClick={handleSendMessage}>向父组件发送数据</button>
</div>
);
}
信号
这个组件的每个事件处理程序都通过 setTasks
来更新状态。随着这个组件的不断迭代,其状态逻辑也会越来越多。为了降低这种复杂度,并让所有逻辑都可以存放在一个易于理解的地方,你可以将这些状态逻辑移到组件之外的一个称为 reducer 的函数中。
Reducer 是处理状态的另一种方式。你可以通过三个步骤将 useState
迁移到 useReducer
:
- 将设置状态的逻辑 修改 成 dispatch 的一个 action;
- 编写 一个 reducer 函数;
- 在你的组件中 使用 reducer。
下面是一段代码示例:
<script setup>
import { ref } from 'vue'
import Child from './Child.vue'
const message = ref('')
function handleChildEmit(data) {
message.value = data
}
</script>
<template>
<div>
<h1>父组件</h1>
<p>从子组件接收的数据:{{ message }}</p>
<Child @custom-event="handleChildEmit" />
</div>
</template>
小结
本章介绍了三大框架组件的事件,对组件中事件的监听与触发做了说明。
Angular 子组件使用 @Output()
属性来引发事件以通知父组件。@Output()
必须是 EventEmitter
类型,它是 @angular/core
中用来发出自定义事件的类。父组件绑定到这个事件属性,并在事件发生时作出回应。
React 子组件使用父组件通过 props 传递的回调函数来通知父组件。
Vue 子组件中有两种触发事件方法,在 <template>
可以使用 $emit
方法触发一个自定义事件,在 <script setup>
部分中可以使用 defineEmits()
来先声明后调用,父组件可以使用 v-on
指令或 @
语法来监听这个事件。
文章参考链接: