MVC笔记,加深理解

搭建MVC实现:

MVC 模式

​ MVC模式 是将程序分为三层:

​ M层(Model): 负责数据层

​ V层(View): 负责视图层

​ C层 (contraller): 控制器 负责交互

在MVC 模式中:

​ C层是 核心层: 既可以更新数据,又可以更新视图

​ V层: 可以获取数据

​ M层: 存储数据

在这里插入图片描述

MVC的主要思想 就在图中, 控制器 要获得 更新视图 更新数据。

返回一个对象,该对象中可以操作MVC,但是不可以直接访问。 是为了保护数据。

推演:

不使用MVC的代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="div"></div>
    <script>
        let data = {
            data: "我是一组数据"
        }

        // 获得元素
        var div = document.getElementById('div');
        // console.log(div);
        div.innerHTML = data.data;

        // 交互
        div.onclick = function() {
            this.style.color = 'red';
        }
    </script>
</body>
</html>

使用MVC , 先分析:

​ MVC中的M 数据层 : 是data

​ MVC中的V 视图层 : 是div元素,以及div的内容

​ MVC中的 C 控制层 : 作为交互 就是 onclick

MVC的架子, 为什么要暴露接口呢? 为了保护数据安全,不让直接操作 M V C 方法

​ 为什么都是自执行函数(IIFE) 还是为了保护数据安全。

let MVC = (function() {
    //  M层 负责 数据层
    let M = ()();
    //  V层  负责视图层
    let V = ()();
    //  C层   负责交互层
    let C = ()();
   
    // 暴露接口
    return {
        Method(){}
    }
})()

然后开始补充内容: 思路 数据层 应该有 获得数据方法 , 存储数据的方法

​ M层 就会是

//  M层 负责 数据层
let M = (function(){

        // 定义数据对象  用来存放 数据
        let data = {};

    return {
        // 添加数据的方法
        add() {},
        // 获得数据的方法
        get() {}
    }
})();

​ 然后思考 视图层将会有什么呢?

​ 视图层 要有一个对象, 用来存放 视图的方法

​ 同样为了 保护 视图的方法。 我们返回接口 。这个接口有两个方法

​ (为什么会这样分开呢? 观察者模式)

​ 观察者模式博客::::

​ 添加视图的方法

​ 执行视图的方法

//  V层  负责视图层
let V = (function(){
    // 定义一个数据对象  用来存放  视图的方法
    let data = {}; 
    return {
        // 咱们把  添加方法  和 执行  分开做。  添加只管添加的方法。  渲染进行执行函数的操作
        // 添加视图的方法 
        add(){},
        // 渲染视图的方法
        render(){},
    }
})();

思考 C层 控制层 这层主要的作用是 复制交互

​ 要一个对象 用来存放 交互的方法

​ 同样 为了保护 交互的方法 我们使用 return 接口

​ 接口中 要有 添加交互的方法 和执行交互的方法

//  C层   负责交互层  这层主要有很多  交互的方法
let C = (function(){
	// 用来存放  交互的方法
    let data = {};
    return {
        // 添加交互的方法
        add(){},
        // 初始化函数。  作用就是   交互的方法的实现
        init(){}
    }
})();

那么MVC返回的接口 , 也可以填充了

​ 思考: 将要暴露什么接口: 对外界 肯定是要暴露 添加数据 添加视图 添加控制器的方法

let MVC() {
	return {
		// 添加数据的方法
		addModel(name, data) {
			M.add(name, data);
		},

		// 添加视图
		addView(name, fn) {
			V.add(name, fn);
		},
		
		// 添加控制器
		addCtrl(name, fn) {
			C.add(name, fn);
		},
	}
}()

此时大概的框架就有了

let MVC = (function() {
    //  M层 负责 数据层
    let M = (function(){

         // 定义数据对象  用来存放 数据
         let data = {};
        
        //  这样返回的方法  是为了  保护  data  数据
        return {
            // 添加数据的方法
            add() {},
            // 获得数据的方法
            get() {}
        }
    })();

    //  V层  负责视图层
    let V = (function(){
        // 定义一个数据对象  用来存放  视图的方法
        let data = {}; 
        return {
            // 咱们把  添加方法  和 执行  分开做。  添加只管添加的方法。  渲染进行执行函数的操作
            // 添加视图的方法 
            add(){},
            // 渲染视图的方法
            render(){},
        }
    })();


    //  C层   负责交互层  这层主要有很多  交互的方法
    let C = (function(){

        let data = {};
        return {
            // 添加交互的方法
            add(){},
            // 初始化函数。  作用就是   交互的方法的实现
            init(){}
        }
    })();
   
    // 暴露接口
    return {
       // 添加数据的方法
		addModel(name, data) {
			M.add(name, data);
		},

		// 添加视图
		addView(name, fn) {
			V.add(name, fn);
		},
		
		// 添加控制器
		addCtrl(name, fn) {
			C.add(name, fn);
		},
    }
})()

