Vue基础

知识

  • HTML(结构):超文本标记语言(Hyper Text Markup Language),决定网页的结构和内容
  • CSS(表现):层叠样式表(Cascading Style Sheets),设定网页的表现样式。

CSS(层叠样式表)是一门标记语言,用于描述HTML文档的样式。它没有变量、函数等编程语言的特性,这给样式的编写和维护带来了一些挑战。为了解决这些问题,前端开发人员引入了CSS预处理器,它们为CSS增加了编程语言的一些特性,如变量、嵌套、混合(mixins)等,提高了样式代码的可维护性和开发效率。

CSS预处理器简介

CSS预处理器是一种扩展了CSS语言的工具,允许开发者使用更强大的语法,然后将其编译成标准的CSS。常见的CSS预处理器包括Sass、Less和Stylus。

Sass 示例

变量

Sass允许使用变量来存储CSS属性值,这使得我们可以在整个样式表中重复使用这些值。

基于Ruby ,通过服务端处理,功能强大。解析效率高。

Sass 代码(SCSS 语法):

1
2
3
4
5
6
7
$primary-color: #3498db;
$font-stack: Helvetica, sans-serif;

body {
font: 100% $font-stack;
color: $primary-color;
}

编译后的 CSS 代码:

1
2
3
4
body {
font: 100% Helvetica, sans-serif;
color: #3498db;
}

嵌套

Sass允许嵌套规则,这使得层级结构清晰明了,减少了重复的选择器定义。

Sass 代码(SCSS 语法):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
nav {
ul {
margin: 0;
padding: 0;
list-style: none;
}

li {
display: inline-block;
}

a {
display: block;
padding: 6px 12px;
text-decoration: none;
}
}

编译后的 CSS 代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
nav ul {
margin: 0;
padding: 0;
list-style: none;
}

nav li {
display: inline-block;
}

nav a {
display: block;
padding: 6px 12px;
text-decoration: none;
}

混合(Mixins)

Sass混合允许定义可以重复使用的CSS片段,这使得样式复用更加方便。

Sass 代码(SCSS 语法):

1
2
3
4
5
6
7
8
9
10
@mixin border-radius($radius) 
{
-webkit-border-radius: $radius;
-moz-border-radius: $radius;
border-radius: $radius;
}

.box {
@include border-radius(10px);
}

编译后的 CSS 代码:

1
2
3
4
5
.box {
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
}

Less 示例

LESS:基于NodeJS,通过客户端处理,使用简单。功能比SASS简单,解析效率也低于SASS.

变量

Less也允许使用变量来存储CSS属性值。

Less 代码:

1
2
3
4
5
@primary-color: #4D926F;

h1 {
color: @primary-color;
}

编译后的 CSS 代码:

1
2
3
h1 {
color: #4D926F;
}

嵌套

Less同样允许嵌套规则,使得层级结构更清晰。

Less 代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
nav {
ul {
margin: 0;
padding: 0;
list-style: none;
}

li {
display: inline-block;
}

a {
display: block;
padding: 6px 12px;
text-decoration: none;
}
}

编译后的 CSS 代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
nav ul {
margin: 0;
padding: 0;
list-style: none;
}

nav li {
display: inline-block;
}

nav a {
display: block;
padding: 6px 12px;
text-decoration: none;
}

混合(Mixins)

Less混合允许定义可以重复使用的CSS片段。

Less 代码:

1
2
3
4
5
6
7
8
9
.border-radius(@radius) {
-webkit-border-radius: @radius;
-moz-border-radius: @radius;
border-radius: @radius;
}

.box {
.border-radius(10px);
}

编译后的 CSS 代码:

1
2
3
4
5
.box {
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
}

总结

CSS预处理器如Sass和Less,通过引入变量、嵌套、混合等编程语言特性,大大增强了CSS的表达能力和复用性。这些特性不仅减少了冗余代码,还提高了代码的可维护性和可读性,使前端开发更加高效和灵活。

  • JavaScript(行为):是一种弱类型脚本语言,其源码不需经过编译,而是由浏览器解释运行,用于控制网页的行为

一些框架

JQuery

JQuery 是一个广泛使用的 JavaScript 库,旨在简化 HTML 文档遍历和操作、事件处理、动画以及 Ajax 交互。

  • 优点:
    • 简化 DOM 操作:JQuery 提供了简洁的 API 来操作 DOM,避免了大量的原生 JavaScript 代码。
    • 兼容性:JQuery 能很好地兼容 IE6、7、8 等老旧浏览器。
    • 插件丰富:有大量的现成插件可以使用,满足各种功能需求。
  • 缺点:
    • 性能问题:由于频繁的 DOM 操作,可能会导致前端性能问题,特别是在处理大量数据时。
    • 渐渐过时:随着现代浏览器的发展和 ES6 标准的普及,许多原本需要 JQuery 实现的功能可以用原生 JavaScript 实现。

Angular

Angular 是由 Google 维护的前端框架,采用 TypeScript 语言开发。

  • 特点:
    • MVC 模式:将后端的 MVC(Model-View-Controller)模式搬到了前端,支持模块化开发。
    • 模块化:提供了依赖注入(Dependency Injection)和模块化机制,使得代码更易维护和测试。
    • TypeScript:与微软合作,采用 TypeScript 开发,增强了代码的可读性和可维护性。
  • 缺点:
    • 学习曲线:对前端程序员不太友好,尤其是那些没有 TypeScript 和模块化开发经验的人。
    • 版本迭代:版本更新较快且变化大,例如从 AngularJS(1.x)到 Angular(2+),几乎是两个完全不同的框架,导致开发者需要重新学习。

React

React 是由 Facebook 开发的高性能 JavaScript 前端库,专注于构建用户界面。

  • 特点:
    • 虚拟 DOM:在内存中模拟 DOM 操作,通过差分计算将变更应用到真实 DOM,有效提升渲染性能。
    • 组件化:以组件为单位构建 UI,使代码更易于复用和维护。
    • 单向数据流:数据在组件之间单向流动,使得数据管理更加清晰和可控。
  • 缺点:
    • 学习难度:需要学习 JSX(JavaScript XML)语法,这是一种在 JavaScript 中嵌入 HTML 的语法。
    • 生态系统复杂:React 只是视图层解决方案,需要结合其他库(如 Redux、Router 等)来实现完整的功能,增加了学习成本。

Vue

Vue 是一个渐进式 JavaScript 框架,由尤雨溪开发。

  • 特点:
    • 渐进式:可以逐步引入 Vue 的特性,不需要一次性全部使用,适合现有项目的渐进式改造。
    • 结合优点:综合了 Angular 的模块化开发和 React 的虚拟 DOM 优点。
    • 简单易学:相比于 Angular 和 React,Vue 的 API 更加简洁,易于上手。
  • 优点:
    • 灵活性:可以用作简单的视图层库,也可以构建复杂的单页应用(SPA)。
    • 文档完善:提供了详细的官方文档和教程,帮助开发者快速上手。

