什么是MVC
MVC的核心理念是:你应该把管理数据的代码(Model)、业务逻辑的代码(Controller)、以及向用户展示数据的代码(View)清晰的分离开
通过MVC框架又衍生出了许多其它的架构,统称MV*,最常见的是MVVM
Vue与Angular就是一个MVVM框架,MVVM与MVC最大的区别是模型与视图实现了双向绑定。
在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。
Vue.js
是一套构建用户界面的渐进式js框架。那么什么叫渐进式框架呢?所谓渐进式就是一步一步的用,比如你只想在页面上渲染一些简单数据,那你只用它的核心代码就好。如果你想更进一步用到组件,那你需要用vue的组件系统。如果项目更大,那你需要用到路由啊,构建工具等等。项目需要哪块就用哪块,这样自底向上增量开发的设计,加上与单文件组件和 Vue 生态系统支持的库结合,使得Vue 也完全胜任复杂的单页应用程序,而且上手也很容易了。
Vue.js是一个轻巧、高性能、可组件化的MVVM库,同时拥有非常容易上手的API,作者是尤雨溪是中国人。
推荐学习文档 官网:https://cn.vuejs.org/v2/guide/
易用:已经会了HTML,CSS,JavaScript?即刻阅读指南开始构建应用!
灵活:简单小巧的核心,渐进式技术栈,足以应付任何规模的应用。
性能:超快虚拟 DOM 、最省心的优化
在idea中使用vue
安装Vue的插件
消除未知指令的错误 : 在标签上使用alt+enter键。添加命名空间即可
下载Vue :去vue2官网或git下载,地址:https://github.com/vuejs/vue
vue的指令学习
1. 插值表达式:
插值表达式:
语法:{{要插入的值}},此时相当于占位符,到时候{{关键字}}会被替换成
Model中的数据
bug点:
当网速较慢时,Vue初始化未完成时,插值表达式不能被解析,会直接显示 出来,加载完毕之后又会被替换成真实结果,造成闪烁(Vue的加载代码写在 HTML元素之后时会出现该bug)
v-cloak指令:
语法:把它当作HTML元素的一个属性使用
示例:
<p v-cloak>{{msg1}}</p>
特点:
当Vue加载完毕后,v-cloak属性会自动消失
使用:
添加如下CSS样式:让所有带v-cloak属性的元素隐藏,Vue加载完成后显示实现,解决插值表达式闪烁的问题
[v-cloak]{
display: none;
}
v-text:
语法:<p v-text="msg1"></p>
作用:和插值表达式一样,用于给HTML元素添加文本
区别:
1.v-text不会存在闪烁问题
2.v-text会将Model中的数据完全替换到HTML元素中(覆盖)
3.插值表达式只会将Model中的数据替换到插值表达式中(占位符内容的替换)
相同点:
1.插值表达式和v-text都可以给HTML元素显示文本
2.插值表达式和v-text都不会解析要添加文本中的HTML标签(原样显示)
v-html:
和v-text的唯一区别:给HTML添加内容时会解析内容中的HTML
代码实现:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
[v-cloak]{
display: none;
/*隐藏*/
}
</style>
</head>
<body>
<div id="app">
<!--v-cloak:解决插值表达式闪烁的问题-->
<p v-cloak>{{msg}}</p>
<!--msg值从前端来-->
<!--v-text等价于插值表示,没有闪烁问题-->
<p v-text="msg"/>
<p v-text="msg3"/>
<!--插入一个标签元素,需要使用v-html-->
<p v-html="msg3"></p>
</div>
<!--
引入Vue.Js
script必须成对的出现,不能自闭和
-->
<script src="../lib/vue.js"></script>
<script>
//新建一个vue的对象
//使用vue,需要一个vue的对象
var vm = new Vue({
//绑定元素el
el:"#app",
//需要传递的数据
data:{
/*
* 前后端分离:
* 前端专注于前端及伪造数据,留下接口
* 后端专注于数据交互,产生真实数据,数据库中的数据,提供请求路径
* */
msg:"Hello,vue",
msg2:"hello2",
msg3:"<h1>hello</h1>"
}
})
</script>
</body>
</html>
运行代码:
2. 绑定数据(v-bind,v-on):
v-bind:
语法:在HTML元素的属性目前加上绑定标识,此时HTML的该属性的值就会根据属性值的名字从Model中获取数据
示例:
<label>用户名:<input type="text" name="username" v-bind:value="msg" /></label>
var vm = new Vue({
el:"#app",
data:{
msg:"我是来自Model中的内容!",
name:"李师师"
}
});
注意:
1.【v-bind:】用于绑定HTML元素属性的值
2.【v-bind:】可以简写为:
3.Vue框架会把使用了v-bind:标识的HTML的属性的值当作一个Javascript表达式来使用只要表达式合法,就能执行(当然,数据必须时字面量或来自于Model中)
如:
:value="msg+'你好'"
:value="msg+name"
v-on:
语法:在HTML的事件属性(不带on)前加上绑定标识,此时HTML触发此事件时,会执行事件中绑定的代码
示例:
<button v-on:click="sayHello(name)">点击下显示你好</button>
<button @click="sayHello(name)">点击下显示你好</button>
var vm = new Vue({
el:"#app",
data:{
msg:"我是来自Model中的内容!",
name:"李师师"
},
methods:{
sayHello:function (name) {
alert("你好!"+name);
}
}
});
注意:
1.常见的web网页的事件都支持绑定
2.事件名字不带on
3.事件触发的方法必须在methods中定义
4.v-on标识的属性会被Vue解析为特定JavaScript,只要内容符合JavaScript规范 都能正确执行(比如传入参数)
5.【v-on:】等价于【@】
代码实现:
<!DOCTYPE html>
<html lang="en"
xmlns:v-bind="http://www.w3.org/1999/xhtml"
xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<p>
<!--绑定HTML元素属性的值,需要使用v-bind:+属性名="vue中数据的key"-->
用户名:<input type="text" name="username" v-bind:value="msg">
</p>
<p>
<!--v-bind:简化就是:-->
用户名:<input type="text" name="username" :value="msg">
</p>
<p>
<!--只要表达式合法,就能执行
变量+变量
变量+字符串常量
变量+字符串+变量
-->
用户名:<input type="text" name="username" :value="msg+'你好'">
用户名:<input type="text" name="username" :value="msg+msg">
</p>
<!--方法调用,绑定方法:v-on:
click和onclick
1,onclick是绑定事件,告诉浏览器在鼠标点击,时要做什么。
2,click本身方法作用是触发onclick事件,只要执行了元素的click()方法,就会触发onclick事件
3,click可以理解为一次简单的触发,只执行一次,找不到以后就不再执行;
4,onclick是给这个id注册一种行为,可以重复触发
5,click是方法;onclick是事件;执行click就是模拟鼠标点击,同时会触发onclick
-->
<p><button v-on:click="hello">点击</button></p>
<!--简化版-->
<p><button @click="hello()">点击</button></p>
<p><input type="text" value="Hello":style="style"></p>
<!--注意点
1,v-bind用来绑定元素属性的数据,可以是任意属性,只要数据合法;
2,v-on给元素事件【包括但不限于,点击,键盘按下,数百哦移动,窗口缩放】绑定方法,只要方法没有错,简写@
-->
</div>
<script src="../lib/vue.js"></script>
<script>
var vm = new Vue({
el:"#app",
data:{
msg:"HELLo,Vue",
style:"border-radius:20px"
},
//方法
methods:{
hello:function () {
alert("方法被调用了")
}
}
});
</script>
</body>
</html>
运行代码:
3. 跑马灯:
案例:跑马灯效果
知识点:
1.v-on:指令或@
2.v-html指令
3.定时器(正确启动和停止)
4.字符串截取
5.ECMAScript6新特性
6.this对象指代
【入坑】
1.在Vue对象vm的作用域外去使用Model中的数据或methods中定义的方法
2.JavaScript对象属性、方法赋值时使用了=号,应该使用:号,如age:56
【ECMAScript6的新特性】
1.给JavaScript对象方法定义值时
标准:
sayHello:function(){}
ES6:
此时,方法名sayHello会作为对象的属性方法值
sayHello(){
}
2.箭头函数的使用
标准:
setInterval(function(){
//此时this对象时Window对象
},500);
ES6:可以把外部环境传入箭头函数所指向的函数内部
setInterval(() => {
//此时this对依然是外部的this
},500);
【知识点】
1.定时器的使用
步骤1:定义全局的定时器编号,初始值为null
步骤2:判断定时器编号是否为null
如果不为null,直接返回(表示此时定时器已经启动,不可重复启动)
如果为null,则使用setInterval()启动定时器,并保存定时器编号到全局定时器变量中
步骤3:停止定时器
使用clearInterval()停止定时器,并把全局的定时器编号变量赋值为null
便于下次继续启动
2.Vue对象
vue对象中data、methods里面声明的内容全部都会成为vm的直接属性、方法
所有这些内容应该直接使用this访问,而不是【this.data.xxx、this.methods.xxx()】
代码实现:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>跑马灯</title>
</head>
<body>
<div id="app">
<button @click="toStart">开始</button>
<button @click="toStop()">停止</button>
<h6 v-html="msg" :style="style"></h6>
<input type="text" :value="msg"/>
</div>
<script src="../lib/vue.js"></script>
<script>
var vm = new Vue({
el:"#app",
data:{
msg:"希望你们每次来上网,都是因为喜欢,",
//注意点 : 赋值,在这里不能使用=号 ,要使用冒号
lightIntervalID:null,
style:"color: red;font-weight: bold;background-color:black"
},
methods:{
toStart(){
/*
vue对象中data、methods里面声明的内容全部都会成为vm的直接属性、方法
所有这些内容应该直接使用this访问,而不是【this.data.xxx、this.methods.xxx()】
*/
console.log("Haaa");
//如果不为null,直接返回(表示此时定时器已经启动,不可重复启动)
if (this.lightIntervalID!=null) {
return;
}
var _this = this; //别名
this.lightIntervalID = setInterval(function () {
//字符走动,跑马灯效果
_this.msg = _this.msg.substring(1).concat(_this.msg.charAt(0))
/*
希望你们每次来上网,都是因为喜欢,而不是无聊!就像结婚,是因为爱情,而不是因为凑合。
望你们每次来上网,都是因为喜欢,而不是无聊!就像结婚,是因为爱情,而不是因为凑合。希
你们每次来上网,都是因为喜欢,而不是无聊!就像结婚,是因为爱情,而不是因为凑合。希望
们每次来上网,都是因为喜欢,而不是无聊!就像结婚,是因为爱情,而不是因为凑合。希望你
*/
},200);
},
toStop(){
clearInterval(this.lightIntervalID);
this.lightIntervalID=null;
}
}
})
</script>
</body>
</html>
运行代码:
4. 双向绑定(v-mode):
v-mode:
v-mode:唯一的一个实现双向数据绑定的指令
语法:
<input type="text" v-model="num1" />
data:{
num1:'0',
num2:'0'
}
适用元素:表单元素,其它元素不能使用v-model指令
input系列(可以输入内容的)、select、textarea
双向绑定:
model层数据的改变会影响view层HTML结果
HTML中表单元素值的改变会写入对应的model层的数据中
【知识点】
JavaScript的eval()方法可以把一个字符串当作JavaScript代码执行,并返回执行结果
如:
this.result = eval("parseInt(this.num1)"+this.opr+"parseInt(this.num2)");
注意:
当代码很复杂或难以控制时可以使用此方法,大多数还是使用标准方法执行JavaScript代码
代码实现:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<p>
<!--value是不会变化,但是我们需要的是可以进行调整
的
数据和视图层可以双向绑定的东西。v-model-->
单价:<input type="text" v-model="price">
数量:<input type="text" v-model="num">
<button @click="calc()">计算</button>
总价:<span v-text="sum"></span>
</p>
</div>
<script src="../lib/vue.js"></script>
<script>
var vm = new Vue({
el:"#app",
data:{
price:3,
num:0,
sum:0
},
methods:{
calc(){
this.sum=this.price * this.num
}
}
});
</script>
</body>
</html>
运行代码:
5. 计算器:
代码实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
num1: <input type="text" v-model="num1">
<select v-model="opr">
<option value="+" selected disabled >+</option>
<option value="-">-</option>
<option value="*">*</option>
<option value="/">/</option>
</select>
num2: <input type="text" v-model="num2">
<button @click="calc()">=</button>
<span v-text="sum"></span>
</div>
<script src="../lib/vue.js"></script>
<script>
var vm = new Vue({
el:"#app",
data:{
num1:0,
num2:1,
sum:0,
opr:'+'
},
methods:{
calc(){
//判断标识
var flag = this.opr;
switch (flag){
case '+':
//这里取得的值为字符串,我们需要转换为int类型
this.sum = parseInt(this.num1) + parseInt(this.num2);
console.log(this.sum);
break;
case '-':
//这里取得的值为字符串,我们需要转换为int类型
this.sum = parseInt(this.num1) - parseInt(this.num2);
console.log(this.sum);
break;
case '*':
//这里取得的值为字符串,我们需要转换为int类型
this.sum = parseInt(this.num1) * parseInt(this.num2);
console.log(this.sum);
break;
case '/':
//这里取得的值为字符串,我们需要转换为int类型
this.sum = parseInt(this.num1) / parseInt(this.num2);
console.log(this.sum);
break;
}
}
}
})
</script>
</body>
</html>
运行代码:
6. v-for循环指令:
v-for循环指令:
1.使用v-for指令遍历简单数组
<p v-for="name in names">{{name}}</p>
<p v-for="name,index in names" v-text="name+'---'+index"></p>
2.使用v-for指令遍历对象数组
<p v-for="user in users">id:{{user.id}}---name:{{user.name}}</p>
3.使用v-for指令遍历对象属性值
<p v-for="value,key in cqCity">{{key+'--'+value}}</p>
4.使用v-for指令遍历数字(作用就是标准的for循环次数遍历)
<p v-for="num,index in 12" v-text="num+'---'+index"></p>
【注意】
1.遍历得到的值可以使用【插值表达式、v-text、v-html】显示
2.不管遍历何种数据类型,都可以得到值和索引
3.遍历对象属性和值时可以得到【值、属性名字、索引】
4.值的赋值顺序是:值、【键名】、索引
5.一次遍历中,多个结果之间使用,分割即可对应赋值(value,key,index)
6.遍历过程中接受值的变量名字可以任意
7.遍历数字时数字是从1开始,不能是负数(因为该功能是固定次数遍历)
8.在组件中使用数据时,一定要用key唯一绑定数据(保证对UI组件的操作不会因为其它组件的变化而发生变化)
注意:
1.key必须是基本数据类型(string/number)
报错:Avoid using non-primitive value as key, use string/number value instead.
2.key的数据值一定不要重复
报错:Duplicate keys detected: '3'. This may cause an update error.
技巧:一般使用对象中的值唯一属性(主键)作为key,比如id
语法:
<p v-for="user in users" :key="user.id">
<label><input type="checkbox"/>{{user.id}}---{{user.name}}</label>
</p>
【知识点】
1.如果组件的属性的值是一个变量,则必须使用v-bind:或者:进行属性值的绑定
2.数组的push()方法用于向数组末尾加入元素,数组的unshift()方法用于向数组最前面加入元素
this.users.push({id:this.id,name:this.name,age:this.age});
this.users.unshift({id:this.id,name:this.name,age:this.age});
3.在遍历对象数组并结合组件(表单元素)一起使用时,一定要指定唯一的key属性,进行组件和数据
的唯一关联,避免被其它操作(指非本元素)影响
代码实现:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="#app">
<p v-for="name in name">{{name}}</p>
<p v-for="name,index in names" v-text="name+'----'+index"/><hr>
<p v-for="student in students">{{student.id}}--{{student.name}}}--{{stuent.age}}}</p>
<br>
<p v-for="value,key kaungshen"{{key}}---{{value}}></p>
<p v-for="num in 12">{{num}}</p>
</div>
<script src="../lib/vue.js"></script>
<script>
var vm = new Vue({
el:"app",
data:{
names:["张三","李四","王梅","王麻子"],
student:[
{id:1,name:"李洋洋",age:1},
{id:2,name:"惠天航",age:2},
{id:3,name:"老痒痒",age:3}
],
kaungshen:{id:1,name:"秦疆",age:18,hobby:"code"}
}
});
</script>
</body>
</html>
7. v-if和v-show指令:
v-if和v-show指令
v-if和v-show指令:
v-if和v-show的区别?
1.v-if切换元素状态的具体操作是(创建元素--删除元素)
比较消耗创建性能
2.v-show切换元素状态的具体操作是(修改css的display样式)
比较消耗渲染性能
使用技巧:
如果该元素会经常显示/隐藏,则使用v-show
如果该元素默认情况下不会显示(大多数时候不会显示),则使用v-if
代码技巧:
如果使用vue绑定的方法只有一句代码,则可以直接写在绑定结果中
<button @click="flag=!flag">控制元素的显示隐藏</button>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<button @click="change()">显示</button>
<!--如果只有一行代码的情况下,可以直接写在事件中
一行代码不用写this , 因为this在我们的函数中,指代本身,但是这里不需要,我们直接操作属性即可;
-->
<button @click="flag=false">隐藏</button>
<button @click="flag=!flag">切换</button>
<!--v-if为true,则显示-->
<p v-if="flag">希望你们每次来上网,都是因为喜欢,而不是无聊!就像结婚,是因为爱情,而不是因为凑合。</p>
<!--v-show为true,则显示-->
<p v-show="flag">希望你们每次来上网,都是因为无聊,而不是喜欢!就像结婚,是因为凑合,而不是因为爱情。</p>
<p>撒娇的骄傲看来是加大了快速解答了空间都卡了时间到了</p>
<p>撒娇的骄傲看来是加大了快速解答了空间都卡了时间到了</p>
<p>撒娇的骄傲看来是加大了快速解答了空间都卡了时间到了</p>
<p>撒娇的骄傲看来是加大了快速解答了空间都卡了时间到了</p>
<!-- ·······此处省略一部分重复代码-->
<p>撒娇的骄傲看来是加大了快速解答了空间都卡了时间到了</p>
<p>撒娇的骄傲看来是加大了快速解答了空间都卡了时间到了</p>
<a href="#">点击链接</a>
</div>
<script src="../lib/vue.js"></script>
<script>
var vm = new Vue({
el:"#app",
data:{
flag:true
},
methods:{
change(){
this.flag=true;
}
}
})
</script>
</body>
</html>
运行代码:
8. 全局过滤:
Vue全局过滤器
Vue全局过滤器:
1.必须定义在创建Vue对象之前(Javascript的边解析边执行原理)
2.定义之后在整张页面中可以使用(一个页面一个Window,一个Window下只有一个Vue)
3.定义方式
参数1:固定(需要被过滤处理的数据)
参数2...参数n:过滤器被调用时传递的参数
Vue.filter("过滤器名字",function(data,param1,param2...){
});
4.调用方式
<h1>{{msg|v-过滤器名字(参数值1,参数值2...)|过滤器2...|过滤器n...}}</h1>
代码实现:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app1">
{{msg|ri()}}
</div>
<div id="app2">
{{msg|ri()}}
</div>
<!--导入Vue-->
<script src="../lib/vue.js"></script>
<script>
//全局过滤器,不要出现日
Vue.filter("ri",function(a){
return a.replace('日',"*")
});
var vm1 = new Vue({
el:"#app1",
data:{
msg:"我爱你,日"
},
filters:{
ri:function(a){
return a.replace('日',"#")
}
}
});
var vm2 = new Vue({
el:"#app2",
data:{
msg:"向日葵"
},
filters:{
ri(a){
return a.replace('日',"!")
}
}
});
</script>
</body>
</html>
运行代码:
9. 自定义过滤器:
Vue具体对象(特定作用域)过滤器
Vue具体对象(特定作用域)过滤器:
1.定义在一个Vue对象中
2.定义方式
var vm = new Vue({
el:"#app1",
data:{},
methods:{},
filters:{
过滤器名字:function(data,param1,param2...){
}或
过滤器名字(data,param1,param2...){
}
}
});
【注意】
1.全局过滤器一定要定义在使用Vue之前
2.Vue的过滤器执行原理
渲染内容 -- 交给第一个处理器 -- 得到结果 -- 交给第二个处理器 -- 得到结果 .... 得到结果--渲染
代码实现:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<input type="text" v-kuang="'red'" value="西部开源"/>
</div>
<script src="../lib/vue.js"></script>
<script>
//自定义指令 v-* v-kuang
Vue.directive("kuang",{
bind:function (el,binding) {
//el,指代指令作用的元素
//binding.value 就是你自定义指令后面的具体指 , v-kuang=""
el.style.color = binding.value;
}
});
//09: 使用BootStrap操作列表
//Vue对象
var vm = new Vue({
el:"#app",
directives:{}
})
</script>
</body>
</html>
运行代码: