案例挑战——MVVM框架理解和实践

news2024/11/26 9:30:46

MVVM框架理解和实践

  • 一、背景介绍
  • 二、 什么是MVVM架构?
    • 1.架构示意图
    • 2.MVVM概念总结
    • 3.实现VM的框架
  • 三、通过案例来理解MVVM框架
    • 1.没有使用MVVM架构的程序
    • 2.使用了MVVM架构的程序
    • 3.对比
  • 四、总结

一、背景介绍

最近正在做新版项目的MVVM架构的结合业务的具体落地,前后与领导进行了多次的交流和沟通,从业务的简单例子入手更改了五版代码。最终输出了一版比较完善的符合MVVM架构和业务需求的模板代码。通过这次的案例挑战,对MVVM架构有了相对于此前更为深层次的理解,通过博客总结的方式进行记录和明确自己的收获。

二、 什么是MVVM架构?

MVVM(Model-View-ViewModel)一种中架构模式,将应用程序的用户界面(视图)与后端逻辑(模型)进行解耦。它通过引入一个视图模型(ViewModel)来实现分离。

在MVVM架构模式中,**模型(Model)**代表应用程序的数据和业务逻辑(与后端服务器进行交互,从数据源中检索数据并进行处理和操作),**视图(View)**是用户界面的可视部分,负责展示数据和接收用户的输入。**视图模型(ViewModel)**为模型和视图之间的中间层,负责处理视图和模型之间的通信和交互也就是将模型数据转换成视图可用的形式,并处理视图的用户交互事件。

1.架构示意图

在这里插入图片描述
视图模型通过绑定机制将视图和模型连接起来,保持他们之间的同步,当模型的数据发生变化时,视图模型会通知视图进行更新。当用户在视图上进行操作的时候,视图模型会将这些操作传递给模型进行处理。

2.MVVM概念总结

模型:代表应用程序的数据和业务逻辑,通常与后端数据源交互
视图:负责展示用户界面,并与用户进行交互
视图模型:连接视图和模型的桥梁,负责将模型数据转换成视图可用的形式,并处理视图的用户交互事件。

3.实现VM的框架

我们可以看出来MVVM框架的核心是视图模型(ViewModel),连接视图和模型的桥梁,负责将模型数据转换成视图可用的形式,并处理视图的用户交互事件。

目前有很多框架可以用来实现MVVM架构中的ViewModel部分:
如 Vue.js、Angular、React、knockout.js

三、通过案例来理解MVVM框架

需求:现在在页面上有一个多选题,页面显示的数据有题目、内容、多个选项。
现在用户进行答题,选择选项后进行提交调用后端的答题接口。

主要的实现思路是,将前端界面上需要的数据正确的显示在页面中,当用户进行答题之后,拿到用户的答题信息,并转为后端需要的数据结构。

页面显示的数据源:

// 定义数据模型
        const questionData ={
                            questionnaireGrainId: 111,
                            title: '1.1.1.3 调查问卷:《Python语言的特点》,时间:0.5min',
                            content: '题目:下列选项中,不属于Python语言特点的是( )',
                            optionList: [
                                {
                                    optionId: 333,
                                    questionnaireGrainId: 111,
                                    optionContent: '苹果',
                                    
                                },
                                {
                                    optionId: 334,
                                    questionnaireGrainId: 111,
                                    optionContent: '橡胶',
                                    
                                },
                                {
                                    optionId: 335,
                                    questionnaireGrainId: 111,
                                    optionContent: '香蕉',
                                    
                                },
                                {
                                    optionId: 336,
                                    questionnaireGrainId: 111,
                                    optionContent: '梨',
                            
                                }
                            ]
                        };

页面效果:
在这里插入图片描述
后端需要的数据结构示例:

{
  "questionnaireGrainId": 111,
  "questionnaireOptionParticipation": [
    {
      "optionId": "333"
    },
    {
      "optionId": "334"
    }
  ]
}

1.没有使用MVVM架构的程序

整体代码:

<!DOCTYPE html>
<html>
<head>
    <title>多选题示例</title>
</head>
<body>
    
    <!-- 绑定数据的容器 -->
        <div id="app">
        </div>
        <button type="button" onclick="submitAnswers()">提交</button>

    <script>
        // 定义数据模型
        const questionData ={
                            questionnaireGrainId: 111,
                            title: '1.1.1.3 调查问卷:《Python语言的特点》,时间:0.5min',
                            content: '题目:下列选项中,不属于Python语言特点的是( )',
                            optionList: [
                                {
                                    optionId: 333,
                                    questionnaireGrainId: 111,
                                    optionContent: '苹果',
                                    
                                },
                                {
                                    optionId: 334,
                                    questionnaireGrainId: 111,
                                    optionContent: '橡胶',
                                    
                                },
                                {
                                    optionId: 335,
                                    questionnaireGrainId: 111,
                                    optionContent: '香蕉',
                                    
                                },
                                {
                                    optionId: 336,
                                    questionnaireGrainId: 111,
                                    optionContent: '梨',
                            
                                }
                            ]
                        };
        
        
        //后端需要的数据结构
        const questionnaireParticipation = {
          questionnaireGrainId: null,
          questionnaireOptionParticipation: [],
        };

        
            // 获取容器元素
            const appContainer = document.getElementById('app');
            
            // 创建标题元素并添加到容器中
            const titleElement = document.createElement('h1');
            titleElement.textContent = questionData.title;
            appContainer.appendChild(titleElement);
            
            // 创建内容元素并添加到容器中
            const contentElement = document.createElement('p');
            contentElement.textContent = questionData.content;
            appContainer.appendChild(contentElement);

            
            // 创建复选框元素并添加到容器中
            questionData.optionList.forEach(option => {
                const checkbox = document.createElement('input');
                checkbox.type = 'checkbox';
                checkbox.name = 'optionList';
                checkbox.value = option.optionId;
        
                const label = document.createElement('label');
                label.appendChild(checkbox);
                label.appendChild(document.createTextNode(option.optionContent));
                label.appendChild(document.createElement('br'));
        
                appContainer.appendChild(label);
            });

        //用户答题方法
        function submitAnswers() {
            // 获取所有被选中的选项
            const optionsData=[];
            const optionElems = document.querySelectorAll('input');

            // 将选项的值存入数组中
            optionElems .forEach(elem => {
                if (elem.checked) {
                const optionId = elem.value;
                optionsData.push({optionId});
                }
                
            });

            console.log(`用户选择的选项为:`,optionsData);

        // 遍历选项数据,赋值到后端需要的数据结构中
        for (let i = 0; i < optionsData.length; i++) {

        questionnaireParticipation.questionnaireGrainId=questionData.questionnaireGrainId;
        questionnaireParticipation.questionnaireOptionParticipation.push(optionsData[i])
        
        }
        console.log("questionnaireParticipation数据结构",questionnaireParticipation);
        // 将 questionnaireParticipation 数组转换为 JSON 字符串
        let questionnaireParticipationDataJson = JSON.stringify(questionnaireParticipation);

        // 在控制台中打印 JSON 字符串
        console.log(questionnaireParticipationDataJson);

    
    
    }
    </script>
</body>
</html>

打印出的数据结构示例:

{
  "questionnaireGrainId": 111,
  "questionnaireOptionParticipation": [
    {
      "optionId": "334"
    },
    {
      "optionId": "335"
    }
  ]
}

2.使用了MVVM架构的程序

这里通过采用VUE框架在实现VM。

<!DOCTYPE html>
<html>
    <head>
        <title>多选题示例</title>
            <!-- 引入 Vue.js -->
            <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    </head>
    <body>
        <!-- 绑定 Vue.js 实例 -->
            <div id="app">
                <h2>{{ question.title }}</h2>
                <p>{{ question.content }}</p>
                <form>
                    <label v-for="option in question.optionList" :key="option.optionId"  >
                        <input type="checkbox" v-model="questionnaireParticipation.questionnaireOptionParticipation" :value="{
                            optionId:option.optionId
                        }">
                        {{ option.optionContent }}
                    </label><br>
                    <button type="button" @click="submitAnswers">提交</button>
                </form>
            </div>
        
    </body>
    <!-- 引入 Vue.js 实例脚本 -->
    <script src="questionnaire-articipation-app.js"></script>
</html>


// 定义数据模型
const questionData ={
                    questionnaireGrainId: 111,
                    title: '1.1.1.3 调查问卷:《Python语言的特点》,时间:0.5min',
                    content: '题目:下列选项中,不属于Python语言特点的是( )',
                    optionList: [
                        {
                            optionId: 333,
                            questionnaireGrainId: 111,
                            optionContent: '苹果',
                            
                        },
                        {
                            optionId: 334,
                            questionnaireGrainId: 111,
                            optionContent: '橡胶',
                            
                        },
                        {
                            optionId: 335,
                            questionnaireGrainId: 111,
                            optionContent: '香蕉',
                            
                        },
                        {
                            optionId: 336,
                            questionnaireGrainId: 111,
                            optionContent: '梨',
                    
                        }
                    ]
                };

        //第四版
        new Vue({
            el: '#app',
            data: {
                question:questionData,
                
                questionnaireParticipation: {
                  questionnaireGrainId:questionData.questionnaireGrainId,
                  questionnaireOptionParticipation:[],
                  }
            },
            methods: {
                
                submitAnswers: function() {
                    //调用后端接口..............
                    
                    //打印数据结构
                    let actorDataJson = JSON.stringify(this.questionnaireParticipation);
                           // 在控制台中打印 JSON 字符串
                           console.log(actorDataJson);
                }
            }
        });