Axios

Axios 是一个基于 Promise 的 HTTP 库,用于浏览器和 Node.js 中发送 HTTP 请求。

  • 特点:
    • 简单易用:API 设计简洁,易于发送 GET、POST 请求。
    • 支持 Promise:基于 Promise 设计,支持 async/await 语法,使异步代码更简洁。
    • 拦截器:可以在请求或响应被处理之前拦截它们,进行统一处理。
  • 用途:
    • 数据交互:用于前端与后端服务器的数据交互,发送请求、接收响应。
    • 替代方案:在 Vue 项目中,通常用 Axios 代替 Vue 的内置 HTTP 能力(Vue 本身不具备通信能力),也可以用 JQuery 的 AJAX 功能。

概述:

关注点分离原则(Separation of Concerns, SoC)是一种设计原则,旨在将软件系统的不同功能分离开来,使其各自独立且更易于理解、开发和维护。Vue.js 遵循这一原则,其核心库只关注视图层,允许开发者使用第三方库或现有项目来处理其他方面的需求。这种设计提高了代码的可维护性和可扩展性。

Vue.js 与关注点分离原则

在 Vue.js 中,不同的任务和职责被分解为独立的模块或库,这些模块各自专注于特定的功能。例如:

  1. 视图层

    • HTML + CSS + JS:这些技术用于定义和控制用户界面的结构、样式和行为。在 Vue.js 中,模板语言、指令和组件系统使得构建动态、响应式的用户界面变得简单和直观。
  2. 网络通信

    • axios:这是一个基于 Promise 的 HTTP 客户端,用于浏览器和 Node.js。它可以用来发送异步 HTTP 请求,从服务器获取数据或将数据发送到服务器。使用 axios 可以轻松地处理 AJAX 请求,与 Vue.js 集成良好。

      示例:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      import axios from 'axios';

      axios.get('/api/data')
      .then(response => {
      console.log(response.data);
      })
      .catch(error => {
      console.error('Error fetching data:', error);
      });
  3. 页面跳转

    • vue-router:这是 Vue.js 官方的路由管理器,用于在单页面应用(SPA)中实现页面导航和路由。它允许开发者定义不同的路由,并通过路由映射到不同的组件,提供了一个灵活且强大的导航解决方案。

      示例:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      import { createRouter, createWebHistory } from 'vue-router';
      import Home from './components/Home.vue';
      import About from './components/About.vue';

      const routes = [
      { path: '/', component: Home },
      { path: '/about', component: About }
      ];

      const router = createRouter({
      history: createWebHistory(),
      routes
      });

      const app = createApp(App);
      app.use(router);
      app.mount('#app');
  4. 状态管理

    • vuex:这是一个专为 Vue.js 应用程序设计的状态管理模式。它集中管理应用中的所有状态,并通过规则确保状态的可预测性和可维护性。使用 vuex,可以更好地管理复杂的应用状态,特别是在多个组件需要共享状态时。

      示例:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      import { createStore } from 'vuex';

      const store = createStore({
      state() {
      return {
      count: 0
      };
      },
      mutations: {
      increment(state) {
      state.count++;
      }
      }
      });

      const app = createApp(App);
      app.use(store);
      app.mount('#app');
  5. Vue UI 库

    • ICEElement UI:这些是基于 Vue.js 的 UI 组件库,提供了一系列的现成组件,用于快速构建美观且一致的用户界面。它们包含了按钮、表单、对话框等常见的 UI 组件,可以显著加快开发速度。

      示例(使用 Element UI):

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      <template>
      <el-button @click="handleClick">Click me</el-button>
      </template>

      <script>
      import { ElButton } from 'element-plus';

      export default {
      components: {
      ElButton
      },
      methods: {
      handleClick() {
      this.$message('Button clicked!');
      }
      }
      }
      </script>

第一个Vue程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
<script src="https://cdn.staticfile.net/vue/3.2.36/vue.global.min.js"></script>
</head>
<body>
<div id="hello-vue" class="demo">
{{ message }}
</div>

<script>
const HelloVueApp =
{
data() {
return {
message: 'Hello Vue!!'
}
}
}

Vue.createApp(HelloVueApp).mount('#hello-vue')
</script>
</body>
</html>

这段代码示例展示了如何使用 Vue.js 创建一个简单的应用程序。以下是对代码的逐步解释:

  1. HTML 基本结构

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
    <script src="https://cdn.staticfile.net/vue/3.2.36/vue.global.min.js"></script>
    </head>
    <body>
    <div id="hello-vue" class="demo">
    {{ message }}
    </div>
    • 标准的 HTML 文档结构,包含 <!DOCTYPE html> 声明。
    • <head> 部分定义了文档的头部信息,包括字符

集设置、标题和外部脚本的引入。

  • 引入了 Vue.js 的 CDN 脚本文件。
    • <body> 部分,定义了一个具有 id="hello-vue"div 元素,该元素将作为 Vue 应用程序的挂载点。
  1. Vue 应用程序定义

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <script>
    const HelloVueApp =
    {
    data() {
    return {
    message: 'Hello Vue!!'
    }
    }
    }

    Vue.createApp(HelloVueApp).mount('#hello-vue')
    </script>
    • 定义了一个 Vue 应用程序对象 HelloVueApp
    • data() 函数返回一个对象,其中包含一个 message 属性,其值为 'Hello Vue!!'。这个 data 对象中的属性将成为 Vue 应用的响应式数据。
    • Vue.createApp(HelloVueApp) 创建一个新的 Vue 应用实例,并将其挂载到 id="hello-vue" 的 DOM 元素上。
  2. Vue 数据绑定

    1
    2
    3
    <div id="hello-vue" class="demo">
    {{ message }}
    </div>
    • 使用双大括号 {{ }} 语法实现 Vue 的数据绑定,将 message 的值显示在 div 元素中。
    • 当 Vue 应用挂载后,message 属性的值 'Hello Vue!!' 会替换双大括号中的内容,动态更新页面显示的内容。

详细解释

  • 引入 Vue.js:通过 <script> 标签引入 Vue.js,这里使用的是 Vue 3.2.36 版本的 CDN。
  • Vue 应用实例
    • const HelloVueApp = { ... } 定义了一个 Vue 应用对象。这个对象包含一个 data 函数,返回一个包含 message 属性的对象。
    • Vue.createApp(HelloVueApp).mount('#hello-vue') 创建并挂载 Vue 应用实例到 id="hello-vue" 的元素上。
  • 数据绑定{{ message }} 是 Vue 的插值语法,用于绑定并显示 message 属性的值。

