首先,你可以在这里下载本文使用到的vue.js文件,使用的是v2.6.10
开发版本。
Vue只关注视图层,是一套构建用户界面的框架。
app.js
:项目的入口模块,一切的请求,都要先进入这里进行处理。(注意:app.js并没有路由分发功能,需要调用router.js
模块进行路由的分发处理)router.js
:这是路由分发处理模块:为了保证路由模型的只能单一,router.js只负责分发路由,不负责具体业务逻辑的处理(如果涉及到业务逻辑处理操作,router.js就无能为力了,只能调用controller模块
进行业务逻辑处理)Controller
:这是业务逻辑处理层,在这个模块中,封装了一些具体业务逻辑处理的逻辑代码,但是,也是为了保证职能单一,此模块只负责处理业务,不负责处理数据的CRUD,如果涉及到了数据的CRUD,需要调用Model层
Model层
:职能单一,只负责操作数据库,执行对应的Sql语句,进行数据的CRUD。View视图层
:每当用户操作了界面,如果需要业务的处理,都会通过网络请求,去请求后端服务,此时,这个请求就会被后端的app.js监听到
。
视图层的分层开发思想
,主要把每个页面分成了M、V和VM。其中,VM是MVVM的思想核心,因为VM是M和V之间的调度者。前端页面使用MVVM的思想,主要是为了让我们开发更方便,因为MVVM提供了数据的双向绑定。(注意:数据的双向绑定是由VM提供的。)
基础代码
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
<script src="./lib/vue.js">script>
head>
<body>
<div id="app">
<p>{{msg}}p>
div>
<script>
//创建一个Vue实例
//当导入vue.js的包之后,在浏览器的内存中,就多了一个Vue构造函数
//注意:我们new 出来的这个vm对象,就是我们MVVM中的VM调度者
var vm = new Vue({
el: '#app', //表示当前我们new的这个vue实例,要控制页面上的哪个区域
//这里的data就是MVVM中的M,专门用来保存每个页面的数据
data: { //data属性中,存放的是el中要用到的数据
msg: '欢迎学习Vue' //通过vue提供的指令,很方便的把数据渲染到页面上,程序员不再手动操作DOM元素了
}
})
script>
body>
html>
v-cloak:解决插值表达式闪烁问题
v-text:解析文本
v-html:解析html
v-bind:提供属性绑定机制,缩写是 “:”
v-on:绑定事件,绑定浏览器常见事件,缩写是 “@”
示例代码:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
<style>
[v-cloak]{display: none;}
style>
head>
<body>
<div id="app">
<p v-cloak>{{msg}}p>
<h4 v-text="msg">h4>
<div v-html="msg2">div>
<input type="button" value="按钮" v-bind:title="mytitle + '123'">
<input type="button" value="按钮" :title="mytitle + '567'">
<input type="button" value="按钮" :title="mytitle" v-on:click="hello">
<input type="button" value="按钮" :title="mytitle" @mouseover="hello">
div>
<script src="./lib/vue.js">script>
<script>
var vm = new Vue({
el: '#app',
data: {
msg: '123',
msg2: '我是H1
',
mytitle: '这个一个自定义的title'
},
methods: { // methods属性中定义了当前Vue实例中所有可能的方法
hello: function() {
alert('hello');
}
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
head>
<body>
<div id="app">
<input type="button" value="浪起来" @click="lang">
<input type="button" value="别浪" @click="dontLang">
<h4>{{ msg }}h4>
div>
<script src="./lib/vue.js">script>
<script>
//注意:在vm实例中,如果想要获取data上的数据,或者想要调用methods中方法,必须通过t his.数据属性名 或 this.方法名 来进行访问,就表示我们 new 出来的vm实例对象
var vm = new Vue({
el: '#app',
data: {
msg: '猥琐发育,别浪!',
timer: null, //在data上定义定时器ID
},
methods: {
lang() {
if(this.timer === null) {
this.timer = setInterval(()=>{
var start = this.msg.substring(0,1);//获取第一个字符串
var end = this.msg.substring(1);//获取到第一个字符后面的所有字符
this.msg = end + start;//重新凭借得到新的字符串,并赋值给 this.msg
//注意: VM实例,会自动监听data中所有数据的改变,只要数据发送变化,就会把最新的数据,从data同步到页面中去。【好处:程序员只需要关系操作数据,不需要考虑如何重新渲染到页面】
},300);
}else {
return;
}
},
dontLang() {
clearInterval(this.timer);
//每当清除了定时器后,重新把timer置为null
this.timer = null;
}
}
})
//分析:
//1.给 【浪起来】按钮,绑定一个点击事件 v-on 或 @
//2. 在按钮的事件处理函数中,写相关的业务逻辑代码:拿到msg字符串,然后调用字符串的substring方法,来进行字符串截取操作,把第一个字符串截取出来,
//放到最后一个位置,即可。
//3.为了实现点击下按钮,自动截取的功能,需要把2步骤的代码,放到一个定时器中
script>
body>
html>
.stop
阻止冒泡.prevent
阻止默认事件.capture
添加事件侦听器时使用事件捕获模式.self
只当事件在该元素本身(比如:不是子元素)触发时触发回调.once
事件只触发一次.self
和.stop
的区别:
.self
只阻止自身元素上的其他默认行为,不会阻止其他元素的默认冒泡行为.stop
阻止包含自身以及其他元素的默认冒泡行为
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
<script src="./lib/vue.js">script>
<style>
.inner {
height: 100px;
background-color: darkcyan;
}
.outer{
padding: 10px;
background-color: green;
}
style>
head>
<body>
<div id="app">
div>
<script>
var vm = new Vue({
el: '#app',
data: {
},
methods: {
divHandler() {
console.log('inner div click event')
},
btnHandler() {
console.log('button click event')
},
linkHandler() {
console.log('a link click event')
},
divSelfHandler() {
console.log('inner self click event')
},
divouterHandler() {
console.log('outer click event')
}
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
<script src="./lib/vue.js">script>
head>
<body>
<div id="app">
<h4>{{ msg }}h4>
<input type="text" v-model="msg">
div>
<script>
var vm = new Vue({
el: '#app',
data: {
msg: 'HELLO world'
},
methods: {
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
<script src="./lib/vue.js">script>
head>
<body>
<div id="app">
<input type="text" name="" v-model="n1">
<select v-model="opt">
<option value="+">+option>
<option value="-">-option>
<option value="*">*option>
<option value="/">/option>
select>
<input type="text" v-model="n2">
<input type="button" value="=" @click="calc">
<input type="text" v-model="result">
div>
<script>
var vm = new Vue({
el: '#app',
data: {
n1: 0,
n2: 0,
result: 0,
opt: '+'
},
methods: {
calc() {
//不推荐该方式,开发中最好不用
let codeStr = `parseInt(this.n1)${this.opt}parseInt(this.n2)`;
this.result = eval(codeStr);
}
}
})
script>
body>
html>
数组方式
<h1 :class="['red','thin']">啧啧啧啧啧啧h1>
数组中使用三元表达式(要在data中添加isactive)
<h1 :class="['red','thin',isactive?'active':'']">h1>
数组中嵌套对象
<h1 :class="['red','thin',{'active':isactive}]">啧啧啧啧啧啧h1>
直接使用对象
<h1 :class="{red:true,'thin':true,italic:true,active:true}">啧啧啧啧啧啧h1>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
<script src="./lib/vue.js">script>
<style>
.red {
color: red;
}
.thin {
font-weight: 200;
}
.italic {
font-style: italic;
}
.active {
letter-spacing: 0.5em;
}
style>
head>
<body>
<div id="app">
<h1 :class="classObj">啧啧啧啧啧啧h1>
div>
<script>
var vm = new Vue({
el: '#app',
data: {
classObj: {red:true,'thin':true,italic:true,active:false}
},
methods: {
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
<script src="./lib/vue.js">script>
head>
<body>
<div id="app">
<h1 :style="styleObj1">啧啧啧啧啧啧h1>
<h1 :style="[styleObj1,styleObj2]">啧啧啧啧啧啧h1>
div>
<script>
var vm = new Vue({
el: '#app',
data: {
styleObj1: {color: 'red','font-weight': 400},
styleObj2: {'font-style':'italic','letter-spacing':'0.5em'}
},
methods: {
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
<script src="./lib/vue.js">script>
head>
<body>
<div id="app">
<ul>
<li v-for="(item,i) in list">第{{i+1}}项:{{item}}li>
ul>
div>
<script>
var vm = new Vue({
el: '#app',
data: {
list: [1,2,3,4,5,6]
},
methods: {
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
<script src="./lib/vue.js">script>
head>
<body>
<div id="app">
<ul>
<li v-for="(item,i) in list">id:{{item.id}}---{{item.name}}li>
ul>
div>
<script>
var vm = new Vue({
el: '#app',
data: {
list: [
{id:1,name:'zzz1'},
{id:2,name:'zzz2'},
{id:3,name:'zzz3'},
{id:4,name:'zzz4'},
{id:5,name:'zzz5'},
]
},
methods: {
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
<script src="./lib/vue.js">script>
head>
<body>
<div id="app">
<p v-for="(val,key,i) in user">{{ key }} --- {{ val }} --- 索引:{{i}}p>
div>
<script>
var vm = new Vue({
el: '#app',
data: {
user: {
id: 1,
name: 'zzzz',
gender: '男'
}
},
methods: {
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
<script src="./lib/vue.js">script>
head>
<body>
<div id="app">
<p v-for="count in 10">第{{count}}次循环p>
div>
<script>
var vm = new Vue({
el: '#app',
data: {
},
methods: {
}
})
script>
body>
html>
v2.2.0+的版本里,每次
for
循环时,通过key属性标识当前循环的唯一身份。
注意: v-for循环的时候,key属性只能使用number获取string
注意: key 在使用的时候,必须使用v-bind 属性绑定的形式,指定key的值
在组件中,使用v-for循环的时候,或者在一些特殊情况中,如果v-for有问题,必须在使用v-for的同时指定唯一的字符串/数字类型的:key值
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
<script src="./lib/vue.js">script>
head>
<body>
<div id="app">
<div>
<label>
ID: <input type="text" v-model="id">
label>
<label>
name: <input type="text" v-model="name">
label>
<input type="button" value="添加" @click="add">
div>
<p v-for="item in list" :key="item.id">
<input type="checkbox">
{{item.id}}---
{{item.name}}
p>
div>
<script>
var vm = new Vue({
el: '#app',
data: {
id: '',
name: '',
list: [
{id:1,name: 'xxx'},
{id:2,name: 'yyy'},
{id:3,name: 'zzz'},
{id:4,name: 'www'}
]
},
methods: {
add() {
this.list.unshift({id: this.id,name:this.name});
}
}
})
script>
body>
html>
v-if
:每次都会重新删除或创建DOM(v-if会消耗较高的切换性能 ,如果该DOM涉及到频繁的切换,最好不要用到v-if
,这时推荐使用v-show
)
v-show
:每次不会重新进行DOM的删除或创建操作,只是切换了DOM的display:none
样式。(如果这个DOM从来不会被进行显示,那么v-show有较高的初始渲染消耗,这时推荐使用v-if
)
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
<script src="./lib/vue.js">script>
head>
<body>
<div id="app">
<input type="button" value="toggle" @click="flag=!flag">
<h3 v-if="flag">v-if控制的DOMh3>
<h3 v-show="flag">v-show控制的DOMh3>
div>
<script>
var vm = new Vue({
el: '#app',
data: {
flag: true
},
methods: {
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
<link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet">
<script src="../lib/vue.js">script>
head>
<body>
<div id="app">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">添加品牌h3>
div>
<div class="panel-body form-inline">
<label for="">
id: <input type="text" class="form-control" v-model="id">
label>
<label for="">
name: <input type="text" class="form-control" v-model="name">
label>
<input type="button" value="添加" class="btn btn-primary" @click="add">
<label for="">
搜索关键字: <input type="text" value="搜索" v-model="keywords">
label>
div>
div>
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<th>idth><th>Nameth><th>Ctimeth><th>Operationth>
tr>
thead>
<tbody>
<tr v-for="item in search(keywords)" :key="item.id">
<td v-text="item.id">td>
<td v-text="item.name">td>
<td v-text="item.ctime">td>
<td>
<input type="button" value="删除" @click.prevent="del(item.id)">
td>
tr>
tbody>
table>
div>
<script>
var vm = new Vue({
el: '#app',
data: {
id: '',
name: '',
keywords: '',
list: [
{id:1,name:'科比',ctime: new Date()},
{id:2,name:'詹姆斯',ctime: new Date()}
]
},
methods: {
add() {
//分析:
//1.获取到id和name,直接从data上获取
//2.组织处一个对象
//3.把这个对象,调用数组的相关方法,添加到当前data上的list中
//4.注意:在Vue中,已经实现数据的双向绑定,每当我们修改了data中的数据,Vue会默认监听到数据的改动,自动把最新的数据,应用到页面上
let data = {id:this.id,name:this.name,ctime:new Date};
this.list.push(data)
this.id = this.name = '';//清空
},
del(id) {
// this.list.some((item,i)=>{
// if(item.id === id) {
// this.list.splice(i,1);
// return true;
// }
// })
let index = this.list.findIndex(item => {
if(item.id === id) {
return true;
}
});
this.list.splice(index,1);
},
search(keywords) {//根据关键字进行数据的搜索
// let newList = [];
// this.list.forEach(item=>{
// if(item.name.indexOf(keywords) !== -1) {
// newList.push(item);
// }
// })
// if(keywords.trim() === '') {
// return this.list;
// }else {
// return newList;
// }
return this.list.filter(item => {
return item.name.includes(keywords) === true ? item : false;
})
}
}
})
script>
body>
html>