此时就要思考了:

在这里插入图片描述

​ C层的交互 是要更新对象, 并且 C层控制 更新视图

​ V层的渲染 是要使用到数据的

现在变成现象解释现象了

因此可以得到。 视图方法的执行 要放在 C层

​ 添加视图的方法, 放在 V层

​ 添加数据的方法, 放在M层

​ 执行的方法都放在 C层。

继续填充

M层

// M层 复杂数据层
let M = (function() {
	// 定义数据对象
	let data = {};

	// 定义接口对象  返回了两个接口  add 接口  和  get 接口
	return {
		// 添加数据
		add(name, value) {
			// 第一步将路径层级转为数组
			let pathName = name.split('.');
			// console.log(pathName);
			// 备份数据
			let result = data;
			// 循环添加数据
			for (let i = 0; i < pathName.length - 1; i++) {
				// 判断数据类型
				if (typeof result[pathName[i]] === 'object' && result[pathName[i]] != null) {
					// 说明真的是引用类型, 指向下一层
					result = result[pathName[i]];
				} else if (typeof result[pathName[i]] === 'undefined') {
					// 强制变为对象
					result[pathName[i]] = {};
					// 改变对象的指向
					result = result[pathName[i]];
				} else {
					throw new Error('不能在值类型上添加数据');
				}
			}
			// console.log(pathName[pathName.length - 1]);
			// 最后一项被赋值
			if (typeof result[pathName[pathName.length - 1]] === 'undefined') {
				result[pathName[pathName.length - 1]] = value;
			} else {
				throw new Error('已经被占用了');
			}

			// console.log(42, data);
		},
		// 获取数据
		get(name) {
			// 第一步将路径层级转为数组
			let pathName = name.split('.');
			// 备份数据
			let result = data;
			// 循环
			for (let i = 0; i < pathName.length - 1; i++) {
				// 判断当前层级是否是引用类型
				if (typeof result[pathName[i]] === 'object' && result[pathName[i]] != null) {
					// 指向下一层
					result = result[pathName[i]];
				} else {
					return null;
				}
			}

			// 遍历完成之后返回最后一项数据
			return result[pathName[pathName.length - 1]];
		}
	}
})()

V层

// V层 负责视图层
	let V = (function() {
		// 定义数据对象
		let data = {
			// view: function() {

			// }
		};

		// 定义接口对象
		return {
			// 添加视图的方法
			add(name, fn) {
				data[name] = fn;
			},
			// 渲染方法
			render(name) {
				return data[name](M);
			}
		}
	})()

C层:

// C层 添加控制器
	let C = (function() {
		// 定义数据对象
		let data = {
			// ajax: function() {}
		};

		// 返回接口对象
		return {
			// 添加控制器的方法
			add(name, fn) {
				data[name] = fn;
			},
			// 初始化方法   控制器的执行
			init() {
				for (let i in data) {
					data[i](M, V);
				}
			}
		}
	})()

整个MVC.js 的实现