打印出的数据结构示例:

{
  "questionnaireGrainId": 111,
  "questionnaireOptionParticipation": [
    {
      "optionId": 333
    },
    {
      "optionId": 334
    }
  ]
}

补充:上面使用MVVM架构的程序,它的V是呈现的html代码,无业务逻辑(如:多选框、按钮、相应对象触发的事件)
VM:监听V、M处理V需要做的业务逻辑,决定将那个M数据渲染给那个V,以及选择那个M进行业务处理
M:js代码,前端数据载体,通过axios组件向后端发送http请求

3.对比

  1. 从上面两版代码最直观的感觉是,使用MVVM架构的程序的代码更为简洁,层次更为清晰。分为了三层,视图层、模型层、视图模型层(这里有vue提供)。

  2. 从上面的代码可以看出使用MVVM架构的程序在代码上根本就没有做数据结构转换的步骤(将用户答题的数据,将其转换为后端程序需要的数据结构),而是用户选择什么数据,通过VM直接就是我后端需要的数据结构。VM做了数据交互的部分,并使用{}符号定义对象。

  3. 使用MVVM架构的程序,将视图与模型之间进行了解耦,与没有实现MVVM架构的程序相比,那么我的V和我的M就能够实现高复用,相似的业务等等,都用这一套M。

四、总结

  1. 通过这一次的案例挑战,对于MVVM架构有了更进一步的理解,理论结合实践,并且需要和高人进行交流和请教高人。
  2. 目前只是对MVVM架构有了一些理解,后续还需要再项目实践中进行刻意练习和思考。目前是对于理解MVVM架构打下了前提。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/587420.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

报表控件FastReport使用指南——如何打开WebP格式的图片

FastReport 是功能齐全的报表控件&#xff0c;可以帮助开发者可以快速并高效地为.NET&#xff0c;VCL&#xff0c;COM&#xff0c;ActiveX应用程序添加报表支持&#xff0c;由于其独特的编程原则&#xff0c;现在已经成为了Delphi平台最优秀的报表控件&#xff0c;支持将编程开…

SWUST软件技术基础实验笔记

目录 前言 堆栈的操作 实验目的 实验要求 单链表操作 实验目的 实验要求 二叉树操作 实验目的 实验要求 查找与排序 实验目的 实验要求 查找算法 排序算法 实验总结 前言 软件技术基础实验分为四个部分&#xff0c;涵盖了堆栈的操作、单链表操作、二叉树操作以…

微前端——qiankun配置方法

什么是微前端 微前端是指存在于浏览器中的微服务&#xff0c;其借鉴了微服务的架构理念&#xff0c;将微服务的概念扩展到了前端。 如果对微服务的概念比较陌生的话&#xff0c;可以简单的理解为微前端就是将一个大型的前端应用拆分成多个模块&#xff0c;每个微前端模块可以…

Qt文件系统源码分析—第八篇QFileSystemWatcher

深度 本文主要分析Windows平台&#xff0c;Mac、Linux暂不涉及 本文只分析到Win32 API/Windows Com组件/STL库函数层次&#xff0c;再下层代码不做探究 本文QT版本5.15.2 类关系图 QTemporaryFile继承QFile QFile、QSaveFile继承QFileDevice QFileDevice继承QIODevice Q…

RK最强ARM系列之RK3588+AI+Ethercat(linux +xenomai+igh)实时解决方案

RK3588是瑞芯微新一代旗舰级高端处理器&#xff0c;具有高算力、低功耗、超强多媒体、丰富数据接口等特点。搭载四核A76四核A55的八核CPU和ARM G610MP4 GPU&#xff0c;内置6.0TOPs算力的NPU。 有五大技术优势 1. 内置多种功能强大的嵌入式硬件引擎&#xff0c;支持8K60fps 的…

5.29-kubernetes learning

文章目录 HomeGet StartedThe kubernetes network model First of all &#xff0c;we should understand the layout of this official website page. Home The Home chapter is that the official website has manuals for different versions of k8s ,and then generally…

chatgpt赋能python:Python中单词排序的方法—从入门到精通

Python中单词排序的方法—从入门到精通 Python是一门很流行的编程语言&#xff0c;它是一门被广泛使用的高级编程语言&#xff0c;为开发者提供了丰富的工具和库&#xff0c;在处理字符串、文本信息时也有着广泛的应用。本文主要介绍在Python中进行单词排序的方法。 什么是单…

python pycharm的安装教程

pycharm安装教程&#xff0c;超详细_皮小孩ls的博客-CSDN博客目录 前言 python的安装教程&#xff1a; 1.下载地址&#xff1a; 2. 安装 1&#xff09;customize installation 勾选 use 2&#xff09;.默认 . 3&#xff09;. 选择安装位置 4&#xff09;.耐心等待&…

