directory

What is MVC?

MVC functions:

How to use the MVC architecture:

Effect:

Here is all the code:

Source address: https://gitee.com/DieHunter/myCode/tree/master/shopCarMVC

Back-end (nodejs) :

server.js

Data.js (store list of items)

The front end

Shopcar.html (entry page)

shop.css

JS folder:

bussiness

command

components

config

controller

event

model

utils

view

conclusion



What is MVC?

Model View Controller: Model-view-controller Generally speaking, in programming languages, Model is data, which can be understood as a database, View is the appearance of data, Controller is used to connect the behavior of the first two, common Vue adopts m-V-VM architecture, similar to MVC, but based on MVC

MVC functions:

When it comes to functions, there is a distinction between object orientation and process orientation

Process oriented is the process of solving a problem step by step, closely linked together to achieve the final result

Object oriented, is the solution of a problem is stripped away, its purpose is not to complete a step, but a thing (object) role (attribute) and behavior (method) as the core

Having said that, what’s so good about MVC?

Here’s an example: A is A front-end programmer in A company, usually with A process oriented programming, this day, very not easy to complete his hand over the heads of the living, ready to go home, at this time, the product manager came and let him change A small place, it is finished, interlocking process oriented thinking makes his code, the code coupling is strong, high cohesion, inseparable, change A place will be almost entirely

A’s brother is also A front-end programmer who usually uses object-oriented programming, but the product manager asked him to change an effect. Because he uses object-oriented programming, his code has no sense of hierarchy, and all general methods are extracted, which makes the code coupling low. If he wants to change, he can directly change related classes or methods

Of course, it can not reflect its advantages in small projects, and even make a mountain out of a molehill, overuse, and in large projects, its coupling is low, code reuse is high, build relatively fast

How to use the MVC architecture:

In my spare time, I made a simple shopping cart with MVC:

The directory structure looks something like this

Overall process of shopping cart:

The directory structure strips the Model View Controller away

Modedl layer: Stores and displays data

View: Render the page based on Model data

Controller: transfers data

Command: Operates data and obtains data

Event: Event bus, registering events

List of products:

Initialize the View layer, set up Ajax to fetch data, and then the Controller triggers events to the event bus, and then the registered events pass Ajax data to the Model to complete the initialization of the list of goods

When Model gets the commodity list data, the event of creating a commodity list is triggered by the agent set(), and the purpose of creating a list is achieved by the command operation view

Shopping cart Form:

When the user operates on the view, the registered event is triggered, and the data in the Model (the shopping cart list) is modified by Command, which in turn drives the refresh table in the View for rendering

Effect:

Here is all the code:

Source code address:Gitee.com/DieHunter/m…

Back-end (nodejs) :

server.js

/* * Back end uses Node + Express to build a simple interface, through local data, the list of goods to the front end * */
const express = require('express');
const path = require('path');
const app = express();
const shopData = require('./data/shopData.js')
let serverToken = 'hello'
app.all("*".function (req, res, next) { / / across domains
    res.header("Access-Control-Allow-Origin"."*");
    res.header("Access-Control-Allow-Headers"."content-type");
    res.header("Access-Control-Allow-Methods"."DELETE,PUT,POST,GET,OPTIONS");
    next();
});
app.use('/getShopList'.function (req, res) {
    let data = req.query
    if(! checkToken(data.token)) {// Simply obtain front-end token and verify
        res.send({
            result: 0.msg: 'token fail'
        })
        return
    }
    res.send({
        result: 1.msg: 'success'.type: 'getShopList',
        shopData
    })
})

function checkToken(teken) {
    return teken == serverToken
}
app.use('/img', express.static(path.join(__dirname, './img'))); // Use url+img to access the folder
app.use('/client', express.static(path.join(__dirname, '.. /client')));
app.listen(1024."127.0.0.1".function () {
    console.log("Service started, listening");
});
Copy the code

Data.js (store list of items)