Vue 的优点

  • 响应式数据绑定:数据和视图自动同步,开发者无需手动更新 DOM。
  • 组件化开发:可以将页面分解为可复用的组件,方便维护和扩展。
  • 易于上手:简单易用的 API,使得新手也能快速掌握。

MVVM

什么是 MVVM

MVVM(Model-View-ViewModel)是一种软件设计模式,旨在简化用户界面的事件驱动编程。

MVVM 源自于经典的 MVC(Model-View-Controller)模式,但在其基础上进行了改进。MVVM 的核心是 ViewModel 层,其主要职责是将 Model 层的数据转换为更易于管理和使用的形式,同时实现视图层的双向数据绑定。

MVVM 模式的三个部分

  1. Model(模型)
    • 表示应用程序的数据和业务逻辑。
    • 负责处理数据存储和业务规则的实现。
    • 不依赖于视图或视图模型。
  2. View(视图)
    • 表示用户界面,负责呈现数据。
    • 通过数据绑定从 ViewModel 获取数据。
    • 包含 UI 元素和布局,但不包含业务逻辑。
  3. ViewModel(视图模型)
    • 连接 Model 和 View。
    • 负责数据的转换和准备,使其适合在 View 中显示。
    • 实现视图和数据之间的双向绑定,响应视图中的用户交互并更新 Model。

MVVM 模式的优点

  • 双向数据绑定:视图与视图模型之间的双向数据绑定使得数据的变化能够自动更新视图,视图的变化也能自动更新数据。
  • 清晰的分层结构:将业务逻辑和用户界面分离,提高了代码的可维护性和可测试性。
  • 模块化:开发人员可以专注于不同的部分,UI 开发人员可以专注于 View,逻辑开发人员可以专注于 ViewModel 和 Model。

MVVM 工作流程

  1. Model 通过接口提供数据,并可能包含数据的处理逻辑。
  2. ViewModel 接收 Model 的数据并进行处理,然后通过绑定的方式提供给 View。
  3. View 通过数据绑定机制,自动从 ViewModel 获取数据并显示给用户。
  4. 用户在 View 中进行的操作会触发 ViewModel 中的相应逻辑,进而更新 Model。
  5. Model 数据发生变化时,ViewModel 会捕获到这些变化并自动更新 View。

MVVM 示例框架

  • Vue.js:一个渐进式 JavaScript 框架,专注于构建用户界面。Vue.js 通过其双向数据绑定和组件化的特性,完美地实现了 MVVM 模式。
  • Angular:Google 开发的一个强大的前端框架。Angular 使用 TypeScript 语言,支持模块化开发,并通过其强大的数据绑定机制和依赖注入系统实现了 MVVM 模式。

例子

以下是一个简单的 Vue.js 示例,展示了如何实现 MVVM 模式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue.js MVVM 示例</title>
<script src="https://cdn.staticfile.net/vue/3.2.36/vue.global.min.js"></script>
</head>
<body>
<div id="app">
<input v-model="message" placeholder="输入一些文字">
<p>{{ message }}</p>
</div>

<script>
const App = {
data() {
return {
message: 'Hello Vue!'
}
}
}

Vue.createApp(App).mount('#app')
</script>
</body>
</html>

在这个示例中:

  • Model:Vue 实例中的 message 数据。
  • View:HTML 中的输入框和段落元素。
  • ViewModel:Vue 实例中的 data 和双向绑定的 v-model 指令。

用户在输入框中输入文字,v-model 指令会将输入的内容绑定到 message 数据,message 数据的变化会自动更新段落元素中的内容,实现了双向数据绑定。

深入剖析MVVM模式:

从 MVVM 深入剖析

MVVM(Model-View-ViewModel) 是一种设计模式,旨在简化用户界面的事件驱动编程。它将应用程序分为三个部分:Model、View 和 ViewModel。以下是对该设计模式的深入剖析,以及如何在 Vue.js 中实现这一模式的具体示例。

1. Model(模型)

Model 代表应用程序的数据和业务逻辑。它包含了纯粹的数据结构和业务逻辑,不依赖于视图或视图模型。

在 Vue.js 中,Model 通常是由 Vue 实例中的数据对象表示。在上面的示例中,message 就是 Model 的一部分:

1
2
3
4
5
data() {
return {
message: 'Hello Vue!'
}
}

2. View(视图)

View 是用户界面,负责展示数据。它通过绑定数据和事件,显示 Model 中的数据,并响应用户输入。

在 Vue.js 中,View 是由模板(HTML)表示的。在上面的示例中,HTML 代码中的 <input><p> 元素就是视图的一部分:

1
2
<input v-model="message" placeholder="输入一些文字">
<p>{{ message }}</p>
  • <input v-model="message"> 使用了 v-model 指令,它实现了双向数据绑定,将输入框的值绑定到 message
  • <p>{{ message }}</p> 使用了 Mustache 语法(双花括号),它将 message 的值展示在段落中。

3. ViewModel(视图模型)

ViewModel 是连接 Model 和 View 的桥梁。它负责将 Model 中的数据转换为 View 可以使用的格式,并处理 View 中的用户交互。

在 Vue.js 中,ViewModel 是由 Vue 实例表示的。在上面的示例中,Vue 实例既是 Model 的一部分,也是 ViewModel 的一部分:

1
2
3
4
5
6
7
8
9
const App = {
data() {
return {
message: 'Hello Vue!'
}
}
}

Vue.createApp(App).mount('#app')

MVVM 的核心:双向数据绑定

Vue.js 通过 v-model 实现了双向数据绑定,这意味着 Model 和 View 之间的同步是自动的。当 Model 中的数据发生变化时,View 会自动更新;当用户在 View 中输入新的数据时,Model 也会自动更新。这是 MVVM 模式的核心优势之一,简化了开发和维护的工作。

深入理解 MVVM 的工作流程

  1. 数据初始化:当 Vue 应用程序实例被创建时,data 函数会被调用,并返回一个包含初始数据的对象。这些数据会被 Vue 的响应式系统接管,使得数据的变化能够被追踪。

  2. 模板编译:Vue 编译模板,将其转换为渲染函数。渲染函数会生成虚拟 DOM 节点,并根据数据的变化更新虚拟 DOM。

  3. 数据绑定v-model 指令实现了双向数据绑定。输入框的值会被绑定到 message,并且 message 的值也会被展示在段落元素中。

  4. 事件监听:Vue 实例会监听数据的变化。当 message 发生变化时,Vue 的响应式系统会通知所有依赖 message 的视图更新。

  5. DOM 更新:渲染函数会生成新的虚拟 DOM 节点,并将其与旧的虚拟 DOM 节点进行对比(即虚拟 DOM 的 diff 算法)。最终,Vue 将最小化的变化应用到实际的 DOM 上,确保视图与数据保持同步。