【CSSpart4--盒子模型】

CSSpart4--盒子模型 网页布局的三大核心&#xff1a;盒子模型&#xff0c;浮动&#xff0c;定位网页布局的过程&#xff08;本质&#xff09;&#xff1a;盒子模型的组成四部分&#xff1a;边框&#xff0c;内容&#xff0c;内边距&#xff0c;外边距 一 、盒子边框border:1.1 …

Queue 队列的实现与应用

目录 1.概念2.常用的队列方法2.1 方法2.2 代码 3.自己实现队列3.1 构造MyQueue3.2 入队列offer()3.3 出队列poll()3.4 获得队头peek()3.5 是否为空isEmpty()3.6 获得队列大小size() 4.循环队列4.1 概念4.2 解析4.3 如何判断队列满4.4 代码&#xff08;保留一个位置实现&#xf…

vue+nodejs校园二手物品交易市场网站_xa1i4

。为满足如今日益复杂的管理需求&#xff0c;各类管理系统程序也在不断改进。本课题所设计的校园二手交易市场&#xff0c;使用vue框架&#xff0c;Mysql数据库、nodejs语言进行开发&#xff0c;它的优点代码不能从浏览器查看&#xff0c;保密性非常好&#xff0c;比其他的管理…

轻松实现动态人脸识别,AidLux加速智慧城市场景化应用落地

随着AI技术进入全新发展阶段&#xff0c;智能物联网&#xff08;AIoT&#xff09;的渗透率进一步加深&#xff0c;应用场景不断拓展&#xff0c;人脸识别也迅速走进了人们的日常生活&#xff0c;在手机解锁、公司考勤、支付验证、天网抓捕在逃嫌犯等场景中发挥着重要作用。 人脸…

dataV教程-浅用dataV

一别多日&#xff0c;好久没有和大家相见了。其一的原因是因为公司的项目&#xff0c;其二就是因为太懒了。现在给大家浅浅的介绍一下这个好用的大屏展示框架吧。如果后续有深入的话&#xff0c;我会出一个详解版本的。 一、dataV介绍 前言:由于当前的大数据时代&#xff0c;…

Github标星60K!mall前台商城系统正式发布,支持完整订单流程!

之前有很多小伙伴问我&#xff0c;mall项目有没有前台商城系统&#xff0c;可见大家对mall项目的前台商城系统还是非常期待的。最近抽空把前台商城系统的功能给完善了&#xff0c;目前已经可以支持完整的订单流程。我已经把前台商城系统开源了&#xff0c;项目地址也放在文末了…

重磅发布!面向装备制造业服务化转型白皮书(私信获取)

《面向装备制造业服务化转型白皮书》 关于白皮书 《面向装备制造业服务化转型白皮书》通过调研160余家装备制造企业的服务化路径及模式&#xff0c;研讨支持企业开展服务型制造的系统化方案&#xff0c;希望为装备制造业服务化转型&#xff0c;探索切实有效的路径以供参考。 …

【MySQL】- 02 MySQL explain执行

目录 1.使用explain语句去查看分析结果2.MYSQL中的组合索引3.使用慢查询分析&#xff08;实用&#xff09;4.MYISAM和INNODB的锁定explain用法详解关于MySQL执行计划的局限性&#xff1a;备注&#xff1a; 1.使用explain语句去查看分析结果 如explain select * from test1 whe…

nSoftware IPWorks 2022 C++ Crack

nSoftware IPWorks 2022 C最全面的互联网组件套件&#xff0c;PKI 代理远程签署代码和文档&#xff0c;无需暴露您的私钥&#xff0c;一种安全的自托管解决方案&#xff0c;可使用集中存储的密钥实现远程代码和文档签名&#xff0c;随附的 PKCS#11 驱动程序允许与 Jarsigner、S…

小航助学题库蓝桥杯stem科技素养模拟练习试卷(中级第2套)(含题库教师学生账号)

需要在线模拟训练的题库账号请点击 小航助学编程在线模拟试卷系统&#xff08;含题库答题软件账号&#xff09;_程序猿下山的博客-CSDN博客 25. 2020 年 7 月 23 日&#xff0c;中国的火星探测器“天问一号“发射&#xff0c;开始了前往火星的 旅程。作为中国首个完全自主研发…

Vue之条件渲染

1. if分支结构 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-widt…

【分享】如何国内免费使用ChatGPT4教程

一、ChatGPT-3使用 1、ChatGPT用法总结&#xff1a; 自动化文本生成&#xff1a;可以用GPT生成文章、新闻、文本摘要&#xff0c;甚至小说、诗歌等文学作品。语音生成&#xff1a;结合语音合成技术&#xff0c;GPT可以生成自然流畅的语音&#xff0c;可以用于语音助手、交互式…