module.exports = [{
        "select": false."id": 1001."icon": "img/1.png"."name": 0 "restaurant"."num": 0."price": 10."sum": 0."delete": false
    },
    {
        "select": false."id": 1002."icon": "img/2.png"."name": 1 "restaurant"."num": 0."price": 20."sum": 0."delete": false
    },
    {
        "select": false."id": 1003."icon": "img/3.png"."name": 2 "the restaurant"."num": 0."price": 30."sum": 0."delete": false
    },
    {
        "select": false."id": 1004."icon": "img/4.png"."name": 3 "restaurant"."num": 0."price": 40."sum": 0."delete": false
    },
    {
        "select": false."id": 1005."icon": "img/5.png"."name": 4 "restaurant"."num": 0."price": 50."sum": 0."delete": false
    },
    {
        "select": false."id": 1006."icon": "img/6.png"."name": 5 "restaurant"."num": 0."price": 60."sum": 0."delete": false
    },
    {
        "select": false."id": 1007."icon": "img/7.png"."name": 6 "restaurant"."num": 0."price": 70."sum": 0."delete": false
    },
    {
        "select": false."id": 1008."icon": "img/8.png"."name": 7 "restaurant"."num": 0."price": 80."sum": 0."delete": false
    },
    {
        "select": false."id": 1009."icon": "img/9.png"."name": 8 "restaurant"."num": 0."price": 90."sum": 0."delete": false
    },
    {
        "select": false."id": 1010."icon": "img/10.png"."name": 9 "restaurant"."num": 0."price": 100."sum": 0."delete": false}]Copy the code

The front end

Shopcar.html (entry page)

<! DOCTYPEhtml>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
	<title>shopCar</title>
	<link rel="stylesheet" href="./src/style/shop.css">
</head>

<body>
	<script type="module">
		View: render the page according to the model data. Controller: pass the data. Command: manipulate the data. Event bus, register event commodity list: Initialize the View layer, set up Ajax to fetch data, and then trigger events to the event bus from the Controller, and then pass Ajax data to the Model from the registered event to complete the item list initialization. When the Model gets the item list data, the new item list event is triggered by the agent set(). When the user manipulates the view, the registration event is triggered, and the data in the Model (the shopping cart list) is modified by Command, which then drives the refresh table in the view to render */
		import ShopView from './src/js/view/ShopView.js'
		// Instantiate the View layer entry function
		new ShopView()
	</script>
</body>

</html>
Copy the code

shop.css

* {
    margin: 0;
    padding: 0;
}

.shopBox {
    overflow: hidden;
    width: 1000px;
    margin: 50px auto 0;
}

.liItem {
    float: left;
    list-style: none;
    padding: 10px;
    width: 150px;
    height: 200px;
    text-align: center;
    border: 1px solid lightcoral;
}

.liItem img {
    width: 100px;
    height: 100px;
}

.leftBtn..rightBtn {
    width: 30px;
    height: 30px;
    background: white;
    border: 1px solid black;
    font-size: 25px;
    line-height: 30px;
}

.text {
    width: 50px;
    height: 26px;
    display: inline-block;
    vertical-align: bottom;
    text-align: center;
}

table {
    font-size: 30px;
    width: 1200px;
    border: 1px solid lightcoral;
    border-collapse: collapse;
    margin: 50px auto;
}

.checkbox {
    width: 30px;
    height: 30px;
}

td {
    border: 1px solid lightcoral;
    text-align: center;
    vertical-align: middle;
}

td button {
    width: 150px;
    height: 60px;
}

.numBox {
    width: 150px;
    height: 30px;
    margin: auto;
    position: relative;
}

.numBox>button {
    width: 40px;
    height: 42px;
    background-color: white;
    border: 1px solid # 000000;
}

.numBox>input {
    width: 70px;
    height: 40px;
    border: 1px solid # 000000;
    border-left: none;
    border-right: none;
    text-align: center;
}
Copy the code

JS folder:

bussiness

  • Ajax.js

    import ShopEvent from '.. /event/ShopEvent.js'
    import Utils from '.. /utils/Utils.js'
    import Api from '.. /config/Api.js'
    import ShopController from '.. /controller/ShopController.js'
    export default class Ajax {//Ajax class for requesting backend or local data
        // Ajax request function
        static AjaxTool(method = Api.GET, url, data) {
            let xhr;
            if (window.ActiveXObject) { / / ie browser
                xhr = new ActiveXObject("Microsoft.XMLHTTP");
            } else if (window.XMLHttpRequest) { // Other browsers
                xhr = new XMLHttpRequest();
            }
            url = Api.URL + Api.PORT + Api.PATH + url
            if(method ! == Api.POST) { method = Api.GET url = Utils.urlJoin(url, data) data =null
            } else {
                method = Api.POST
            }
            xhr.open(method, url);
            xhr.send(data ? JSON.stringify(data) : ' ')
            xhr.addEventListener('load', Ajax.loadHandler) // The Ajax class is static and cannot use this
        }
        static loadHandler(e) {
            / / this point to XHR
            let xhr = e.currentTarget;
            if (xhr.readyState === 4 && xhr.status === 200) {
                Ajax.data = xhr.response
            } else {
                Ajax.data = 'error'}}static set data(value) { // Use the set object proxy mode instead of the request data callback function.
            let res = JSON.parse(value)
            switch (res.result) {
                case 1:
                    console.log(res.msg)
                    ShopController.dispatch(ShopEvent.GET_DATA, res)// Get the data and do nothing else. Throw the data into the Event bus through the Event bus
                    break;
                case 0:
                    console.log('Load failed')
                    console.log(res.msg)
                    break;
                default:
                    break; }}}Copy the code

     