代码解析

我们再来看一下完整的代码,并结合上面的分析进行详细解释:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue.js MVVM 示例</title>
<script src="https://cdn.staticfile.net/vue/3.2.36/vue.global.min.js"></script>
</head>
<body>
<div id="app">
<input v-model="message" placeholder="输入一些文字">
<p>{{ message }}</p>
</div>

<script>
const App = {
data() {
return {
message: 'Hello Vue!'
}
}
}

Vue.createApp(App).mount('#app')
</script>
</body>
</html>
  • <input v-model="message">:这个指令使得输入框和 message 数据之间实现双向绑定。任何对输入框的改变都会自动更新 message,反之亦然。
  • <p>{{ message }}</p>:这个表达式将 message 的当前值显示在段落中。每当 message 发生变化时,段落中的内容也会自动更新。
  • Vue.createApp(App).mount('#app'):这行代码创建一个 Vue 应用实例,并将其挂载到 #app 元素上,使得 Vue 应用生效。

通过这种方式,Vue.js 实现了 MVVM 模式,使得数据和视图的管理变得更加简洁和高效。这种模式不仅提高了开发效率,还使得代码更易于维护和扩展。


MVVM 模式的详细解释

1. View(视图层)

View是用户界面,主要由HTML和CSS构建。View的主要任务是展示数据,并与用户交互。视图层的设计可以使用各种前端框架和模板语言,例如:

  • FreeMarker:一种Java模板引擎,用于生成HTML页面。
  • Thymeleaf:一种现代的Java模板引擎,用于Spring应用。
  • Vue.js、AngularJS、EJS:这些是前端框架或模板引擎,用于构建动态的、交互式的用户界面。

在MVVM模式中,View通过绑定ViewModel来获取数据,并自动更新视图,使得视图层和数据层的耦合度降低。

2. Model(数据层)

Model是指数据模型,负责处理业务逻辑和数据操作。它主要围绕数据库系统进行,处理从数据库中读取、更新、删除数据的操作。Model层的任务包括:

  • 业务逻辑处理:实现具体的业务需求。
  • 数据操作:通过数据库操作接口(如SQL、ORM)进行数据的CRUD(创建、读取、更新、删除)。

Model层需要与前端约定统一的接口规则,以便前后端能够顺畅地进行数据交换。

3. ViewModel(视图数据层)

ViewModel是由前端开发人员创建和维护的视图数据层,负责处理View和Model之间的数据交互。ViewModel的主要任务是:

  • 数据转换:将从Model获取的数据转换为View层需要的格式。
  • 二次封装:将数据封装成视图模型,包含视图的状态和行为。

ViewModel包括以下两部分:

  • 视图状态:定义视图的外观和内容。例如,哪些部分需要显示,哪些部分需要隐藏。
  • 视图行为:定义视图的交互逻辑。例如,点击按钮时触发的事件,页面加载时的初始化操作。

通过ViewModel,前端开发者可以专注于处理和维护视图数据,更新数据后,视图会自动更新,而不需要直接操作DOM。这种方式提高了开发效率和代码可维护性。

通过这种方式,视图层和数据层实现了分离,前端开发者只需要维护ViewModel,数据的更新会自动反映到视图上,简化了开发和维护过程。


特点

MVVM(Model-View-ViewModel)模式和MVC(Model-View-Controller)模式的主要目的是分离视图(View)和模型(Model)。

1. 低耦合

低耦合意味着视图(View)和模型(Model)之间的依赖关系尽可能减少,从而使得它们能够独立变化和修改。

  • View和Model独立变化:View和Model之间通过ViewModel进行通信。当View发生变化时,Model不需要进行任何改变,反之亦然。这种独立性使得界面设计和业务逻辑可以分别进行修改和更新而不互相影响。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    const ViewModel = {
    data() {
    return {
    message: 'Hello World'
    }
    }
    }

    Vue.createApp(ViewModel).mount('#app')

2. 可复用

可复用是指可以将某些通用的视图逻辑放在ViewModel中,使得多个视图可以重用这些逻辑。

  • 视图逻辑的复用:假设你有多个视图都需要显示用户的信息,你可以将显示用户信息的逻辑放在一个ViewModel中,然后多个视图都可以绑定到这个ViewModel,从而重用这段视图逻辑。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    const UserViewModel = {
    data() {
    return {
    user: {
    name: 'John Doe',
    age: 30
    }
    }
    }
    }

    Vue.createApp(UserViewModel).mount('#userView1')
    Vue.createApp(UserViewModel).mount('#userView2')

3. 独立开发

独立开发使得开发人员和设计人员可以分别专注于不同的部分,提高了开发效率。

  • 开发人员专注于业务逻辑和数据:开发人员可以专注于编写ViewModel和Model,处理业务逻辑和数据交互,而不需要关心视图的具体实现。
  • 设计人员专注于页面设计:设计人员可以专注于设计和实现视图(HTML/CSS),确保用户界面的美观和可用性。

4. 可测试

可测试是指因为ViewModel包含了大部分的视图逻辑,使得测试工作可以主要针对ViewModel进行,而不需要复杂的UI操作。

  • 测试ViewModel:ViewModel包含了视图的逻辑,因此可以对其进行单元测试,验证其逻辑的正确性,而不需要涉及到复杂的UI交互。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    const ViewModel = {
    data() {
    return {
    message: 'Hello Test'
    }
    },
    methods: {
    updateMessage(newMessage) {
    this.message = newMessage;
    }
    }
    }

    // 可以对ViewModel进行单元测试
    let vm = ViewModel.data();
    vm.updateMessage('Hello World');
    console.assert(vm.message === 'Hello World');

总结

  • 低耦合:通过ViewModel中介,视图和模型可以独立变化。
  • 可复用:视图逻辑可以在多个视图之间重用。
  • 独立开发:开发人员和设计人员可以分别专注于自己的工作领域。
  • 可测试:可以对ViewModel进行单元测试,简化了界面测试的复杂性。

显然,MVVM模式有效提高了代码的可维护性、开发效率和测试效率,是现代前端开发中广泛使用的一种设计模式。

了解了这些,再回来看Vue,也许就会大彻大悟

MVVM 模式的实现者:Vue.js

在MVVM(Model-View-ViewModel)模式中,Vue.js作为ViewModel的实现者,起到了连接视图层(View)和数据层(Model)的关键作用。让我们详细解释每个组件以及Vue.js是如何实现这些组件之间的互动的。

1. Model(模型层)

模型层是指应用中的数据和业务逻辑。在Vue.js中,模型层通常表示为JavaScript对象或从服务器获取的数据。例如:

1
2
3
4
const model = {
name: "Alice",
age: 30
};

2. View(视图层)

视图层是用户界面,主要由HTML和CSS构建。在Vue.js中,视图层可以使用模板语法来绑定数据。例如:

1
2
3
4
<div id="app">
<p>{{ name }}</p>
<p>{{ age }}</p>
</div>

3. ViewModel(视图模型层)

ViewModel是MVVM模式中的核心组件,负责连接Model和View。Vue.js的实例(Vue实例)就充当了ViewModel的角色。它实现了数据绑定和DOM监听,确保视图和数据的一致性。

在Vue.js中,ViewModel通过以下机制实现:

  • 数据绑定:通过Vue的模板语法(如{{ }})和指令(如v-model),可以轻松地将数据绑定到视图。
  • 观察者模式:Vue.js使用观察者模式来检测数据的变化,并自动更新视图。
  • 事件监听:Vue.js可以监听用户输入事件,并相应地更新数据。

Vue.js 的实现机制

  1. 数据和视图的双向绑定

在MVVM架构中,数据和视图之间的通信必须通过ViewModel。Vue.js通过双向绑定实现了这一点:

  • 数据变化影响视图:当数据(Model)发生变化时,Vue.js会自动更新视图(DOM)中的相应部分。
  • 视图变化影响数据:当用户在视图中进行交互(如输入文本)时,Vue.js会自动更新数据(Model)。
  1. Observer 观察者模式

Vue.js实现了一个观察者模式,用于观察数据的变化并更新视图。具体来说,Vue.js会:

  • 监视数据对象:Vue.js会遍历数据对象的每个属性,并为每个属性创建一个观察者(Observer)。
  • 更新视图:当数据发生变化时,观察者会通知相关的视图组件进行更新。
  1. 事件监听

Vue.js能够监听用户在视图中的操作,并相应地更新数据。例如,使用v-model指令可以将表单输入元素与数据进行双向绑定:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<div id="app">
<input v-model="name">
<p>{{ name }}</p>
</div>

<script>
const app = Vue.createApp({
data() {
return {
name: 'Alice'
}
}
});

app.mount('#app');
</script>

在这个例子中,当用户在输入框中输入文字时,name数据会自动更新,进而导致视图中显示的{{ name }}也会更新。

总结

Vue.js作为MVVM模式的实现者,通过数据绑定、观察者模式和事件监听,实现了视图层(View)和模型层(Model)之间的解耦。Vue.js的核心功能就是实现了DOM监听与数据绑定,使得前端开发者可以高效地构建和维护复杂的用户界面,而无需手动操作DOM。通过这种方式,Vue.js提高了代码的可维护性和开发效率,是现代前端开发中非常重要的工具。

数据绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>

</head>
<body>

<!--view层,模板-->
<div id="app">
{{message}}
</div>

<!--1.导入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script type="text/javascript">
var vm = new Vue({
el:"#app",
/*Model:数据*/
data:{
message:"hello,vue!"
}
});
</script>
</body>
</html>

解释Vue.js的基本示例

这个示例展示了如何使用Vue.js框架创建一个简单的应用程序。我们会一步一步地解释代码的每一部分。

HTML 部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>

<!--view层,模板-->
<div id="app">
{{message}}
</div>

<!--1.导入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script type="text/javascript">
var vm = new Vue({
el:"#app",
/*Model:数据*/
data:{
message:"hello,vue!"
}
});
</script>
</body>
</html>

详细解释

  1. HTML基本结构
1
2
3
4
5
6
7
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>

这部分是HTML的基础结构,定义了文档的类型(HTML5)和文档的语言(英语)。<meta charset="UTF-8">指定文档的字符编码为UTF-8,保证特殊字符的正确显示。

  1. 视图层(View)
1
2
3
<div id="app">
{{message}}
</div>

这个<div>元素是视图层,定义了一个ID为app的容器,里面包含一个插值表达式{{message}}。Vue.js会自动将message的值插入到这个位置。

  1. 导入Vue.js
1
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>

这一行通过CDN导入了Vue.js库的2.5.21版本。Vue.js是一个用于构建用户界面的渐进式框架。

  1. 初始化Vue实例
1
2
3
4
5
6
7
8
9
<script type="text/javascript">
var vm = new Vue({
el:"#app",
/*Model:数据*/
data:{
message:"hello,vue!"
}
});
</script>

这段脚本代码在浏览器加载完成后执行,主要部分是初始化一个Vue实例(var vm = new Vue({ ... }))。让我们深入了解一下它的每个部分:

  • el属性

    1
    el: "#app"

    这个属性指定Vue实例应该控制的DOM元素。这里选择了ID为app的元素,即<div id="app">。Vue实例会挂载到这个元素上。

  • data属性

    1
    2
    3
    data: {
    message: "hello,vue!"
    }

    这个属性是一个对象,包含了应用的数据模型。在这个例子中,data对象只有一个属性message,其值为"hello,vue!"

数据绑定

1
{{message}}

Vue.js通过数据绑定将data对象中的message属性值插入到<div>元素中。因此,当Vue实例初始化后,<div>中的内容将显示为"hello,vue!"

总结

这个示例展示了Vue.js的基本用法,通过以下步骤实现了一个简单的数据绑定:

  1. 定义HTML模板,使用插值表达式显示数据。
  2. 导入Vue.js库。
  3. 初始化Vue实例,指定挂载元素和数据模型。

这样,当Vue实例创建时,它会根据数据模型自动更新视图,使得数据和视图保持同步。Vue.js的这一核心特性极大地简化了前端开发过程,使开发者可以更加专注于应用逻辑而非繁琐的DOM操作。

基础语法指令

v-bind

v-bind 是 Vue.js 中用于动态绑定 HTML 特性的指令。它可以将 Vue 实例中的数据绑定到 HTML 元素的属性上,使得这些属性的值随着数据的变化而变化。

下面是一个简单的示例,演示了如何使用 v-bind 绑定元素的 href 属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>V-bind 示例</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
</head>
<body>

<div id="app">
<!-- 使用 v-bind 绑定 href 属性 -->
<a v-bind:href="url">Visit Vue.js Website</a>
</div>

<script type="text/javascript">
var vm = new Vue({
el: "#app",
data: {
// 定义数据 url
url: "https://vuejs.org/"
}
});
</script>

</body>
</html>

这段代码是一个简单的 HTML 页面,演示了如何使用 Vue.js 中的 v-bind 指令来动态绑定 HTML 元素的属性。具体来说:

  • 页面中有一个 <div> 标签,它的 id 属性设置为 app,这是 Vue 实例的挂载点。
  • 在 Vue 实例中,通过 new Vue({}) 创建了一个 Vue 实例 vm
  • 在 Vue 实例中的 data 选项中,定义了一个属性 url,其值为 "https://vuejs.org/",这个属性将会被绑定到 HTML 元素的 href 属性上。
  • 页面中有一个 <a> 标签,它通过 v-bind:href="url" 指令,将 url 数据动态绑定到 href 属性上,使得点击这个链接时会跳转到 Vue.js 官网。