// 实现MVC
let MVC = (function() {
	// M层 负责数据层
	let M = (function() {
		// 定义数据对象
		let data = {
			
		};

		// 定义接口对象
		return {
			// 添加数据
			add(name, value) {
				// 第一步将路径层级转为数组
				let pathName = name.split('.');
				// console.log(pathName);
				// 备份数据
				let result = data;
				// 循环添加数据
				for (let i = 0; i < pathName.length - 1; i++) {
					// 判断数据类型
					if (typeof result[pathName[i]] === 'object' && result[pathName[i]] != null) {
						// 说明真的是引用类型, 指向下一层
						result = result[pathName[i]];
					} else if (typeof result[pathName[i]] === 'undefined') {
						// 强制变为对象
						result[pathName[i]] = {};
						// 改变对象的指向
						result = result[pathName[i]];
					} else {
						throw new Error('不能在值类型上添加数据');
					}
				}
				// console.log(pathName[pathName.length - 1]);
				// 最后一项被赋值
				if (typeof result[pathName[pathName.length - 1]] === 'undefined') {
					result[pathName[pathName.length - 1]] = value;
				} else {
					throw new Error('已经被占用了');
				}

				// console.log(42, data);
			},
			// 获取数据
			get(name) {
				// 第一步将路径层级转为数组
				let pathName = name.split('.');
				// 备份数据
				let result = data;
				// 循环
				for (let i = 0; i < pathName.length - 1; i++) {
					// 判断当前层级是否是引用类型
					if (typeof result[pathName[i]] === 'object' && result[pathName[i]] != null) {
						// 指向下一层
						result = result[pathName[i]];
					} else {
						return null;
					}
				}

				// 遍历完成之后返回最后一项数据
				return result[pathName[pathName.length - 1]];
			}
		}
	})()
    
	// V层 负责视图层
	let V = (function() {
		// 定义数据对象
		let data = {
			// view: function() {

			// }
		};

		// 定义接口对象
		return {
			// 添加视图的方法
			add(name, fn) {
				data[name] = fn;
			},
			// 渲染方法
			render(name) {
				return data[name](M);
			}
		}
	})()

	// C层 添加控制器
	let C = (function() {
		// 定义数据对象
		let data = {
			// ajax: function() {}
		};

		// 返回接口对象
		return {
			// 添加控制器的方法
			add(name, fn) {
				data[name] = fn;
			},
			// 初始化方法  控制器的执行
			init() {
				for (let i in data) {
					data[i](M, V);
				}
			}
		}
	})()


	// 返回一个对象,该对象中可以操作M V C ,但是不可以直接访问
	return {
		// 添加数据
		// 之前定义方法的方式
		// addModel: function() {
		// 使用ES6语法  在对象字面量中 定义的方法可以省略冒号以及function关键字
		addModel(name, data) {
			M.add(name, data);
		},

		// 添加视图
		addView(name, fn) {
			V.add(name, fn);
		},
		// 添加控制器
		addCtrl(name, fn) {
			C.add(name, fn);
		},
		// 初始化方法
		install() {
			C.init();
		}
	} 
})()


使用MVC之后的代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="div"></div>
    
    <!-- 引入MVC  文件 -->
    <script src="MVC.js"></script>
    <script>

        console.log(MVC); 
        // 添加数据
        MVC.addModel('model',{ 
            data: "我是一组数据"
        });
        
        // 添加视图
        MVC.addView('view', function(M) {
            // 获得数据
            let data = M.get('model');
            
            // 获得元素
            let dom = document.getElementById('div');
            console.log(data);

            dom.innerHTML = data.data;
            // 返回元素
            return dom;
        });
        // 添加控制器
        MVC.addCtrl('ctrl', function(M, V) {
            // 获得元素
            let dom = V.render('view');

            // 添加事件
            dom.onclick = function(){
                this.style.color = 'red';
            }
        });

        // 执行控制器代码
        MVC.install();


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

MVC在项目中的应用:

视图层: 是需要返回容器的。 为什么要返回容器呢。 就是返回整个元素? 因为元素要在控制层被使用。元素有有交互。要有事件的发生。

​ 七个步骤

1、 获得容器元素

2、 获取数据

3、 定义大模板

4、 定义小模板

5、 定义变量 用来存储格式化之后的模板

6、 格式化模板

7、 上树

8、 返回容器元素

        // 返回元素
        return dom;
    });
    // 添加控制器
    MVC.addCtrl('ctrl', function(M, V) {
        // 获得元素
        let dom = V.render('view');

        // 添加事件
        dom.onclick = function(){
            this.style.color = 'red';
        }
    });

    // 执行控制器代码
    MVC.install();


</script>
````

MVC在项目中的应用:

视图层: 是需要返回容器的。 为什么要返回容器呢。 就是返回整个元素? 因为元素要在控制层被使用。元素有有交互。要有事件的发生。

​ 七个步骤

1、 获得容器元素

2、 获取数据

3、 定义大模板

4、 定义小模板

5、 定义变量 用来存储格式化之后的模板

6、 格式化模板

7、 上树

8、 返回容器元素

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值