command

  • MainCommand (Command summary)

    import GetDataCommand from '.. /command/GetDataCommand.js'
    import CreateListCommand from '.. /command/CreateListCommand.js'
    import CreateTableCommand from '.. /command/CreateTableCommand.js'
    import AddItemCommand from '.. /command/AddItemCommand.js'
    import DelItemCommand from '.. /command/DelItemCommand.js'
    import ReduceItemCommand from '.. /command/ReduceItemCommand.js'
    import ChangeItemCommand from '.. /command/ChangeItemCommand.js'
    import SelectItemCommand from '.. /command/SelectItemCommand.js'
    export default {
        GetDataCommand,
        CreateListCommand,
        CreateTableCommand,
        AddItemCommand,
        DelItemCommand,
        ReduceItemCommand,
        ChangeItemCommand,
        SelectItemCommand
    }
    Copy the code

     

  • GetDataCommand (Get a list of items)

    import ShopModel from '.. /model/ShopModel.js'
    export default class GetDataCommand { // Action class for executing commands sent by the CTRL layer through events
        constructor(){}eventHandler(e) { // Use dynamic methods instead of static static methods, because the method will be used multiple times, instantiated with new AddShopCommand and called
            let {
                data
            } = e
            ShopModel.getInstance().shopList = data.shopData// Send the ajax-fetched data to Model}}Copy the code

     

  • CreateListCommand (Create a list of items)

    import CreateList from '.. /view/CreateList.js'
    export default class CreateListCommand { // Action class for executing commands sent by the CTRL layer through events
        constructor() {// Create a list of items
    
        }
        eventHandler(e) { // Use dynamic methods instead of static static methods, because the method will be used multiple times, instantiated with new AddShopCommand and called
            let {
                data
            } = e
            for (let i = 0; i < data.length; i++) {
                let createList = new CreateList(document.body)
                createList.shopList = data[i]
            }
        }
    }
    Copy the code

     

  • CreateTableCommand Create shopping cart table

    import CreateTable from '.. /view/CreateTable.js'
    export default class ShopCommand { // Action class for executing commands sent by the CTRL layer through events
        constructor() {// Refresh the cart table
    
        }
        eventHandler(e) { // Use dynamic methods instead of static static methods, because the method will be used multiple times, instantiated with new AddShopCommand and called
            let {
                data
            } = e
            let createTable = new CreateTable(document.body)
            createTable.shoppingList = data
        }
    }
    Copy the code

     

  • AddItemCommand (add items)

    import ShopModel from '.. /model/ShopModel.js'
    export default class AddItemCommand { // Action class for executing commands sent by the CTRL layer through events
        constructor() { // Add new items
    
        }
        eventHandler(e) { // Use dynamic methods instead of static static methods, because the method will be used multiple times, instantiated with new AddShopCommand and called
            let {
                data
            } = e
            AddItemCommand.addItem(ShopModel.getInstance().shoppingList, data)
        }
        static addItem(list, data) { // iterate to query for an item increase or decrease
            let arr = list.filter(function (item) {
                return item.id === data.id;
            }); // If there is a return value, the item is operated on (between 1 and 99, if 0, delete directly).
            if (arr.length == 0) {
                data.num++;
                data.sum = data.num * data.price;
                list.push(data);
            } else if (arr[0].num < 99) {
                arr[0].num++;
                arr[0].sum = arr[0].num * arr[0].price;
            }
            ShopModel.getInstance().shoppingList = list
        }
    }
    Copy the code

     

  • ReduceItemCommand (Reduce items)

    import ShopModel from '.. /model/ShopModel.js'
    export default class ReduceItemCommand { // Action class for executing commands sent by the CTRL layer through events
        constructor() { // Reduce items
    
        }
        eventHandler(e) { // Use dynamic methods instead of static static methods, because the method will be used multiple times, instantiated with new AddShopCommand and called
            let {
                data
            } = e
            ReduceItemCommand.reduceItem(ShopModel.getInstance().shoppingList, data)
        }
        static reduceItem(list, data) { // iterate to query for an item increase or decrease
            let arr = list.filter(function (item) {
                return item.id === data.id;
            }); // If there is a return value, the item is operated on (between 1 and 99, if 0, delete directly).
            if (arr[0].num > 1) {
                arr[0].num--;
                arr[0].sum = arr[0].num * arr[0].price;
            } else {
                data.num = 0; // Initialize shopList in model here, otherwise fake delete (delete stack quantity)
                list = list.filter(function (item) {
                    returnitem.id ! == data.id; }); } ShopModel.getInstance().shoppingList = list } }Copy the code

     

  • ChangeItemCommand (Modifies the number of items)

    import ShopModel from '.. /model/ShopModel.js'
    export default class ChangeItemCommand { // Action class for executing commands sent by the CTRL layer through events
        constructor() { // Change the number of items
    
        }
        eventHandler(e) { // Use dynamic methods instead of static static methods, because the method will be used multiple times, instantiated with new AddShopCommand and called
            let {
                data
            } = e
            ChangeItemCommand.changeItem(ShopModel.getInstance().shoppingList, data)
        }
        static changeItem(list, data) {
            let arr = list.filter(function (item) {
                return item.id === data.id;
            });
            arr[0].sum = arr[0].num * arr[0].price;
            ShopModel.getInstance().shoppingList = list
        }
    }
    Copy the code

     

  • DelItemCommand (delete an item)

    import ShopModel from '.. /model/ShopModel.js'
    export default class DelItemCommand { // Action class for executing commands sent by the CTRL layer through events
        constructor() { // Delete the item
    
        }
        eventHandler(e) { // Use dynamic methods instead of static static methods, because the method will be used multiple times, instantiated with new AddShopCommand and called
            let {
                data
            } = e
            DelItemCommand.delItem(ShopModel.getInstance().shoppingList, data)
        }
        static delItem(list, data) { // iterate to query for an item increase or decrease
            data.num = 0; // Initialize shopList in model here, otherwise fake delete (delete stack quantity)
            data.select = false; // Initialize shopList in model here, otherwise fake delete (delete stack quantity)
            ShopModel.getInstance().shoppingList = list.filter(function (item) { // Array filter function, return the array whose ID attribute is not equal to the current ID, that is, delete the currently selected object, and reassign the value
                return item.id !== data.id;
            });
        }
    }
    Copy the code

     

  • SelectItemCommand

    import ShopModel from '.. /model/ShopModel.js'
    export default class SelectItemCommand { // Action class for executing commands sent by the CTRL layer through events
        constructor(){}eventHandler(e) { // Use dynamic methods instead of static static methods, because the method will be used multiple times, instantiated with new AddShopCommand and called
            let {
                data
            } = e
            SelectItemCommand.selItem(ShopModel.getInstance().shoppingList, data)
        }
        static selItem(list, data) { // iterate to query for an item increase or decrease
            if(! data) {/ / the marqueelist.checkedAll = ! list.checkedAll list.map(function (item) {
                    item.select = list.checkedAll; // Other option boxes are in the same state as the full option boxes})}else { / / radio buttons
                list.checkedAll = 1 // counter is used to check whether all is selected
                list.map(function (item) { // select one of the tables (checkAll is executed when the table is initialized)
                    if(item.id === data.id) { item.select = ! item.select } list.checkedAll *= item.select }) } ShopModel.getInstance().shoppingList = list } }Copy the code

     

components

  • Counter (Counter component)

    import ShopEvent from '.. /event/ShopEvent.js'
    import ShopController from '.. /controller/ShopController.js'
    import Utils from '.. /utils/Utils.js'
    export default class Counter { // Counter component
        constructor(_data, _parentEle) {
            this.data = _data
            this.parentEle = _parentEle
            this.ele = this.createCounter()
        }
        createCounter() { // Create a quantity counter
            let div = Utils.createEle('div', {}, {
                className: 'numBox'
            })
            this.parentEle.appendChild(div);
            let leftBtn = this.createMark(div, 'reduce') // Reduce the merchandise button
            let input = Utils.createEle('input', {}, {
                type: 'text'.value: this.data.num
            })
            div.appendChild(input);
            let rightBtn = this.createMark(div, 'add') // Add product button
            leftBtn.addEventListener("click".this.reduceItemEvent);
            rightBtn.addEventListener("click".this.addItemEvent);
            input.addEventListener("input", Utils.throttle(this.changeItemEvent, 500)); / / throttling
            return div;
        }
        createMark(parentEle, type) { // Determine whether to increase or decrease keys
            let markBtn = Utils.createEle('button', {}, {
                textContent: type == "add" ? '+' : The '-'
            })
            parentEle.appendChild(markBtn);
            return markBtn
        }
        addItemEvent = e= > { // When a new item is added, an event is thrown to the command control model to modify the data and refresh the table
            ShopController.dispatch(ShopEvent.ADD_SHOPIING_ITEM, this.data)
        }
        reduceItemEvent = e= > { // Reduce items
            ShopController.dispatch(ShopEvent.REDUCE_SHOPIING_ITEM, this.data)
        }
        changeItemEvent = e= > { // Modify the item
            e.target.value = this.data.num = this.checkNumber(e.target.value)
            ShopController.dispatch(ShopEvent.CHANGE_SHOPIING_ITEM, this.data)
        }
        checkNumber(value) { // Filter data
            value = value.replace(/[^0-9]/g.""); // Only numbers are allowed
            if (value === "0") { // If =0, set to 1
                value = "1";
            }
            if (value.length > 2) { // If the input is more than 2 bits, make the value 99 (Max. 99 bits)
                value = "99";
            }
            if (value.length === 0) { // If there is no input, set it to 1
                value = "1";
            }
            return value
        }
    }
    Copy the code

     

config

  • Api

    export default class Api {// Interface configuration class
        static URL = "http://127.0.0.1";
        static PORT = ": 1024";
        static PATH = '/'
        static GET = "get";
        static POST = "post";
        static IMGPATH = Api.URL + Api.PORT + Api.PATH;
        static ServerApi = {
            getShopList: 'getShopList' // Get the list of items}}Copy the code

     

controller

  • ShopController (control layer, do event conduction, data transmission)

    export default class ShopController extends EventTarget { // The control layer handles user interaction, routing, and input. The model View Controller is stripped away, and the data is routed through the event listener cast in the Controller
        constructor() { // Inherits the event object, which is used to throw custom events
            super(a); }static get instance() {  / / singleton written with Java getinstance similar, new generates a new object, memory, and so to write can give you an existing reference use, save effectiveness, if only use the get + property name instead of a read-only property set, only allow calls, cannot be modified
            if(! ShopController._instance) {Object.defineProperty(ShopController, "_instance", {
                    value: new ShopController()
                })
            }
            return ShopController._instance;
        }
        static dispatch(type, data) { // Throw a defined event to pass data
            let event = new Event(type)
            event.data = data
            ShopController.instance.dispatchEvent(event)
        }
        static runCommand(type, Command) { // Observer mode, which calls a method in another class when a custom event is triggered, corresponds to Dispatch, similar to addEventlistener, but replaces the callback function with a dynamic method in the class
            var command = new Command()
            ShopController.instance.addEventListener(type, command.eventHandler)
        }
    }
    Copy the code

     

event

  • ShopEvent

    export default class ShopEvent {
        constructor(){}// All custom event names
        static GET_DATA = 'get_data'
        static GET_SHOP_LIST = 'get_shop_list'
        static GET_SHOPIING_LIST = 'get_shopping_list'
        static ADD_SHOPIING_ITEM = 'add_shopping_item'
        static DEL_SHOPIING_ITEM = 'del_shopping_item'
        static REDUCE_SHOPIING_ITEM = 'reduce_shopping_item'
        static CHANGE_SHOPIING_ITEM = 'change_shopping_item'
        static SELECT_SHOPIING_ITEM = 'select_shopping_item'
    }
    Copy the code

     

  • EventGroup (Event Bus)

    import ShopEvent from './ShopEvent.js'
    import ShopController from '.. /controller/ShopController.js'
    import MainCommand from '.. /command/MainCommand.js'
    let {
        GetDataCommand,
        CreateListCommand,
        CreateTableCommand,
        AddItemCommand,
        DelItemCommand,
        ReduceItemCommand,
        ChangeItemCommand,
        SelectItemCommand
    } = MainCommand
    export default class EventGroup { // The event bus, which registers all the business logic of the Model layer and other layers, communicates through the event mechanism in the Controller layer
        constructor() {
            /* 1. After Ajax gets the data, the method in GetDataCommand is triggered to pass the data to the Model layer, and CreateListCommand is called from the Model layer to create item list 2. CreateTableCommand 3 is triggered by any action the user makes to the item, which modifies the Model to trigger CreateTableCommand. CreateTableCommand 4 is driven by AddItemCommand, which is triggered when the list of items is clicked or the plus button is clicked. AddItemCommand modifies the data in the Model using AddItemCommand. Click the item minus button and trigger the ReduceItemCommand to modify the data in the Model to drive CreateTableCommand 5. CreateTableCommand 6 is driven by DelItemCommand when the Delete item button is clicked, which deletes the data in the Model. CreateTableCommand 7 is driven by the ChangeItemCommand that is triggered when the number of items is changed, updating the data in the Model. SelectItemCommand is triggered when an item is selected, updating the data in the model to drive CreateTableCommand */
            ShopController.runCommand(ShopEvent.GET_DATA, GetDataCommand)// Get item list data
            ShopController.runCommand(ShopEvent.GET_SHOP_LIST, CreateListCommand)// Create an item list
            ShopController.runCommand(ShopEvent.GET_SHOPIING_LIST, CreateTableCommand)// Refresh the cart table
            ShopController.runCommand(ShopEvent.ADD_SHOPIING_ITEM, AddItemCommand)// Add item or quantity plus one
            ShopController.runCommand(ShopEvent.DEL_SHOPIING_ITEM, DelItemCommand)// Delete the item
            ShopController.runCommand(ShopEvent.REDUCE_SHOPIING_ITEM, ReduceItemCommand)// Quantity of goods minus 1
            ShopController.runCommand(ShopEvent.CHANGE_SHOPIING_ITEM, ChangeItemCommand)// Change the number of items
            ShopController.runCommand(ShopEvent.SELECT_SHOPIING_ITEM, SelectItemCommand)// Select the item}}Copy the code

     

model

  • ShopModel (Model layer for data storage and data logic)

    import ShopEvent from '.. /event/ShopEvent.js'
    import ShopController from '.. /controller/ShopController.js'
    export default class ShopModel { // The model layer is used for data storage and data logic. The data is passed through the event handling mechanism (controller), and the data is manipulated by the command
        constructor() {
            this._shopList = null
            this._shoppingList = []
        }
    
        static getInstance() { / / singleton written with Java getinstance similar, new generates a new object, memory, and so to write can give you an existing reference use, save effectiveness, if only use the get + property name instead of a read-only property set, only allow calls, cannot be modified
            if(! ShopModel._instance) {Object.defineProperty(ShopModel, "_instance", {
                    value: new ShopModel()
                })
            }
            return ShopModel._instance;
        }
        set shopList(value) {// Set the list of items
            this._shopList = value;
            ShopController.dispatch(ShopEvent.GET_SHOP_LIST, value)
        }
        get shopList() {
            return this._shopList
        }
        set shoppingList(value) {// When data is modified, drive the view to refresh the table
            this._shoppingList = value;
            ShopController.dispatch(ShopEvent.GET_SHOPIING_LIST, value)
        }
        get shoppingList() {
            return this._shoppingList
        }
    }
    Copy the code

     

utils

  • Utils (Utility classes)

    export default class Utils { / / tools
    	// Concatenate the object into the URL
    	static urlJoin(url, obj) {
    		var list = []
    		for (var key in obj) {
    			if (obj.hasOwnProperty(key)) {
    				list.push(`${key}=${obj[key]}`)}}return `${url}?${list.join('&')}`
    	}
    	static createEle(ele, style, attribute) { // Add tags, set attributes and styles
    		let element = document.createElement(ele)
    		if (style) {
    			for (let key instyle) { element.style[key] = style[key]; }}if (attribute) {
    			for (let key inattribute) { element[key] = attribute[key]; }}return element
    	}
    	// function throttling
    	static throttle(fn, time) {
    		let _timer = null
    		return function () {
    			if (_timer) {
    				clearTimeout(_timer)
    				_timer = null
    			}
    			_timer = setTimeout(fn.bind(this. arguments), time) } } }Copy the code

     

view

  • ShopView (View layer, for element rendering, displaying data)

    import Api from '.. /config/Api.js'
    import AJAX from '.. /bussiness/Ajax.js'
    import EventGroup from '.. /event/EventGroup.js'
    export default class ShopView { // View layer, used for element rendering, display data, based on (model) data creation
        constructor() {
            new EventGroup() // Register all custom events for data transfer
            AJAX.AjaxTool(Api.GET, Api.ServerApi.getShopList, { // Request the server shopping cart list
                token: 'hello'// Send the token obtained from the backend for authentication. The token is not obtained here and is replaced with a character}}})Copy the code

     

  • CreateList (list view)

    import Api from '.. /config/Api.js'
    import Utils from '.. /utils/Utils.js'
    import ShopEvent from '.. /event/ShopEvent.js'
    import ShopController from '.. /controller/ShopController.js'
    
    export default class CreateList { // View layer, used for element rendering, display data, based on (model) data creation
        constructor(parentEle) {
            this.parentEle = parentEle
            this._shopList = null
        }
        set shopList(value) { // Use the object proxy to render the list of items whenever the data changes
            if (this._shopList) {
                this.createListEle(this._shopList, this.parentEle)
                return;
            }
            this._shopList = value
            this.createListEle(value, this.parentEle)
        }
        get shopList() {
            return this._shopList
        }
        createListEle(data, parentEle) {
            let li = Utils.createEle('li', {}, {
                'className': 'liItem'
            })
            let img = Utils.createEle('img', {}, {
                'src': Api.IMGPATH + data.icon
            })
            let title = Utils.createEle('div', {}, {
                'textContent': data.name
            })
            let price = Utils.createEle('span', {}, {
                'textContent': data.price + "Yuan"
            })
            li.appendChild(img);
            li.appendChild(title);
            li.appendChild(price);
            li.addEventListener('click'.this.addItemEvent)
            parentEle.appendChild(li);
        }
        addItemEvent = e= > { // When the user clicks add item, the data is sent through the Controller layer to the event bus, which drives the Model layer and modifies the data, and then the Model provides the data refresh table
            ShopController.dispatch(ShopEvent.ADD_SHOPIING_ITEM, this.shopList)
        }
    }
    Copy the code

     

conclusion

In general, MVC architecture is a design concept often used by many languages in large projects. It improves code reuse and reduces coupling, making it shine in large projects. In fact, it is not difficult to find that things in life and MVC have similar things in common