v-if, v-else

  • v-if
  • v-else

v-ifv-else 是 Vue.js 中的条件渲染指令,用于根据条件决定是否渲染某个 DOM 元素或组件。

  • v-if 指令用于根据表达式的值来决定是否渲染元素或组件。如果表达式为真(即返回 true),则渲染该元素或组件;如果表达式为假(即返回 false),则不渲染该元素或组件。

  • v-else 指令用于在 v-if 指令的后面表示一个“else 块”,用于在 v-if 条件不满足时渲染内容。v-else 元素必须直接跟在 v-if 元素的后面,且不能有任何元素或组件插入。

以下是一个简单的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div id="app">
<p v-if="isVisible">这个段落将会显示</p>
<p v-else>这个段落将会隐藏</p>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
isVisible: true // 可以动态改变该值来测试条件渲染
}
});
</script>

在上面的示例中,根据 isVisible 数据的值,决定了显示哪一个 <p> 元素。当 isVisibletrue 时,渲染第一个 <p> 元素;当 isVisiblefalse 时,渲染第二个 <p> 元素。

v-else-if 是 Vue.js 中的条件渲染指令,用于在 v-ifv-else 之间添加额外的条件判断。

  • v-if 指令用于根据表达式的值来决定是否渲染元素或组件。
  • v-else-if 指令用于在多个条件之间添加额外的条件判断。
  • v-else 指令用于在 v-ifv-else-if 条件不满足时渲染内容。

以下是一个示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div id="app">
<p v-if="type === 'A'">A 类型</p>
<p v-else-if="type === 'B'">B 类型</p>
<p v-else>C 类型</p>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
type: 'B' // 可以动态改变该值来测试条件渲染
}
});
</script>

在上面的示例中,根据 type 数据的值,决定了显示哪一个 <p> 元素。如果 type'A',则渲染第一个 <p> 元素;如果 type'B',则渲染第二个 <p> 元素;如果 type 不是 'A' 也不是 'B',则渲染第三个 <p> 元素。

v-for

v-for 是 Vue.js 中用于循环渲染列表的指令,它的语法格式如下:

1
2
3
<div v-for="(item, index) in items" :key="index">
<!-- 内容 -->
</div>
  • v-for 后面的 (item, index) 表示循环遍历时,每一项的变量名和索引名,你可以根据需要自定义。
  • in items 表示要遍历的数据源,通常是一个数组或者对象。
  • :key="index" 是为了给每一项设置唯一的 key 值,用于优化 Vue.js 的渲染性能,它的值可以是当前项的索引(index),或者是唯一标识符。

以下是一个示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div id="app">
<ul>
<li v-for="(item, index) in items" :key="index">
{{ index }}: {{ item }}
</li>
</ul>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
items: ['Apple', 'Banana', 'Orange']
}
});
</script>

在上面的示例中,v-for 指令用于循环遍历 items 数组,对于数组中的每一项,都会渲染一个 <li> 元素,其中 item 是当前项的值,index 是当前项的索引。

v-on

v-on 指令用于监听 DOM 事件,并在事件触发时执行相应的 Vue 实例方法或者表达式。它的基本语法格式如下:

1
<button v-on:click="handleClick">Click me</button>

在上面的示例中,v-on:click 表示监听按钮的点击事件,当按钮被点击时,会触发 handleClick 方法。

以下是一个示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<div id="app">
<button v-on:click="handleClick">Click me</button>
<p>{{ message }}</p>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
message: 'Button not clicked yet'
},
methods:
{
handleClick: function () {
this.message = 'Button clicked!';
}
}
});
</script>

在这个示例中,当按钮被点击时,handleClick 方法会更新 message 数据,从而改变页面上显示的文本内容。

双向绑定

双向数据绑定是指在 Vue.js 中,数据和视图之间建立了双向的关联,当数据发生变化时,视图会相应地更新;反之,当视图发生变化时,数据也会相应地更新。这种机制使得开发者无需手动操作 DOM 元素,而是专注于数据的处理,提高了开发效率和代码可维护性。

为什么要实现数据的双向绑定呢?这是因为在大部分应用中,用户与界面的交互是双向的:用户可以通过输入框、复选框等表单元素改变数据,同时数据的变化也需要及时地反映到界面上。双向数据绑定能够简化开发者处理这种交互的流程,提高开发效率。

在 Vue.js 中,你可以通过 v-model 指令在表单元素上创建双向数据绑定。这意味着你可以将表单元素和 Vue 实例中的数据属性绑定在一起,使得二者之间的变化能够相互影响。v-model 指令会根据表单元素的类型自动选取正确的方式来更新元素,比如文本框会监听输入事件,复选框会监听点击事件等。

需要注意的是,v-model 会忽略表单元素的 valuecheckedselected 等特性的初始值,而总是将 Vue 实例中的数据作为数据来源。因此,在使用 v-model 绑定表单元素时,应该通过 JavaScript 在 Vue 组件的 data 选项中声明初始值。

下面是一个示例,展示了如何在 Vue.js 中使用 v-model 实现双向数据绑定:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div id="app">
<input type="text" v-model="message">
<p>{{ message }}</p>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
});
</script>

在这个示例中,文本框和 <p> 元素之间建立了双向绑定,当你在文本框中输入内容时,message 数据会更新,并实时反映在页面上。

好的,让我给每个例子添加一些解释:

  1. 多行文本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div id="app">
<textarea v-model="textareaValue"></textarea>
<p>输入的内容是: {{ textareaValue }}</p>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
textareaValue: '' // 绑定到多行文本框的数据
}
});
</script>

在这个示例中,v-model 指令将 <textarea> 元素与 Vue 实例的 textareaValue 属性双向绑定,所以当在文本框中输入内容时,视图中的文本也会随之更新。

  1. 单复选框
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div id="app">
<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">{{ checked ? '已选中' : '未选中' }}</label>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
checked: false // 绑定到单复选框的数据
}
});
</script>

这里的 v-model 指令将 <input type="checkbox"> 元素与 Vue 实例的 checked 属性双向绑定,所以当复选框被选中或取消选中时,checked 的值也会相应变化。

  1. 多复选框
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<div id="app">
<input type="checkbox" value="Apple" v-model="selectedFruits"> Apple
<input type="checkbox" value="Banana" v-model="selectedFruits"> Banana
<input type="checkbox" value="Orange" v-model="selectedFruits"> Orange
<p>你选择的水果是: {{ selectedFruits }}</p>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
selectedFruits: [] // 绑定到多复选框的数据,是一个数组
}
});
</script>

这里的 v-model 指令将多个复选框元素与 Vue 实例的 selectedFruits 数组双向绑定,所以当选择或取消选择任何一个复选框时,selectedFruits 数组中的值都会随之变化。

  1. 单选按钮
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div id="app">
<input type="radio" id="male" value="男" v-model="gender">
<label for="male"></label>
<input type="radio" id="female" value="女" v-model="gender">
<label for="female"></label>
<p>你选择的性别是: {{ gender }}</p>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
gender: '' // 绑定到单选按钮的数据
}
});
</script>

这里的 v-model 指令将多个单选按钮元素与 Vue 实例的 gender 属性双向绑定,所以当选择任何一个单选按钮时,gender 的值会随之变化。

  1. 下拉框
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<div id="app">
<select v-model="selectedFruit">
<option disabled value="">请选择水果</option>
<option value="Apple">苹果</option>
<option value="Banana">香蕉</option>
<option value="Orange">橙子</option>
</select>
<p>你选择的水果是: {{ selectedFruit }}</p>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
selectedFruit: '' // 绑定到下拉框的数据
}
});
</script>

这里的 v-model 指令将 <select> 元素与 Vue 实例的 selectedFruit 属性双向绑定,所以当选择任何一个

组件

组件是 Vue.js 中一种抽象的概念,它可以封装可复用的 HTML 元素和相关功能逻辑,使得我们可以将页面拆分成独立的、可复用的模块。在 Vue 应用中,一个组件可以包含 HTML、CSS 和 JavaScript,它们共同组成了一个完整的、可复用的功能模块。

通常情况下,一个 Vue 应用会以一棵嵌套的组件树的形式组织起来,即一个组件内部可以包含其他的组件,形成了层层嵌套的关系。这样的组件树可以使得应用的开发和维护更加清晰和灵活,提高了代码的复用性和可维护性。

在 Vue.js 中,组件可以通过 Vue 实例来创建,然后通过在父组件中引用或者在路由中定义来使用。组件可以接收父组件传递的数据,并通过 props 属性来定义组件的接口。同时,组件也可以发出事件,向父组件传递消息。

下面是一个简单的示例,展示了一个组件的基本结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!-- ParentComponent.vue -->
<template>
<div>
<h1>Parent Component</h1>
<ChildComponent message="Hello from Parent" @custom-event="handleCustomEvent" />
</div>
</template>

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

