什么是MVVM?
MVVM = Model-View-ViewModel
Vue的MVVM严格来说更像是一个抽象概念,vue并不是MVVM架构实现,因为它不像Thinkphp这样的框架对于MVC有具象的表现,只是借鉴了MVVM的核心思想。
这是个老生常谈的问题了,社区里对Vue是否是MVVM架构的叫法问题经常会有不同的观点,其实作者本人也对表达了对这方面的解释
什么是Model和View?
这个其实很好理解,如果有MVC相关经验的话
Model总结下来其实就是对数据的操作管理,可能包含:
- 数据持久化存储
- 对数据的处理(格式化\时间戳处理\倒计时处理)
- 与后端的交互
- 封装与统一(例如使用vuex或pinia)
- 对view的解耦,使得数据层是独立的
Model 示例:
//这个就是model,也就是数据层
const message = ref('Hello')
//也可以是reactive
const form = reactive({
user: {
name: '',
age: 18
},
settings: {
theme: 'dark',
notifications: true
},
tags: ['vue', 'mvvm', 'example']
})
//可以是computed
const fullName = computed(() => `${firstName.value} ${lastName.value}`)
//甚至可以是Pinia或vuex管理的整个模块
import { defineStore } from 'pinia'
import { ref, reactive } from 'vue'
export const useProductStore = defineStore('product', () => {
// Model: 商品列表
const products = ref<Product[]>([])
// Model: 分页信息
const pagination = reactive({
page: 1,
pageSize: 10,
total: 0
})
// Model: 搜索条件
const searchKeyword = ref('')
// Action: 从后端加载商品列表
async function fetchProducts() {
const res = await fetch(`/api/products?page=${pagination.page}&size=${pagination.pageSize}&keyword=${searchKeyword.value}`)
const data = await res.json()
products.value = data.items
pagination.total = data.total
}
// Action: 新增商品
async function addProduct(newProduct: Partial<Product>) {
await fetch('/api/products', {
method: 'POST',
body: JSON.stringify(newProduct)
})
await fetchProducts() // 刷新列表
}
return {
products, pagination, searchKeyword,
fetchProducts, addProduct
}
})
View相较于Model更容易理解一些,Model包含一些抽象概念,而View纯粹是具象的表现
可以这样理解,所有标记语言的部分基本都属于view
包括组件也是
//整个template部分都是view,视图层
<template>
<input v-model="message" />
<p>{{ message }}</p>
</template>
什么是ViewModel呢?
ViewModel相对来说比较难理解一些,因为单看这个View Model的单词会觉得这是个抽象概念,但实际上ViewModel确实就是一个抽象流程
ViewModel = 帮助 View 获取和操作 Model 的中介或“桥梁”,负责协调数据的读取与更新流程,实现 View 和 Model 之间的解耦与同步流程
//具体表现如下
ViewModel包含Action,与Model存在关系,与View也存在关系
<script setup>
import { ref } from 'vue'
const count = ref(0) // 状态(Model)
function increment() { // 操作(Action)
count.value++
}
</script>
<template>
<button @click="increment">+1</button>
<p>{{ count }}</p>
</template>