MVVM模式
MVVM
M 是模型(model),V是视图(view),VM(ViewModel)是V和M的双向协调者。
![image-20211109185324431](http://cdn.upeveryday.cn/img/image-20211109185324431.png)
view
DOM元素
View是视图层,也就是用户界面。前端主要由HTML和css来构建,为了更方便地展现viewModel或者Model层的数据,已经产生了各种各样的前后端模板语言,比如FreeMarker、Thymeleaf等等,各大MVVM框架如Vue.js, AngularJs, EJS等也都有自己用来构建用户界面的内置模板语言。
model
data中的属性
<script> new Vue({ el: '#app', data: { ok: true, message: 'RUNOOB', id : 1 } }) </script>
Model是指数据模型,泛指后端进行的各种业务逻辑处理和数据操控,主要围绕数据库系统展开。这里的难点主要在于需要和前端约定统一的接口规则
ViewModel
ViewModel是由前端开发人员组织生成和维护的视图数据层。在这一层,前端开发者对从后端获取的Model数据进行转换处理,做二次封装,以生成符合View层使用预期的视图数据模型。
需要注意的是ViewModel所封装出来的数据模型包括视图的状态和行为两部分,而Model层的数据模型是只包含状态的
- 比如页面的这一块展示什么,那一块展示什么这些都属于视图状态(展示)
- 页面加载进来时发生什么,点击这一块发生什么,这一块滚动时发生什么这些都属于视图行为(交互)
视图状态和行为都封装在了ViewModel里。这样的封装使得 ViewModel 可以完整地去描述View 层。由于实现了双向绑定,ViewModel的内容会实时展现在View层,这是激动人心的,因为前端开发者再也不必低效又麻烦地通过操纵 DOM 去更新视图。
MVVM 框架已经把最脏最累的一块做好了,我们开发者只需要处理和维护ViewModel,更新数据视图就会自动得到相应更新,真正实现事件驱动编程。 View 层展现的不是Model层的数据,而是ViewModel的数据,由ViewModel 负责与Model 层交互,这就完全解耦View 层和Model层,这个解耦是至关重要的,它是前后端分离方案实施的重要一环。
MVC
M 是模型,V是视图,C是控制器(业务)
vue使用了MVVM架构来设计框架。架构是说逻辑分层,框架是指具体的实现。
很明显VM的实现是这个框架的核心,也是最复杂的地方。从更大范围上看,vue专注界面的实现,也就是MVC中的V层。因此,vue只是一个局部框架,传统MVC中的模型和业务不是vue的范畴,需要自行设计。
- Model:模型层,这里表示JavaScript对象
- View:视图层,这里表示DOM(HTML操作的元素)
- ViewModel:连接视图和数据的中间件
vue基础
1. 安装
<script>
引入
直接下载并用 <script>
标签引入,Vue
会被注册为一个全局变量。
对于制作原型或学习,你可以这样使用最新版本:
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
对于生产环境,我们推荐链接到一个明确的版本号和构建文件,以避免新版本造成的不可预期的破坏:
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
2. 常用操作
变量取值
标签内取值
使用双引号
<!--view层:模板-->
<div id="app" v-text="message">
</div>
<script>
var vm=new Vue({
el:"#app",
//model:数据对象
data:{
message:"hello world!"
}
})
</script>
标签外取值
使用双大括号
{ {}}
<!--view层:模板-->
<div id="app">
{
{ message }}
</div>
<script>
var vm=new Vue({
el:"#app",
//model:数据
data:{
message:"hello world!"
}
})
</script>
绑定HTML属性v-bind
v-bind
<div id="app">
<p v-bind:title="title">html属性不能使用双大括号形式绑定,只能使用v-bind指令</p>
</div>
......
var vm = new Vue({
el: '#app',
data: {
title: 'title content'
}
});
这里的 html 最后会渲染成:
<div id="app">
<p title="title content">html属性不能使用双大括号形式绑定,只能使用v-bind指令</p>
</div>
v-bind缩写
<!-- 完整语法 -->
<a v-bind:href="url">...</a>
<!-- 缩写 -->
<a :href="url">...</a>
<!-- 动态参数的缩写 (2.6.0+) -->
<a :[key]="url"> ... </a>
条件v-if
是否显示当前标签
if-else
<div id="app" >
<p v-if="seen">seen为真</p>
<p v-else>seen为假</p>
</div>
<script>
var vm=new Vue({
el:"#app",
data:{
// seen:true
seen:false
}
})
</script>
if-else-if
<div id="app" >
<!-- ==只要求值相等,===要求类型和值都要相同-->
<p v-if="type==='A'">A</p>
<p v-else-if="type==='B'">B</p>
<p v-else-if="type==='C'">C</p>
<p v-else-if="type==='D'">D</p>
<p v-else>0</p>
</div>
<script>
var vm=new Vue({
el:"#app",
data:{
type:'1'
}
})
</script>
循环v-for
v-for
<div id="app" >
<ol>
<li v-for="(todo,index) in todos">
<!--index是当前遍历元素的索引-->
{
{ todo.text }}--{
{index}}
</li>
</ol>
</div>
<script>
var vm=new Vue({
el:"#app",
//js中对象用{},数组用[]
data: {
todos: [//数组中存放对象
{
text: '学习 JavaScript' },
{
text: '学习 Vue' },
{
text: '整个牛项目' }
]
}
})
</script>
key属性
当使用列表渲染时,永远添加key
属性,这样可以提高列表渲染的效率,提高了页面的性能。
如果我们要利用key
属性的优点,必须保证同一父元素的所有子元素有不同的key
属性。
<!--用户列表-->
<div v-for="(user,index) in users" class="text item" :key="index">
{
{user.username}}
</div>
事件处理v-on
v-on
给按钮绑定单机事件,事件方法定义在methods
对象中
<div id="app" >
<button v-on:click="sayHello">点击我</button>
</div>
<script>
var vm=new Vue({
el:"#app",
//js中对象用{},数组用[]
data: {
message:"hello"
},
methods:{
//方法必须定义在methods对象中
sayHello: function () {
alert(this.message)
}
}
})
</script>
v-on可以缩写
<!-- 完整语法 -->
<a v-on:click="doSomething">...</a>
<!-- 缩写 -->
<a @click="doSomething">...</a>
表单输入绑定v-model
v-model
v-model后可以跟任何变量名称,只要此变量名称在data中存在,那么表单中的值就与此变量进行了双向绑定
将表单与model变量进行双向绑定
- 修改变量,表单内容也会改变
- 修改表单内容,变量也会改变
文本
示例1:将输入框与变量message绑定
<div id="app" >
输入的文本:<input type="text" v-model="message"> {
{message}}
</div>
<script>
var vm=new Vue({
el:"#app",
//js中对象用{},数组用[]
data: {
message:"hello"
},
methods:{
//方法必须定义在methods对象中
}
})
</script>
单选框
实例2:将单选框与model变量message绑定,并且在下面展示出选择的内容
将单选框的value与message进行双向绑定
<div id="app">
<input type="radio" value="男" v-model="message"