前端八股---MVVM

目录

[一、什么是 MVVM?](#一、什么是 MVVM?)

二、三部分详解

[1. Model(模型)](#1. Model(模型))

[2. View(视图)](#2. View(视图))

[3. ViewModel(视图模型)](#3. ViewModel(视图模型))

三、核心亮点:双向绑定

[四、Vue 实例(ViewModel)](#四、Vue 实例(ViewModel))

[Vue 实例是什么?](#Vue 实例是什么?)

[Vue2 vs Vue3 实例创建](#Vue2 vs Vue3 实例创建)

组件实例创建时机

[五、Vue 如何实现双向绑定?](#五、Vue 如何实现双向绑定?)

六、面试高频问题

[Q:什么是 MVVM?](#Q:什么是 MVVM?)

[Q:MVVM 和 MVC 的区别?](#Q:MVVM 和 MVC 的区别?)

[Q:Vue 实例是什么时候创建的?](#Q:Vue 实例是什么时候创建的?)

[Q:Vue2 和 Vue3 创建组件实例有什么区别?](#Q:Vue2 和 Vue3 创建组件实例有什么区别?)

[七、为什么 Vue3 要取消 this?](#七、为什么 Vue3 要取消 this?)

[原因1:this 容易让人困惑](#原因1:this 容易让人困惑)

[原因2:TypeScript 类型推导更简单](#原因2:TypeScript 类型推导更简单)

原因3:代码更清晰


一、什么是 MVVM?

MVVM 是一种架构模式,实现了视图和数据的双向绑定:数据变视图自动变,视图变数据自动变。

复制代码
┌─────────────────────────────────────────────────────────────┐
│                         MVVM 架构                            │
│                                                             │
│  ┌─────────┐         ┌─────────────┐         ┌─────────┐   │
│  │  Model  │ ◄─────► │  ViewModel  │ ◄─────► │  View   │   │
│  │  数据   │         │  Vue 实例   │         │  视图   │   │
│  └─────────┘         └─────────────┘         └─────────┘   │
│       ↑                    ↑                      ↑        │
│       │                    │                      │        │
│   原始数据            响应式系统                 DOM        │
│   API返回             双向绑定                 页面        │
│                                                             │
└─────────────────────────────────────────────────────────────┘

二、三部分详解

1. Model(模型)

要点 说明
是什么 数据层
包含 后端接口返回的数据、本地数据、状态
职责 只关心数据,不关心页面
例子 data() { return { count: 0 } }

2. View(视图)

要点 说明
是什么 视图层
包含 页面、DOM、用户看到的界面
职责 只负责展示,不直接操作数据
例子 <div>{``{ count }}</div>

3. ViewModel(视图模型)

要点 说明
是什么 Vue 实例
职责 连接 Model 和 View 的中间层,实现双向绑定
核心能力 数据变化 → 更新视图;视图操作 → 更新数据
例子 Vue 组件实例

三、核心亮点:双向绑定

传统做法(手动操作 DOM):

javascript 复制代码
// 没有 MVVM 时
const input = document.getElementById('input')
const span = document.getElementById('span')

// 数据 → 视图
span.innerText = data

// 视图 → 数据
input.addEventListener('input', (e) => {
  data = e.target.value
  span.innerText = data  // 还要手动更新视图
})

MVVM 做法(自动双向绑定):

javascript 复制代码
<template>
  <div>
    <input v-model="message" />
    <p>{{ message }}</p>
  </div>
</template>

<script setup>
const message = ref('')
// 不用写任何 DOM 操作代码!
</script>

四、Vue 实例(ViewModel)

Vue 实例是什么?

每个 Vue 组件,本质上就是一个 Vue 实例。它是一个对象,掌管着当前组件里的一切。

掌管内容 说明
data 响应式数据
methods 方法
computed 计算属性
watch 侦听器
生命周期 钩子函数
DOM 更新 虚拟 DOM、渲染
事件监听 原生事件、自定义事件
v-model 双向绑定

Vue2 vs Vue3 实例创建

javascript 复制代码
// Vue2
const vm = new Vue({
  data: { count: 0 },
  methods: { increment() { this.count++ } }
})
// vm 就是 ViewModel

// Vue3
import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)  // 根实例
app.mount('#app')
// Vue3 组件实例依然存在,但被隐藏,不再暴露 this

组件实例创建时机

复制代码
┌─────────────────────────────────────────────────────────────┐
│  组件实例创建规则:                                           │
│                                                             │
│  1. 根实例:手动创建(new Vue() / createApp())              │
│                                                             │
│  2. 其他组件实例:不是一开始就创建!                           │
│     而是在组件被渲染到视图时,由 Vue 自动创建                  │
│                                                             │
│  3. 一个组件被渲染几次,就创建几个实例                         │
│                                                             │
│  例如:                                                      │
│  <UserCard v-for="user in users" :key="user.id" />         │
│  有 10 个用户,就创建 10 个 UserCard 实例                    │
└─────────────────────────────────────────────────────────────┘

五、Vue 如何实现双向绑定?

复制代码
┌─────────────────────────────────────────────────────────────┐
│                    Vue 双向绑定原理                          │
│                                                             │
│   数据变化 → 视图更新(响应式系统)                           │
│   ┌─────────┐    ┌─────────┐    ┌─────────┐               │
│   │ 数据变化 │ → │ 触发 set│ → │ 通知更新│ → 重新渲染       │
│   └─────────┘    └─────────┘    └─────────┘               │
│                                                             │
│   视图变化 → 数据更新(事件监听)                             │
│   ┌─────────┐    ┌─────────┐    ┌─────────┐               │
│   │ 用户输入 │ → │ 触发事件│ → │ 更新数据│ → 响应式触发     │
│   └─────────┘    └─────────┘    └─────────┘               │
│                                                             │
│   v-model 就是连接这两套机制的语法糖                          │
└─────────────────────────────────────────────────────────────┘

六、面试高频问题

Q:什么是 MVVM?

答:

MVVM 是一种架构模式,由三部分组成:

  • Model:数据层

  • View:视图层

  • ViewModel:连接层(Vue 实例)

核心特性是双向绑定:数据变化自动更新视图,视图变化自动更新数据。

Q:MVVM 和 MVC 的区别?

对比 MVC MVVM
组成部分 Model、View、Controller Model、View、ViewModel
数据流向 单向 双向
核心 Controller 控制逻辑 ViewModel 自动同步
DOM 操作 需要手动 自动

Q:Vue 实例是什么时候创建的?

答:

  • 根实例:手动创建(new Vue()createApp()

  • 其他组件实例:在组件被渲染时自动创建

  • 一个组件被渲染几次,就创建几个实例

Q:Vue2 和 Vue3 创建组件实例有什么区别?

答:

  1. 根实例创建方式不同 :Vue2 用 new Vue(),Vue3 用 createApp()

  2. 实例暴露程度不同 :Vue2 完全暴露实例,通过 this 访问;Vue3 隐藏实例,<script setup> 中没有 this

  3. 实例创建时机相同:都是组件渲染时动态创建,渲染几次就创建几个实例

  4. API 风格不同:Vue2 推荐 Options API,Vue3 推荐 Composition API

对比项 Vue2 Vue3 (<script setup>)
有没有 this ✅ 有 ❌ 没有
访问数据 this.count count
访问方法 this.increment() increment()
访问 DOM this.$el ref
触发事件 this.$emit() defineEmits()
TypeScript 支持较弱 完美支持
学习曲线 需要理解 this 像写普通 JS

七、为什么 Vue3 要取消 this?

原因1:this 容易让人困惑

javascript 复制代码
// Vue2 中的坑
export default {
  data() {
    return {
      count: 0
    }
  },
  methods: {
    increment() {
      // 普通函数:this 正确
      setTimeout(function() {
        this.count++  // ❌ 这里的 this 是 window!不是组件!
      }, 1000)
      
      // 必须用箭头函数
      setTimeout(() => {
        this.count++  // ✅ 箭头函数 this 正确
      }, 1000)
    }
  }
}
javascript 复制代码
// Vue3:没有 this,永远不会有这个问题
const count = ref(0)

function increment() {
  setTimeout(() => {
    count.value++  // ✅ 直接用变量,永远正确
  }, 1000)
}

原因2:TypeScript 类型推导更简单

javascript 复制代码
// Vue2:TypeScript 很难推导 this 的类型
export default {
  data() {
    return {
      count: 0
    }
  },
  methods: {
    increment() {
      this.count  // this 是什么类型?很复杂
    }
  }
}

// Vue3:TypeScript 完美推导
const count = ref(0)  // 类型自动是 Ref<number>
function increment() {
  count.value  // 类型明确
}

原因3:代码更清晰

javascript 复制代码
// Vue2:数据和方法分散在不同的区域
export default {
  data() {
    return {
      count: 0,
      user: null,
      loading: false
    }
  },
  methods: {
    increment() { this.count++ },
    fetchUser() { ... }
  }
}

// Vue3:相关逻辑可以放在一起
const count = ref(0)
const increment = () => count.value++

const user = ref(null)
const loading = ref(false)
const fetchUser = async () => { ... }
相关推荐
神毓逍遥kang2 小时前
在nest.js中我想把Java的Sa-Token搬来
前端·后端
Sheldon一蓑烟雨任平生2 小时前
grid(一文读懂 css 网格布局)
前端·css·grid·grid-template·现代css·css 网格布局
砍材农夫2 小时前
Hermes 搭建可视化web-dashboard界面
前端·人工智能
Z_Wonderful2 小时前
Qiankun 子应用数据互通 + 资源共享 完整方案(React+Vue)
前端·vue.js·react.js
你的牧游哥2 小时前
Electron核心api详解
前端·javascript·electron
渣渣xiong2 小时前
从零开始:前端转型AI agent直到就业第十二天-第十三天
前端·人工智能
05Nuyoah2 小时前
CSS 基础认知和基础选择器
前端·javascript·css·node.js
DanCheOo2 小时前
从单 Chat 到多 Agent 系统:AI 应用的架构演进路线
前端·agent
开开心心就好2 小时前
经典塔防游戏移植移动端随时畅玩
java·前端·科技·游戏·edge·django·pdf