婚慶攝影企業(yè)網(wǎng)站企業(yè)seo顧問服務(wù)
?MVVM(Model-View-ViewModel)是一種軟件設(shè)計模式,MVVM模式由三個主要部分組成:
?Model(模型)?:負責管理應(yīng)用程序的業(yè)務(wù)邏輯和數(shù)據(jù)。它不關(guān)心UI如何展示數(shù)據(jù),主要負責與服務(wù)器通信和數(shù)據(jù)處處理?。
?View(視圖)?:直接與用戶交互的界面,負責展示數(shù)據(jù)。視圖不包含業(yè)務(wù)邏輯,只負責數(shù)據(jù)的展示?。
?ViewModel(視圖模型)?:作為視圖和模型之間的橋梁,包含UI邏輯,通過數(shù)據(jù)綁定機制驅(qū)動視圖的變化。它處理用戶的輸入并將結(jié)果傳遞給模型?。
MVVM的核心機制和優(yōu)勢
?數(shù)據(jù)綁定?是MVVM的核心機制,它允許視圖和視圖模型之間的自動同步,無需手動編寫繁瑣的代碼來更新界面?。
這種設(shè)計模式的主要優(yōu)勢包括:
?解耦?:視圖和模型完全解耦,視圖模型管理兩者的交互,提高了代碼的可維護性和擴展性?。
?可測試性?:由于視圖模型不依賴于視圖,可以通過單元測試來驗證業(yè)務(wù)邏輯的正確性,而不需要啟動UI環(huán)境?。
?提高開發(fā)效率?:通過數(shù)據(jù)綁定和事件處理,簡化了開發(fā)過程,減少了手動同步數(shù)據(jù)的需要?。
項目結(jié)構(gòu)
mvvm_example/
├── main.cpp
├── view.h
├── view.cpp
├── viewmodel.h
├── viewmodel.cpp
├── model.h
└── model.cpp
代碼實現(xiàn)
model.h
#ifndef MODEL_H
#define MODEL_H#include <QObject>
#include <QString>class Model : public QObject
{Q_OBJECTQ_PROPERTY(QString data READ data WRITE setData NOTIFY dataChanged)public:explicit Model(QObject *parent = nullptr);QString data() const;void setData(const QString &newData);signals:void dataChanged();private:QString m_data;
};#endif // MODEL_H
model.cpp
#include "model.h"Model::Model(QObject *parent) : QObject(parent)
{
}QString Model::data() const
{return m_data;
}void Model::setData(const QString &newData)
{if (m_data != newData) {m_data = newData;emit dataChanged();}
}
viewmodel.h
#ifndef VIEWMODEL_H
#define VIEWMODEL_H#include <QObject>
#include "model.h"class ViewModel : public QObject
{Q_OBJECTQ_PROPERTY(QString displayData READ displayData NOTIFY displayDataChanged)public:explicit ViewModel(Model *model, QObject *parent = nullptr);QString displayData() const;signals:void displayDataChanged();public slots:void onModelDataChanged();void setViewModelData(const QString &newData);private:Model *m_model;
};#endif // VIEWMODEL_H
viewmodel.cpp
#include "viewmodel.h"ViewModel::ViewModel(Model *model, QObject *parent) : QObject(parent), m_model(model)
{connect(m_model, &Model::dataChanged, this, &ViewModel::onModelDataChanged);
}QString ViewModel::displayData() const
{return m_model->data();
}void ViewModel::onModelDataChanged()
{emit displayDataChanged();
}void ViewModel::setViewModelData(const QString &newData)
{m_model->setData(newData);
}
view.h
#ifndef VIEW_H
#define VIEW_H#include <QWidget>
#include "viewmodel.h"QT_BEGIN_NAMESPACE
namespace Ui { class View; }
QT_END_NAMESPACEclass View : public QWidget
{Q_OBJECTpublic:explicit View(ViewModel *viewModel, QWidget *parent = nullptr);~View();private slots:void on_pushButton_clicked();void updateLabel(const QString &data);private:Ui::View *ui;ViewModel *m_viewModel;
};
#endif // VIEW_H
view.cpp
#include "view.h"
#include "ui_view.h"View::View(ViewModel *viewModel, QWidget *parent): QWidget(parent), ui(new Ui::View), m_viewModel(viewModel)
{ui->setupUi(this);// 綁定 ViewModel 的 displayDataChanged 信號到更新標簽的槽函數(shù)connect(m_viewModel, &ViewModel::displayDataChanged, this, [this]() {updateLabel(m_viewModel->displayData());});// 綁定按鈕點擊信號到槽函數(shù)connect(ui->pushButton, &QPushButton::clicked, this, &View::on_pushButton_clicked);
}View::~View()
{delete ui;
}void View::on_pushButton_clicked()
{QString input = ui->lineEdit->text();m_viewModel->setViewModelData(input);
}void View::updateLabel(const QString &data)
{ui->label->setText(data);
}
main.cpp
#include "view.h"
#include "model.h"
#include "viewmodel.h"
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);Model model;ViewModel viewModel(&model);View view(&viewModel);view.show();return a.exec();
}
在上述代碼里,MainWindow
類實際上就充當了 View
的角色。不過為了更清晰地體現(xiàn) View
的概念,我們可以把界面相關(guān)的操作進一步封裝,并且更明確地展示 View
、ViewModel
和 Model
之間的交互。以下是改進后的代碼:
項目結(jié)構(gòu)
mvvm_example/
├── main.cpp
├── view.h
├── view.cpp
├── viewmodel.h
├── viewmodel.cpp
├── model.h
└── model.cpp
代碼實現(xiàn)
model.h
#ifndef MODEL_H
#define MODEL_H#include <QObject>
#include <QString>class Model : public QObject
{Q_OBJECTQ_PROPERTY(QString data READ data WRITE setData NOTIFY dataChanged)public:explicit Model(QObject *parent = nullptr);QString data() const;void setData(const QString &newData);signals:void dataChanged();private:QString m_data;
};#endif // MODEL_H
model.cpp
#include "model.h"Model::Model(QObject *parent) : QObject(parent)
{
}QString Model::data() const
{return m_data;
}void Model::setData(const QString &newData)
{if (m_data != newData) {m_data = newData;emit dataChanged();}
}
viewmodel.h
#ifndef VIEWMODEL_H
#define VIEWMODEL_H#include <QObject>
#include "model.h"class ViewModel : public QObject
{Q_OBJECTQ_PROPERTY(QString displayData READ displayData NOTIFY displayDataChanged)public:explicit ViewModel(Model *model, QObject *parent = nullptr);QString displayData() const;signals:void displayDataChanged();public slots:void onModelDataChanged();void setViewModelData(const QString &newData);private:Model *m_model;
};#endif // VIEWMODEL_H
viewmodel.cpp
#include "viewmodel.h"ViewModel::ViewModel(Model *model, QObject *parent) : QObject(parent), m_model(model)
{connect(m_model, &Model::dataChanged, this, &ViewModel::onModelDataChanged);
}QString ViewModel::displayData() const
{return m_model->data();
}void ViewModel::onModelDataChanged()
{emit displayDataChanged();
}void ViewModel::setViewModelData(const QString &newData)
{m_model->setData(newData);
}
view.h
#ifndef VIEW_H
#define VIEW_H#include <QWidget>
#include "viewmodel.h"QT_BEGIN_NAMESPACE
namespace Ui { class View; }
QT_END_NAMESPACEclass View : public QWidget
{Q_OBJECTpublic:explicit View(ViewModel *viewModel, QWidget *parent = nullptr);~View();private slots:void on_pushButton_clicked();void updateLabel(const QString &data);private:Ui::View *ui;ViewModel *m_viewModel;
};
#endif // VIEW_H
view.cpp
#include "view.h"
#include "ui_view.h"View::View(ViewModel *viewModel, QWidget *parent): QWidget(parent), ui(new Ui::View), m_viewModel(viewModel)
{ui->setupUi(this);// 綁定 ViewModel 的 displayDataChanged 信號到更新標簽的槽函數(shù)connect(m_viewModel, &ViewModel::displayDataChanged, this, [this]() {updateLabel(m_viewModel->displayData());});// 綁定按鈕點擊信號到槽函數(shù)connect(ui->pushButton, &QPushButton::clicked, this, &View::on_pushButton_clicked);
}View::~View()
{delete ui;
}void View::on_pushButton_clicked()
{QString input = ui->lineEdit->text();m_viewModel->setViewModelData(input);
}void View::updateLabel(const QString &data)
{ui->label->setText(data);
}
main.cpp
#include "view.h"
#include "model.h"
#include "viewmodel.h"
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);Model model;ViewModel viewModel(&model);View view(&viewModel);view.show();return a.exec();
}
代碼解釋
View
類
- 構(gòu)造函數(shù):接收一個
ViewModel
對象的指針,負責初始化界面并建立信號與槽的連接。 on_pushButton_clicked
槽函數(shù):當用戶點擊按鈕時,獲取輸入框中的文本,然后調(diào)用ViewModel
的setViewModelData
方法更新數(shù)據(jù)。updateLabel
槽函數(shù):當ViewModel
的displayData
發(fā)生變化時,更新界面上的標簽文本。
ViewModel
類
- 作為
View
和Model
之間的橋梁,負責處理業(yè)務(wù)邏輯和數(shù)據(jù)轉(zhuǎn)換。當Model
的數(shù)據(jù)發(fā)生變化時,會發(fā)出displayDataChanged
信號通知View
更新。
Model
類
- 負責存儲和管理數(shù)據(jù),當數(shù)據(jù)發(fā)生變化時發(fā)出
dataChanged
信號。
main.cpp
- 創(chuàng)建
Model
、ViewModel
和View
對象,并顯示View
。
通過這種方式,我們清晰地劃分了 View
、ViewModel
和 Model
的職責,實現(xiàn)了 MVVM 模式。