export default {
components: {
ChildComponent
},
methods: {
handleCustomEvent(payload) {
console.log('Received payload from child:', payload);
}
}
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- ChildComponent.vue -->
<template>
<div>
<h2>Child Component</h2>
<p>{{ message }}</p>
<button @click="emitEvent">Send Event to Parent</button>
</div>
</template>

<script>
export default {
props: {
message: String
},
methods: {
emitEvent() {
this.$emit('custom-event', { data: 'Custom data from child' });
}
}
}
</script>

在这个示例中,ParentComponent 是父组件,ChildComponent 是子组件。父组件通过引入子组件的方式来使用它,并且可以传递数据给子组件。子组件可以接收父组件传递的数据,并且可以发出自定义事件给父组件。


当我们需要在组件中使用外部数据时,可以使用 Vue.js 中的 props 属性。props 允许父组件传递数据给子组件,在子组件内部可以通过定义的 props 属性来接收这些数据。

下面是一个简单的示例,展示了如何使用 props 属性传递参数到组件中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!-- ParentComponent.vue -->
<template>
<div>
<ChildComponent message="Hello from ParentComponent!"></ChildComponent>
</div>
</template>

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

export default {
components: {
ChildComponent
}
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
<!-- ChildComponent.vue -->
<template>
<div>
<p>{{ message }}</p>
</div>
</template>

<script>
export default {
props: ['message']
}
</script>

解释:

  • ParentComponent.vue 中,我们使用 <ChildComponent> 标签来引入子组件,并通过 message 属性向子组件传递数据。
  • ChildComponent.vue 中,我们通过 props 属性声明了一个名为 message 的 prop。子组件可以通过这个 prop 来接收来自父组件的数据,并在模板中使用它。

这样,父组件就能够把数据传递给子组件,并在子组件内部使用这些数据了。

Axios

Axios 是一个基于 Promise 的 HTTP 客户端,用于浏览器和 Node.js。它能够以简洁的方式进行 HTTP 请求,并支持拦截器、取消请求、自动转换 JSON 数据、客户端端口防御等特性。以下是一些关于 Axios 异步通信的知识点:

  1. 发送 GET 请求:

    1
    2
    3
    4
    5
    6
    7
    axios.get('/api/data')
    .then(response => {
    console.log(response.data);
    })
    .catch(error => {
    console.error('Error fetching data:', error);
    });
  2. 发送 POST 请求:

    1
    2
    3
    4
    5
    6
    7
    axios.post('/api/user', { name: 'John', age: 30 })
    .then(response => {
    console.log(response.data);
    })
    .catch(error => {
    console.error('Error creating user:', error);
    });
  3. 拦截器(Interceptors):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    axios.interceptors.request.use(config => {
    // 在发送请求之前做些什么
    return config;
    }, error => {
    // 对请求错误做些什么
    return Promise.reject(error);
    });

    axios.interceptors.response.use(response => {
    // 对响应数据做些什么
    return response;
    }, error => {
    // 对响应错误做些什么
    return Promise.reject(error);
    });
  4. 取消请求:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    const source = axios.CancelToken.source();

    axios.get('/api/data', {
    cancelToken: source.token
    }).catch(thrown => {
    if (axios.isCancel(thrown)) {
    console.log('Request canceled:', thrown.message);
    } else {
    console.error('Error fetching data:', thrown);
    }
    });

    // 取消请求
    source.cancel('Operation canceled by the user.');
  5. 处理响应和错误: Axios 的 thencatch 方法用于处理成功和失败的响应。成功时,响应数据会通过 then 方法传递,失败时,错误信息会通过 catch 方法传递。

  6. 自动转换 JSON 数据: Axios 会自动将响应数据转换为 JSON 格式。

  7. 设置请求头:

    1
    axios.defaults.headers.common['Authorization'] = 'Bearer token';
  8. 处理并发请求:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    axios.all([
    axios.get('/api/data1'),
    axios.get('/api/data2')
    ]).then(axios.spread((response1, response2) => {
    console.log('Response 1:', response1.data);
    console.log('Response 2:', response2.data);
    })).catch(error => {
    console.error('Error fetching data:', error);
    });

当与 Vue 结合使用时,通常会在组件的生命周期钩子中使用 Axios 发起 HTTP 请求。以下是一个简单的示例,演示了如何在 Vue 组件中使用 Axios 发送 GET 请求,并将响应数据显示在页面上:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue Axios 示例</title>
<!-- 导入 Vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<!-- 导入 Axios -->
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
<h1>Vue Axios 示例</h1>
<ul>
<!-- 使用 v-for 指令渲染列表 -->
<li v-for="post in posts" :key="post.id">{{ post.title }}</li>
</ul>
</div>

<script>
new Vue({
el: '#app',
data() {
return {
posts: [] // 初始化一个空数组用于存储文章数据
};
},
mounted() {
// 在组件挂载后发送 GET 请求获取文章数据
axios.get('https://jsonplaceholder.typicode.com/posts')
.then(response => {
// 请求成功时更新数据
this.posts = response.data;
})
.catch(error => {
// 请求失败时处理错误
console.error('Error fetching posts:', error);
});
}
});
</script>
</body>
</html>

在这个示例中,我们创建了一个 Vue 实例,并在 mounted 生命周期钩子中使用 Axios 发送了一个 GET 请求,获取了 JSONPlaceholder 提供的假数据,并将获取到的文章列表数据渲染到页面上。

这个示例演示了如何在 Vue 应用中使用 Axios 发起 HTTP 请求,并将响应数据动态地展示在页面上,以实现数据的动态更新。

当涉及 Vue 中的计算属性、内容分发和自定义事件时,它们是 Vue.js 中非常重要的概念,用于管理数据和组件之间的交互。下面是对它们的简要解释:

1. 计算属性(Computed Properties)

解释: 计算属性是一种声明式的数据属性,用于根据其他数据的值动态计算而来。它们类似于实例中的 data 属性,但是它们的值是根据其他属性计算得来的,而不是直接由开发者设置的。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
<div>
<p>{{ message }}</p>
<p>{{ reversedMessage }}</p>
</div>
</template>

<script>
export default {
data() {
return {
message: 'Hello Vue!'
};
},
computed: {
// 计算属性:反转 message 字符串
reversedMessage() {
return this.message.split('').reverse().join('');
}
}
};
</script>

2. 内容分发(Content Distribution)

解释: 内容分发是一种 Vue 组件的技术,用于在父组件中分发内容到子组件的指定位置。通过内容分发,可以创建可复用的组件,并允许父组件将任意内容插入到子组件中的指定位置。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!-- ParentComponent.vue -->
<template>
<div>
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
</template>

<!-- 在使用组件时 -->
<parent-component>
<template v-slot:header>
<h1>Header Content</h1>
</template>

<p>Main Content</p>

<template v-slot:footer>
<p>Footer Content</p>
</template>
</parent-component>

3. 自定义事件(Custom Events)

解释: 自定义事件是一种在 Vue 组件中实现父子组件通信的方式。它允许子组件触发事件,并将数据发送给父组件,父组件可以监听这些事件并对其进行响应。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- ChildComponent.vue -->
<template>
<button @click="sendData">Send Data</button>
</template>

<script>
export default {
methods: {
sendData() {
// 触发名为 sendData 的自定义事件,并传递数据
this.$emit('sendData', 'Some Data');
}
}
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!-- ParentComponent.vue -->
<template>
<div>
<child-component @sendData="handleData"></child-component>
</div>
</template>

<script>
export default {
methods: {
handleData(data) {
// 监听子组件的 sendData 事件,并处理传递过来的数据
console.log('Received Data:', data);
}
}
};
</script>

小示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<template>
<div>
<h1>{{ greeting }}</h1>

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

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

<my-component :title="componentTitle" @customEvent="handleCustomEvent"></my-component>

<input type="text" v-model="inputValue">
<p>{{ inputValue }}</p>

<custom-directive v-my-directive></custom-directive>

<router-link to="/about">About</router-link>
</div>
</template>

<script>
import { ref, reactive, computed, watch } from 'vue';
import axios from 'axios';

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: ''
};
},
computed: {
componentTitle() {
return this.showMessage ? 'Show Message' : 'Hide Message';
}
},
methods: {
toggleMessage() {
this.showMessage = !this.showMessage;
},
handleCustomEvent(data) {
console.log('Custom Event Received:', data);
}
},
directives: {
myDirective(el, binding) {
el.style.backgroundColor = binding.value;
}
},
created() {
axios.get('https://jsonplaceholder.typicode.com/posts')
.then(response => {
console.log('Response:', response.data);
})
.catch(error => {
console.error('Error:', error);
});
},
mounted() {
watch(() => this.inputValue, (newValue, oldValue) => {
console.log('Input Value Changed:', newValue);
});
}
};
</script>

<style scoped>
h1 {
color: red;
}
</style>

好的,让我更详细地解释一下这个 Vue 组件。

  1. greeting: 这个属性存储了一个字符串 'Hello Vue 3!',用于显示在页面中的标题 <h1> 中。

  2. toggleMessage 方法:这是一个用于切换 showMessage 值的方法。showMessage 控制着消息的显示状态,当点击按钮时,会切换它的值,从而控制消息的显示或隐藏。

  3. items 数组:这是一个包含了三个对象的数组,每个对象都有一个 idname 属性。使用 v-for 指令遍历数组,将每个对象的名称显示在 <li> 元素中。

  4. <my-component> 组件:这是一个自定义组件,通过属性绑定 :title="componentTitle" 传递了一个动态标题,并通过 @customEvent="handleCustomEvent" 监听了一个自定义事件。

  5. 输入框和段落:使用 v-model 指令实现了输入框与段落之间的双向数据绑定。当输入框的值发生变化时,段落中显示的值也会跟着变化。

  6. custom-directive 自定义指令:这是一个自定义指令,名为 myDirective,用于改变元素的背景颜色。通过 v-my-directive 在元素上应用了这个指令。

  7. <router-link> 路由链接:这是一个 Vue Router 的路由链接,通过 to 属性指定了导航目标路由。

  8. computed 计算属性:定义了一个名为 componentTitle 的计算属性,根据 showMessage 的值动态返回组件的标题,如果 showMessagetrue,则返回 'Show Message',否则返回 'Hide Message'

  9. methods 方法:包含了 toggleMessagehandleCustomEvent 两个方法。toggleMessage 用于切换消息的显示状态,handleCustomEvent 用于处理自定义事件。

  10. directives 自定义指令:定义了一个名为 myDirective 的自定义指令,用于改变元素的背景颜色。

  11. created 钩子函数:在组件创建时执行异步操作,发送 Ajax 请求获取数据。

  12. mounted 钩子函数:在组件挂载到 DOM 后执行监听输入框值变化的操作。

  13. <style scoped> 样式:这是组件的样式部分,仅作用于当前组件的样式,其中 h1 标签的文字颜色设置为红色。