开发模式mvc mvp mvvm
目标:将数据 视图 业务逻辑控制分层
mvc:具备view controller(控制器) model(模型)
model:负责保存应用数据,与后端数据进行同步(专门用来封装和处理数据)
controller:负责业务逻辑,根据用户行为对model数据进行修改(专门用来处理请求的 1.接收参数 2.调用service层代码 3.控制页面跳转)
view:负责视图展示,将model中的数据可视化出来(展示数据)
view→controller→model→view
可维护性差
mvp:(强调责任分离,方便维护代码)
前端跳过了这个过程
model ←→presenter←→view
虽然分离了view和model 但是应用逐渐变大之后 导致presenter的体积增大 难以维护
mvvp:(model view vm(view model视图模型)
m专门来准备数据
v 展示页面
vm视图和模型(视图和数据的转换)
保持view和model松耦合的同时 还维护了它们关系的代码 使用户专注于业务逻辑 兼顾开发效率和可维护性
vm包含dom-listener data-binding
dom监听器 监听页面dom节点的变化 当页面dom节点发生改变的时候 数据也会发生对应的改变
data-binding 绑定数据 当model数据发生改变的时候 界面也会发生对应的改变
以上即双向绑定技术:view改变model也会变 model变view也会变
总结:
反应web领域发展进程
这三者都是框架模式 它们的目标都是为了解决model和view的耦合问题
mvc模式出现较早主要应用于后端 如spring mvc 在前端领域的早期也有应用 如 backbone.js 它的优点是分层清晰 缺点是数据流混乱 灵活性带来的维护性问题
mvp模式是mvp的进化形式 presenter作为中间层负责mv通信 解决了两者耦合问题 但p层过于臃肿会导致维护问题
mvvm模式在前端领域有广泛应用 它不仅解决mv耦合问题 还同时解决了维护两层映射关系的大量繁杂代码和dom操作代码,在提高开发效率 可读性的同时还保持了优越的性能表现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
@keyframes zhuan{
0%{
color: red;
transform: translateX(20px);
}
30%{
color: aqua;
transform: translateX(30px);
}
70%{
color: greenyellow;
transform: translateX(70px);
}
100%{
color: blanchedalmond;
transform: translateX(100px);
}
}
.active {
color: red;
}
.hello-enter{
/* 进入过渡之前的状态 在元素插入之前生效 */
/* 透明度 */
opacity: 0;
}
.hello-enter-active{
/* 过渡时的状态 */
animation: zhuan 3s;
}
.hello-enter-to{
/* 过渡的进行中状态 元素被插入后生效 */
color: red;
}
.hello-leave{
opacity: 1;
}
.hello-leave-active{
transition: 2s;
}
.hello-leave-to{
/* 元素离开后 dom会被清除 */
opacity: 0;
}
</style>
</head>
<body>
<div id="app">
<!-- v-show不展现时不是删除dom节点 而是增加class属性 display:none -->
<del v-show="num%2==0">show</del>
<!-- 类似if-else语句 若为false则dom节点会删除 -->
<del v-if="num%2==0">12345</del>
<del v-if="now==1">99999</del>
<del v-else-if="now==2">88899</del>
<del v-else="now==0">88888</del>
<!-- 动态class切换 -->
<h1 :class="{active:num%2==0}">{{num}}</h1>
<h1>{{str}}</h1>
<!-- computed里的函数不用以函数形式调用且只要里面的值不变刷新不用重新计算(具有缓存功能 响应式) methods里的函数每次刷新都要计算 -->
<h2>{{getNum}}</h2>
<!-- v-bind绑定'123'可以转化为数字类型的123 -->
<Demo v-bind:number="173">
<!-- 显示到slot插槽中 -->
<del slot="demo1">111</del>
<del slot="demo2">222</del>
<del slot="demo3">333</del>
</Demo>
<!-- v-on:click简写@click
v-bind:简写 : -->
<!-- v-bind:是用来绑定属性的。
v-on:用来绑定事件的。
v-on使用的时候一般写在methods方法里面
v-bind使用的时候一般写在data里面。 -->
<!-- $event即原生es5的e参数 -->
<button v-on:click="add(101,$event)">add</button>
<hr>
<ul>
<!-- <li v-for="item in list"> -->
<li v-for="(item,index) in list">
{{index}}:{{item}}
</li>
</ul>
<hr>
<b>{{value}}</b>
<input type="text" v-model="value">
<!-- 双向绑定 1.视图->数据 -->
<!-- 双向绑定 2.数据->视图 -->
<hr>
<em>{{value1}}</em>
<input type="text" @input="inputFn($event)" :value="value1">
<!-- 双向绑定 1.视图->数据 @input -->
<!-- 双向绑定 2.数据->视图 :value -->
<hr>
<transition name="hello">
<p v-if="isActive">zhouaozhan 666</p>
</transition>
</div>
<script src="./tool/vue.js"></script>
<script>
//子组件 1.创建 2.注册 3.使用
var Demo =Vue.component('Demo',{
//子组件传参 props
// props:['come','number'],
props:{
come:{
type:String,
//没有传递参数的默认值
default:'缺失参数',
//是否必须传入参数 若为true不传入会报错
required:false
},
number:{
type:Number,
default:1000,
required:false,
//检验参数是否合法
validator:function(e){
return e>150
}
}
},
// slot插槽
template:'<a>百度{{come}}:{{number}} <slot name="demo1"></slot> <slot name="demo3"></slot> <slot name="demo2"></slot></a>'
})
//根组件
var vm =new Vue({
el:'#app',//绑定实例与页面中的标签
data:{
num:0,
str:'abc',
hello:'hi',
now:2,
list:['a','b','c'],
value:'',
value1:'',
isActive:false
},
methods:{
add(value,e){
console.log(value,e)
this.num++
// console.log(this.$el.innerText)//获取标签里的内容
},
inputFn(e){
this.value1 =e.target.value
}
},
//计算属性 其属性不能与data内数据重名
computed:{
getNum(){
return this.num*this.num
}
},
//侦听数据 允许异步操作 (访问一个API)
watch:{
// 此处函数只能写与要监听数据一样的
num(newValue,oldValue){
console.log(newValue,oldValue)
}
},
// 子组件注册
component:{
Demo
}
})
</script>
</body>
</html>