什么是MVVM
Model - View - ViewModel
模板 视图 视图模板
```js
对vue来说
data 就是model
div 就是 view
通过双向数据绑定把数据渲染到div里 然后导出的组件实例 就是v-m
data = {}
<div v-for="item in data">
<h2>{{item.name}}</h2>
</div>
export default {}
前端发展史
- html 全称是Hyper Text Markup Language 1993
- 最早的html 纯文本页面
- CGI技术 为了解决不同用户能看到不同页面 向浏览器输出拼接字符串,这个技术就叫CGI
- 新的创建动态HTML的方式 ASP JSP PHP (模板字符串)
- js (兼容问题)
//<div id="root"></div>
document.getELementById('root').innerHTML = 'hello world'
document.getELementById('root').style.color = 'red'
- jquery
$('#root').text('hello world').css('color':'red')
7.MVC Model - view - Contorllar
8.MVVM Model View ViewModel 数据驱动视图
工作:Model -> ViewModel <- View
vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的
``因为vue是通过Object.defineProperty()来实现数据劫持的。
`采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调
var obj = {};
Object.defineProperty(obj, 'name', {
get: function() {
console.log('我被获取了')
return val;
},
set: function (newVal) {
console.log('我被设置了')
}
})
obj.name = 'fei';//在给obj设置name属性的时候,触发了set这个方法
var val = obj.name;//在得到obj的name属性,会触发get方法
```vue是通过数据劫持的方式来做数据绑定的,其中最核心的方法便是通过Object.defineProperty()来实现对属性的劫持,那么在设置或者获取的时候我们就可以在get或者set方法里假如其他的触发函数,达到监听数据变动的目的
简单的双向绑定
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="demo"></div>
<input type="text" id="inp">
<script>
var obj = {};
var demo = document.querySelector('#demo')
var inp = document.querySelector('#inp')
Object.defineProperty(obj, 'name', {
get: function() {
return val;
},
set: function (newVal) {//当该属性被赋值的时候触发
inp.value = newVal;
demo.innerHTML = newVal;
}
})
inp.addEventListener('input', function(e) {
// 给obj的name属性赋值,进而触发该属性的set方法
obj.name = e.target.value;
});
obj.name = 'fei';//在给obj设置name属性的时候,触发了set这个方法
</script>
</body>
</html>
讲解vue如何实现
![在这里插入图片描述](https://img-blog.csdnimg.cn/2020122419042583.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1NDI0Njc5,size_16,color_FFFFFF,t_70)
vue代码实现
function defineReactive (obj, key, val) {
var dep = new Dep();
Object.defineProperty(obj, key, {
get: function() {
//添加订阅者watcher到主题对象Dep
if(Dep.target) {
// JS的浏览器单线程特性,保证这个全局变量在同一时间内,只会有同一个监听器使用
dep.addSub(Dep.target);
}
return val;
},
set: function (newVal) {
if(newVal === val) return;
val = newVal;
console.log(val);
// 作为发布者发出通知
dep.notify();//通知后dep会循环调用各自的update方法更新视图
}
})
}
function observe(obj, vm) {
Object.keys(obj).forEach(function(key) {
defineReactive(vm, key, obj[key]);
})
}