MVC模式是Web后端的常用的开发模式。model层一般都是实体类,有时候会多一个dao层用于专门写sql的操作,view层是前端,controller层编写业务逻辑。
Vue.js框架为了方便开发,使用了MVVM模式,它是前端页面的一种开发模式,分为M,V和VM,MVVM提供了数据的双向绑定。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>document</title>
<!-- 导入Vue的包 -->
<script src="https://cdn.staticfile.org/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<!-- MVVM里的View层 -->
<div id="app">
<p>{{ msg }}</p>
</div>
<script>
// 创建一个Vue的实例,vm就是MVVM里的vm调度者
var vm = new Vue({
el: '#app', //当前Vue对象要控制html页面哪个区域
// data对应MVVM中的Model
data: { //data属性中,存放el中要用到的数据
msg:'欢迎学习Vue' // 使用 Vue 提供的指令,直接将数据渲染到页面上
}
})
</script>
</body>
</html>
View中的input通过v-model
和vm中的id进行双向绑定,input中内容发生变化,在vm中可以检测到。
<div id="app">
<label>
Id:
<input type="text" class="form-control" v-model="id"/>
label>
div>
var vm = new Vue({
el:'#app',
data:{
id:'', // 与Id文本框进行了双向绑定,可以自动拿到文本框里的值
list:[
{ id:1, name:'奔驰',ctime:new Date() },
{ id:2, name:'宝马',ctime:new Date() }
]
}
})
Vue中数据保存在model中,即上面中的data,以数组的形式存在,如上面的list。
<tbody>
<tr v-for="item in list" :key="item.id">
<td>{{ item.id }}td>
<td>{{ item.name }}td>
<td>{{ item.ctime }}td>
<td>
<a href="#">删除a>
td>
tr>
tbody>
add(){ // 添加一个car的信息
// console.log('ok!')
// 1. 获取到id和name
// 2. 组织出一个对象
var car = {id:this.id,name:this.name,ctime:new Date()}
// 3. 把对象添加的 data 中去
this.list.push(car)
this.id = ''
this.name = ''
}
删除的时候,1. 先根据拿到想要删除对象的一个属性,比如id,或者name。2. 根据该属性找到对象在数组中的索引,也就是findIndex()函数的作用。3. splice()方法删除该索引位置的对象
del(id){ // 根据删除一个car的信息
// 根据id查询对象在list中的index
var index = this.list.findIndex(item => { // 遍历list,将集合中每个元素传入item,
if (item.id == id){ // 如果返回true,findIndex方法将这个item对应的index 返回
return true
}
})
this.list.splice(index,1)
}
这里关键字查询的操作方式,为前端列表数据的展示提供了一个新的思路。不去遍历整个list数组,而是遍历按照指定条件的查询结果(一个新数组)。
做个总结,查询数组对象的index使用findIndex()方法;查询整个对象用filter()方法
<tbody>
<tr v-for="item in search(keywords)" :key="item.id">
<td>{{ item.id }}td>
<td>{{ item.name }}td>
<td>{{ item.ctime }}td>
<td>
<a href="#" @click.prevent="del(item.id)">删除a>
td>
tr>
tbody>
search(keywords){
var newList = this.list.filter(item => { // 遍历list将集合中每个元素传入item,
if (item.name.includes(keywords)){ // 如果item.name中包含keywords,返回item
return item
}
})
return newList
}
后端传过来的数据,有可能跟想要展示在前台的数据不一样,比如在前端显示时间,通常是按照yyyy-mm-dd的形式展示,但后台拿过来的数据有可能是时间戳。这个时候就需要对数据进行加工处理后,再显示出来。
<td>{{ item.ctime | dateFormat("yyyy-mm-dd") }}td>
// 全局过滤器,进行时间格式化
Vue.filter('dateFormat',function(dateStr,pattern){
// 根据字符串拿到时间
var dt = new Date(dateStr)
// 拿到年月日
var y = dt.getFullYear()
var m = (dt.getMonth()+1).toString().padStart(2,'0') // 使用ES6提供的方法,将月份补充为2位
var d = dt.getDate().toString().padStart(2,'0')
// 如果输入格式为yyyy-mm-dd
if (pattern && pattern.toLowerCase() == 'yyyy-mm-dd') {
return `${y}-${m}-${d}`
}else{ // 如果输入格式
var hh = dt.getHours().toString().padStart(2,'0')
var mm = dt.getMinutes().toString().padStart(2,'0')
var ss = dt.getSeconds().toString().padStart(2,'0')
return `${y}-${m}-${d}:${hh}:${mm}:${ss}`
}
})
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Document</title>
<!-- 导入View.js包 -->
<script src="https://cdn.staticfile.org/vue/2.6.12/vue.js"></script>
<!-- 导入bootstrap样式 -->
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" />
</head>
<body>
<div id="app">
<!-- 添加品牌,panel面板 -->
<div class="panel panel-primary">
<!-- panel面板header -->
<div class="panel-heading">
<h3 class="panel-title">添加品牌</h3>
</div>
<!-- panel面板body -->
<div class="panel-body form-inline">
<label>
Id:
<input type="text" class="form-control" v-model="id"/>
</label>
<label>
Name:
<input type="text" class="form-control" v-model="name" @keyup.enter="add()" />
</label>
<input type="button" value="添加" class="btn btn-primary" @click="add()"/>
<label>
搜索:
<!-- 这里v-color中如果不加单引号,表示data中的变量,加了表示字符串 -->
<input type="text" class="form-control" v-model="keywords" v-focus v-color="'red'" />
</label>
</div>
</div>
<!-- 品牌列表 -->
<table class="table table-bodered table-hover table-striped">
<!-- 表头 -->
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Ctime</th>
<th>Operation</th>
</tr>
</thead>
<!-- 表身 -->
<tbody>
<tr v-for="item in search(keywords)" :key="item.id"><!-- 这里key如果不加:就当做一个字符串了 -->
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
<td>{{ item.ctime | dateFormat("yyyy-mm-dd") }}</td>
<td>
<a href="#" @click.prevent="del(item.id)">删除</a>
</td>
</tr>
</tbody>
</table>
</div>
<script>
// 全局过滤器,进行时间格式化
Vue.filter('dateFormat',function(dateStr,pattern){
// 根据字符串拿到时间
var dt = new Date(dateStr)
// 拿到年月日
var y = dt.getFullYear()
var m = (dt.getMonth()+1).toString().padStart(2,'0') // 使用ES6提供的方法,将月份补充为2位
var d = dt.getDate().toString().padStart(2,'0')
// 如果输入格式为yyyy-mm-dd
if (pattern && pattern.toLowerCase() == 'yyyy-mm-dd') {
return `${y}-${m}-${d}`
}else{ // 如果输入格式
var hh = dt.getHours().toString().padStart(2,'0')
var mm = dt.getMinutes().toString().padStart(2,'0')
var ss = dt.getSeconds().toString().padStart(2,'0')
return `${y}-${m}-${d}:${hh}:${mm}:${ss}`
}
})
// 自定义按键修饰符
Vue.config.keyCodes.f2 = 113 // 将f2键的keyCode为113,将113和f2绑定
// 自定义指令,调用指令时需要加v-
Vue.directive('focus',{
bind: function(el){
},
inserted: function(el){ // inserted 表示元素插入到DOM中到时候,会执行inserted函数,el为JS原生元素
el.focus() // 从内存渲染到页面上的时候,执行inserted
}
})
Vue.directive('color',{
bind: function(el,binding){
// binding.expression = 'red',binding.value=red
el.style.color = binding.value // 一加载到内存中去,就调用
} // 不管元素有没有被插入到页面中去,这个元素就已经有了一个内联样式
})
var vm = new Vue({
el:'#app',
data:{
id:'', // 与Id文本框进行了双向绑定,可以自动拿到文本框里的值
name:'', // 与Name 文本框进行了双向绑定,可以自动拿到文本框里的值
keywords:'', // 搜索的关键字
list:[
{ id:1, name:'奔驰',ctime:new Date() },
{ id:2, name:'宝马',ctime:new Date() }
]
},
methods:{
add(){ // 添加一个car的信息
// console.log('ok!')
// 1. 获取到id和name
// 2. 组织出一个对象
var car = {id:this.id,name:this.name,ctime:new Date()}
// 3. 把对象添加的 data 中去
this.list.push(car)
this.id = ''
this.name = ''
},
del(id){ // 根据删除一个car的信息
// 根据id查询对象在list中的index
var index = this.list.findIndex(item => { // 遍历list,将集合中每个元素传入item,
if (item.id == id){ // 如果返回true,findIndex方法将这个item对应的index 返回
return true
}
})
this.list.splice(index,1)
},
search(keywords){
var newList = this.list.filter(item => { // 遍历list将集合中每个元素传入item,
if (item.name.includes(keywords)){ // 如果item.name中包含keywords,返回item
return item
}
})
return newList
}
}
});
</script>
</body>
</html>