vuejs概述
jQuery
库是针对js
的dom
的封装,封装了好多原生js
的dom
操作繁琐的地方,那Vuejs
是针对 html+css+js
的一个封装 虽然vuejs
没有脱离这三大技术,但是 在原有基础上进行了整合 推出了 组件化开发的概念。
MVC框架:
Model
- - - View
- - - Controllor
模型 - - - 视图 - - - 控制者
框架(vue使用的):
Model
- - - View
- - - View
- - - Model
模型 - - - 视图 - - - 视图 - - - 模型
数据直接对应页面;
数据变化 页面就变化;
页面变化 数据就变化;
干掉了 传统MVC结构中的业务逻辑 直接使数据和页面绑定;
让页面操作更简单,所以Vue中没有 js的dom操作
Vue特点:
- 简单 易上手(精通难)
一片html代码 结合json 实现vue效果 - 双向数据绑定特点(不再需要dom操作)
数据和页面的效果直接绑定
数据变化 页面直接变化 干掉了中间的业务逻辑(后面说) - 个人团队维护 开源 所以进步快
尤雨溪带队开发的 - MVVM框架 非常好用
在MVC框架基础上的一个升级(后面说) - Vuejs不支持IE8及以下
只要是IE9+ 几乎所有浏览器都支持 - 轻量级 更适合开发移动端(PC端一样可以)
因为Vue的效果比较简单 所以Vue不适合开发向大型电商网站那样复杂的页面 - Vue开发PC端 最多的是开发 后台管理页面
- SPA 单页面应用
Single Page Web Application (单页面 Web应用)
初步使用Vue搭建HelloWorld程序
<!--第二步 一片html代码-->
<div id="app">
<h1>{{msg}}</h1>
</div>
//第一步: 引入vue.js文件
<script src="vue.js"></script>
<script>
//第三步 定义json渲染vue
var vm=new Vue({
el:"#app",
data:{
msg:"Hello World!"
}
})
</script>
vue的双向数据绑定演示
<div id="app">
<h1>{{msg}}</h1>
<input type="text" v-model="msg">
</div>
<script src="vue.js"></script>
<script>
var vm=new Vue({
el:"#app",
data:{
msg:"Hello World!"
}
})
</script>
Vue基本结构的介绍
<!--第二步: 一片html代码 一般先定义一个统一的父元素,然后用vue去加载这一块元素
那么以后这一块元素内所有的位置 都按照vue的语法来加载-->
<div id="app">
<!--这个是 Mustache模板语法
格式: {{js表达式}} js表达式包括: 三目表达式 运算符表达式
方法调用 变量
这个语法表示一种模板 将来会受vue渲染并执行
就想蒸蛋糕的那个模具一样 会按照我们写的格式进行加载并取得结果
-->
<h1>{{msg}}</h1>
</div>
<!--第一步 : 引入vue.js文件-->
<script src="vue.js"></script>
<script>
/*第三步: 定义json、渲染vue代码;
先把Vue对象创建出来,
构造方法需要传入一个json进行vue对象的配置,
有点类似于 `$.ajax({})` 参数的大括号就是针对当前ajax进行配置*/
var vm=new Vue({
//挂载目标(表示:当前vue语法,挂载到哪一个目标元素上面去;一旦挂载,那么该目标就按照vue语法加载)
el:"#app", //值是一个字符串 里面传入选择器(一会讲 都支持哪些选择器)
data:{ /*定义data是专门给挂载目标里面所使用的所有变量赋值*/
msg:"我是vue变量的值"
}
});
</script>
Vue所支持的选择有哪些:
-
id选择器;
-
class选择器(如果有多个 只会选择第一个);
-
元素选择器;
如果有多个 只会选择第一个
Vue2.x版本 不允许直接挂载到body上面去!!!
Do not mount Vue to <html> or <body> - mount to normal elements instead
. -
子代/后代选择器;
-
交集选择器;
-
所有的css3选择器 都支持;
var vm=new Vue({
//ID选择器
// el:"#app",
//class选择器
// el:".pox",
//元素选择器
// el:"div",
//子代/后代选择器
// el:"body>#app",
//交集选择器
// el:"div#app",
//所有css3选择器也支持
el:"div:nth-child(1)",
data:{
msg:"我是数据"
}
})
vue所支持的渲染的数据类型
1.字符串
2. number类型
3. boolean类型
4. 数组类型
5. 对象类型
6. 内置对象类型
<div id="app">
<h1>{{msg}}</h1>
<h1>{{num}}</h1>
<h1>{{boo}}</h1>
<h1>{{arr}}</h1>
<h1>{{json}}</h1>
<h1>{{d}}</h1>
</div>
var vm=new Vue({
el:"#app",
data:{
msg:"我是字符串类型",
num:5,
boo:false,
arr:["关羽","张飞","刘备"],
json:{
name:"小明",
age:16
},
d:new Date()
}
})
v-show指令的使用:
vue
中提供了一些以v-
开头的指令,专门写到标签上面的,那么这些指令作用: 扩展标签原有功能
;
该指令控制元素的显示与隐藏 v-show="变量或者表达式"
;
变量或者表达式结果是true
时 ,该元素显示;否则false
隐藏。
v-show
指令:控制的是元素的 display
属性。
<div id="app">
<div id="box" v-show="boo"></div>
</div>
<script src="js/vue.js"></script>
<script>
var vm=new Vue({
el:'#app',
data:{
boo:true
}
});
</script>
v-if指令的使用:
v-if
指令:也是控制元素的显示与隐藏。
v-if="变量或者表达式"
变量或者表达式为true
时元素显示、否则隐藏; 跟v-if
搭配使用的就是v-else
, 如果v-if
的条件为false
则v-else
的元素显示;v-else
没有值
跟随v-if
的变化而变化,跟if..else语句
一样。v-else-if="变量或者表达式"
如果v-if
里面的条件是false
则继续向下判断
v-else-if
;v-else-if
可以有多个 谁是true
谁显示。
使用注意点:
v-if
和v-else-if
和v-else
标签之间,不能有任何其他标签 否则报错!也就是保证v-if
语句的完整性。
v-if和v-show都是控制元素显示隐藏,那么区别在哪里?
v-show
控制元素的显示隐藏用的是display
属性,也就是说不管条件是true还是false元素都会加载,只不过如果条件为false 元素设置display:none
;v-if
控制元素的显示与隐藏用的是 加载与不加载 如果条件为false
则元素直接从dom
中删除,如果条件为true
则重新加载该元素。如果页面加载时 条件为false
那么该元素都不会存在到dom中。- 由以上结论可以看出:
如果有一个或单个元素或者父元素下的一堆元素,短时间内进行多次的显示隐藏 那么推荐使用v-show
;
如果一个元素是懒加载形式 暂时不用,等用到时在显示加载,则推荐使用v-if
;
<div id="app">
<!--<div id="box" v-if="boo"></div>
<div id="pox" v-else></div>-->
<ul>
<li v-if="num==1">我是第一个li</li>
<li v-else-if="num==2">我是第二个li</li>
<li v-else-if="num==3">我是第三个li</li>
<li v-else>我是第四个li</li>
</ul>
</div>
var vm=new Vue({
el:'#app',
data:{
boo:true,
num:1,
}
});
v-for指令的使用:
v-for
指令:可以实现 遍历数组或者js对象;然后根据遍历出来的数量加载指定数量的元素。
数组、对象需要在vue
的data
里面定义。
v-for指令遍历数组:
- 格式1:
<标签 v-for="变量 in 数组对象">{{变量}}</标签>
- 格式2:
<标签 v-for="(元素变量,索引标量) in arr">{{变量}}---{{索引}}</标签>
v-for指令遍历json对象:
- 格式1:
<标签 v-for="属性值 in json对象"></标签>
- 格式2:
<标签 v-for="(属性值,属性名) in json对象"></标签>
- 格式3:
<标签 v-for="(属性值,属性名,索引) in json对象"></标签>
<div id="app">
<div v-for="k in arr">{{k}}</div>
<ul>
<li v-for="(item,index) in arr">{{item}}====={{index}}</li>
<li v-for="item in per">{{item}}</li>
<li v-for="(item,key) in per">{{item}}====={{key}}</li>
<li v-for="(value,key,index) in per">{{key}}====={{value}}===={{index}}</li>
</ul>
var vm=new Vue({
el:'#app',
data:{
arr:["关羽","刘备","张飞","庞统","李白"],
per:{
name:"小强",
age:18,
gender:"男",
location:"善知教育"
}
}
});
一些其他指令的使用
mustache语法
是一种模板语法 在vue未加载到该语法代码时,则该语法看起来像是乱码一样,只有vue挂载成功了以后 才真正加载。
假设当前网速缓慢,比如下面代码我们用 setTimeout
模拟网速缓慢,那么页面加载时 会优先显示一个 花括号{{}}
,这样给用户的 带来非常不好的体验。
- 那么针对这种
mustache语法
使用时 先加载花括号{{}}
,再加载内容的方式该如何处理呢?
vue官方推出了一个v-cloak
指令:该指令的作用就是保证了mustache语法
在未加载出来之前 并不显示,直到语法加载成功后 才显示,但是需要css配合:[v-cloak]{display:none;}
。
实现原理:
在当前标签使用了v-cloak
以后 那么如果mustache语法未加载时 则标签具有该属性,跟css属性选择器配合
导致元素不显示,直到mustache语法
的值加载成功,则自动删除该属性 元素就显示出来了。
<div id="app">
<h1 v-cloak>{{msg}}</h1>
<h1 v-html="str2">我是默认内容</h1>
<h1 v-text="str2">我也是默认内容</h1>
</div>
setTimeout(()=>{
var vm=new Vue({
el:'#app',
data:{
msg:"HelloWorld!",
str1:"我是str1的内容",
str2:"<a href='http://www.baidu.com'>我是a标签</a>"
}
});
},2000)
渲染内容的指令:
v-html="变量或者表达式"
;
v-text="变量或者表达式"
;
这两个指令都是能够把 变量或者表达式的值
作为当前标签的内部内容来渲染,如果标签原本内部有内容则覆盖。
这两个指令的区别就是: 如果内容中有标签 那么v-html
可以渲染标签,v-text
不可以渲染标签 只会把内容原封不动渲染到页面上。
这两个指令也具有 渲染成功后才显示的效果,所以有些地方如果要渲染一些变量内容 也可以使用该指令。
v-model指令的使用:
v-model
指令:是专门用在输入框上面 用来替代 输入框的value
属性,让输入框的value
可以关联一个vue
的变量,从而实现双向数据绑定
- 格式:
<input type="text" v-model="变量">
要注意: 一旦输入框使用了v-model
那么就不要再定义value
属性,因为v-model
就代替value
属性。 - 效果:
一旦用户修改输入的内容 则对应的变量会发生值的改变,如果其他地方也用到了该内容,则也会发生改变。 - 可以使用
v-model
的标签:input
,textarea
标签。
<div id="app">
<input type="text" v-model="msg">
<textarea v-model="msg" id="" cols="30" rows="10"></textarea>
<h1>{{msg}}</h1>
<h1 v-html="msg"></h1>
</div>
var vm=new Vue({
el:'#app',
data:{
msg:"HelloWorld!"
}
});
template模板标签的使用
如果我们的指令想要控制的标签元素(一堆标签)不是单个标签,那么之前的做法是 再添加一个父元素标签 然后把指令定义到统一的父元素标签上面去。
无论是 v-if
还是v-for
还是v-show
都是这样做的,但是如果实际开发的需求不允许我们再添加一个父元素标签了呢?
- 所以我们需要用到
vue
中的template
标签。 - 该标签是H5推出的标签 但是
Vue
中重新定义了它的功能,在vue
中template
标签不渲染, 也就是说我们可以写指令控制template
里面的元素,但是template
本身又不渲染到页面上。 - 所以如果以后有想要控制多个元素的情况下 可以考虑使用template标签
- 但是
template
标签不能使用v-show
指令!!! v-if
和template
配合使用 可以实现分组管理
<!--<template>我是template标签</template>-->
<div id="app">
<!--<div v-for="(item,index) in arr">
<div>{{item}}:我是第一个div</div>
<div>{{item}}:我是第二个div</div>
<div>{{item}}:我是第三个div</div>
</div> -->
<!--<template v-for="(item,index) in arr">
<div>{{item}}:我是第一个div</div>
<div>{{item}}:我是第二个div</div>
<div>{{item}}:我是第三个div</div>
</template>-->
<template v-if="boo">
<div>我是一个div</div>
<div>我也是</div>
</template>
<template v-else>
<ul>
<li>我是一个li</li>
<li>我也是li</li>
</ul>
</template>
</div>
var vm=new Vue({
el:'#app',
data:{
arr:["小明","小红","大婷"],
boo:true
}
});
v-on绑定事件的指令使用
vue中 使用v-on
指令来绑定事件:
格式: <标签 v-on:不带on的事件类型="事件方法名"></标签>
暂时不需要事件对象时 驱动函数名可以不加括号
该事件要在Vue
的json
里面定义:
methods:{
驱动函数名:function(){}
}
v-on
指令使用时 开发工具会提示添加命名空间:
xmlns:v-on="http://www.w3.org/1999/xhtml"
没啥用 添不添加都行,不影响运行。
如果实在看不过去 我们v-on
有简化写法:<标签 @不带on的事件名称="事件驱动函数名"></标签>
在事件的驱动函数里面 通过this
可以直接访问data
里面的变量
要注意: this.
不能省略
var vm=new Vue({
el:'#app',
data:{
msg:"我是默认内容"
},
methods:{
show:function(){
alert("你点我干嘛")
},
show1:function(){
console.log("鼠标移入了");
},
getData(){
// console.log(this.msg);
this.msg="哈哈,新内容吧";
}
}
});
//补充: es6中 json对象绑定方法 可以向下面这样去写
var per={
name:"小强",
//es6的新写法
show(){
console.log("我是show方法");
}
}
per.show()
class Person{
sayHi(){
}
}
vue事件中的event使用
vue
中的event
事件对象需要在绑定事件的标签上面传入$event
参数。- 格式:
<标签 @事件名称="事件驱动函数($evnet)"> </标签>
$event
是固定写法 必须这么写,然后在事件驱动函数里面 第一个参数接收event
。event
属性跟原来学习的没有任何差别。- 如果标签上面绑定事件时 没有传入
$event
那么事件驱动函数也无法接收event
几种情况:
- 不需要
event
事件对象 而是传入自定义数据
<li v-for="(item,index) in arr" @click="getData(item,index)">{{item}}</li>
标签上面传入几个参数, 那么事件驱动函数就可以用形参去接受。 - 如果需要
event
对象 还需要 传入数据 那么必须保证$event
是在第一个参数位置:
<li v-for="(item,index) in arr" @click="getData1($event,item,index)">{{item}}</li>
。
<div id="app">
<!-- <div id="box" @click="show($event)"></div>-->
<div id="box" @click="show($event)"></div>
<ul>
<!--不使用event对象的情况下传入参数-->
<li v-for="(item,index) in arr" @click="getData(item,index)">{{item}}</li>
</ul>
<ol>
<!--如果有event也有其他数据 那么必须保证 $event在第一位-->
<li v-for="(item,index) in arr" @click="getData1($event,item,index)">{{item}}</li>
</ol>
</div>
var vm=new Vue({
el:'#app',
data:{
msg:"HelloWorld!",
arr:["关羽","刘备","张飞","袁绍","庞统"]
},
methods:{
show(event){
console.log(event);
},
getData(s,i){
// console.log(s,i);
this.arr.splice(i,1);
},
getData1(event,item,index){
console.log(event,item+"---"+index);
}
}
});
vue中的事件修饰符
vue
中阻止事件冒泡不用event
对象 直接使用事件修饰符即可
- 格式:
<标签 @事件名称.修饰符="驱动函数"></标签>
- 修饰符有:
stop
: 阻止事件冒泡
prevent
: 阻止默认事件
once
: 该事件只能触发一次
self
: 只有event.target===this
的时候才触发该事件
<div id="app">
<!--<div id="box" @contextmenu.prevent="demo" @click.once="boxclick($event)">-->
<div id="box" @contextmenu.prevent="demo" @click.self="boxclick($event)">
<!--<div id="pox" @click.stop="poxclick"></div>-->
<div id="pox"></div>
</div>
</div>
<div id="app">
/ 这是第一种阻止浏览器默认行为 /
<!--<div id="box" @contextmenu.prevent="demo" @click="boxclick">-->
/ 这是第二种阻止浏览器默认行为 /
<div id="box" @contextmenu.slef.prevent="demo" @click="boxclick">
<div id="pox" @click.stop="poxclick"></div>
</div>
</div>
var vm=new Vue({
el:'#app',
data:{
msg:"HelloWorld!"
},
methods:{
boxclick(event){
alert("你点到了box");
console.log(event.target);
},
poxclick(){
alert("你点到了pox")
},
demo(){
alert("你右键点击了")
}
}
});
v-bind指令的初步使用
v-bind
指令是专门用来给标签的原有属性绑定变量的,也就是说 让标签的原有属性 的值可以是vue
的一个变量,变量值改变 属性值就改变
。
使用格式:<标签 v-bind:属性名="变量或者表达式"></标签>
此处注意: 一旦使用v-bind
那么属性值必须是一个合法的变量或者表达式,不能是直接一个中文或者其他的值 否则会报错。
v-bind
的简化写法:<标签 :属性名="变量或者表达式"></标签>
;
v-bind指令之class属性的绑定
v-bind
能绑定任何标签的原生属性 同样也包括class
和style
属性
那么 v-bind
绑定class
时有下面这么几种情况:
第一种: 绑定一个字符串变量 字符串里面都是class
类名
<div id="box" :class="msg">
data:{
msg:"fz co"
}
第二种: 绑定一个数组变量 数组里面都是字符串 每一个字符串就是一个class
:
<div id="box" :class="arr">
arr:["fz","co","ml"]
第三种: 绑定一个json
对象 json
的键就是class
名字 值是布尔值
布尔值为true
表示当前class
启用
布尔值为false
表示当前class
不启用
<div id="box" :class="json">
json:{
fz:true,
co:false,
ml:false,
mt:false
}
第四种:绑定一个数组字面量
<div id="box" :class='["fz","co","ml"]'>
第五种:绑定json字面量
<div id="box" :class='{fz:true,co:false,ml:false,mt:false}'>
v-bind指令之style属性的绑定
v-bind
指令绑定style
的方式:
第一种:
绑定一个长字符串 字符串里面定义 行内样式的写法
<div id="box" :style="msg">
data:{
msg:"font-size:25px;color:#fff;margin-left:30px"
}
第二种:
绑定一个json对象 json对象的键值对用来定义css属性名和属性值
<div id="box" :style="json" @click="show">
json:{
fontSize:"30px",
color:"#fff",
"margin-left":"50px",
"margin-top":"100px"
}
第三种:
绑定一个json字面量值
<div id="box" :style='{fontSize:"30px", color:"#fff","margin-left":"50px","margin-top":"100px"}' @click="show">
第四种(知道就行)
绑定一个数组对象
<div id="box" :style='arr' @click="show">
arr:[
{fontSize:"30px",color:"#fff",},
{"margin-left":"50px",},
{"margin-top":"100px"}
]
vue-resource交互手段的使用
Vue
本身是不具有交互能力的 需要像JQ
使用插件那个样子 进行扩展使用,Vue
中比较好用的交互第三方 是vue-resource
(旧),和Axios
两种交互手段。
现在主流的都是Axios
只不过很多之前的老项目里面还依然还有Vue-resource
的代码。
关于各种第三方的代码 都去github
网站去搜索 www.github.com
。
vue-resource
的使用:
第一步: 引入vue
核心文件
第二步:引入vue-resource
文件
第三步: 通过this.$http.get/post
方法 进行交互访问
发起get
请求:
this.$http.get(服务器地址,提交的参数).then(成功的回调,失败回调)
;
在成功的回调里面 使用 参数.bodyTex
t获取返回的数据
get
方式给服务器提交数据:
- 地址栏拼接
this.$http.get("php/01.getData.php?username=小强&password=123456").then(data=>{
this.msg=data.bodyText;
})
- 通过get方法的第二个参数提交
this.$http.get("服务器地址",{
params:{
键1:值1,
键2:值2
}
}).then(成功的回调)
<h1>{{msg}}</h1>
<button @click="getData">发起一个get请求</button>
getData(){
/*this.$http.get("php/01.getData.php").then(function (data) {
console.log(data.bodyText);
this.msg=data.bodyText
},function (err) {})*/
/* this.$http.get("php/01.getData.php?username=小强&password=123456").then(data=>{
this.msg=data.bodyText;
})*/
this.$http.get("php/01.getData.php",{
params:{
username:"小美",
password:"111111"
}
}).then(data=>{
this.msg=data.bodyText;
})
},
发起一个post
请求
this.$http.post("服务器地址",要提交的参数).then(成功的回调,失败的回调)
;
post
请求方法向服务器提交参数:
this.$http.post("服务器地址",
{
键1:值1,
键2:值2
},
{
emulateJSON:true
//这个键值对的意思就是自动拼接那个POST提交参数的请求头
//application/x-www-form-urlencoded
}).then(成功的回调,失败的回调)
第二个参数是一个长字符串 键值对的拼接
<h1>{{msg}}</h1>
<button @click="postData">发起一个post请求</button>
postData(){
/* this.$http.post("php/01.postData.php").then(data=>{
this.msg=data.bodyText
})*/
this.$http.post("php/01.postData.php",{
username:"小强",
password:"123456"
},
{
emulateJSON:true
}).then(data=>{
this.msg=data.bodyText;
})
},
发起一个跨域请求:
<button @click="corsData">发起一个跨域请求</button>
this.$http.jsonp("跨域服务器的地址",{
jsonp:"cb" //改变默认的callback键名的属性
}).then(成功的回调,失败的回调)
corsData(){
this.$http.jsonp("http://localhost/2020-11-01/php/01.corsData.php",{
jsonp:"cb"
}).then(data=>{
console.log(data.bodyText);
})
}
Axios交互手段的使用
axios
是现在Vue
中使用最多的交互手段;axios
跟JQ
的ajax
用法很像。
axios
交互的原理使用的就是promise
语法,一旦引入axios.js
那么全局就会有一个axios
方法。
第一种: axios.get()
发起简单get
请求
axios.get(服务器地址,给服务器提交的参数)
.then(成功的回调)
.catch(失败的回调)
通过回调函数的参数 调用data
属性 取得返回数据。
提交参数: 地址栏拼接。
getSimpleData(){
/*axios.get("php/02.getData.php")
.then(data=>{
console.log(data.data);
this.msg=data.data
})*/
axios.get("php/02.getData.php?username=小强&password=123456")
.then(data=>{
console.log(data.data);
this.msg=data.data
})
},
第二种: axios.post()
发起简单的post
请求
axios.post(服务器地址,提交的参数)
.then(成功的回调)
.catch(失败的回调)
提交参数:
第二个参数传入一个字符串
字符串定义 键=值&键=值
postSimpleData(){
axios.post("php/02.postData.php")
.then(data=>{
this.msg=data.data;
})
axios.post("php/02.postData.php","username=小强&password=123456")
.then(data=>{
this.msg=data.data;
})
},
第三种: axios({ })
进行各项属性配置的axios
请求
- 常用属性:
method
:“GET/POST”,
url
:“服务器地址”,
params
/data
:“提交的参数”
axios({
属性配置
})
.then(成功的回调)
.catch(失败的回调)
axios
方法的get
方式提交参数:
- 地址栏拼接
url:“服务器地址?键=值&键=值” - 通过属性params提交
axios({
params:{
键1:值1,
键2:值2
}
})
getData(){
/*axios({
method:"get",
url:"php/02.getData.php"
}).then(data=>{
// console.log(data);
this.msg=data.data
})*/
//提交参数
axios({
method:"get",
url:"php/02.getData.php",
params:{
username:"小白白",
password:"123456"
}
}).then(data=>{
this.msg=data.data;
})
}
axios
方法post
方式提交参数:
- 通过data属性提交
axios({
data:"键1=值1&键2=值2"
})
- 通过
data
属性 值是一个URLSearchParams对象
提交参数
var mydata=new URLSearchParams();
mydata.append("键1","值1");
mydata.append("键2","值2");
axios({
data:mydata
})
postData(){
/*axios({
method:"post",
url:"php/02.postData.php"
}).then(data=>{
this.msg=data.data;
})*/
/*axios({
url:"php/02.postData.php",
method:"post",
data:"username=小砌墙&password=666666"
}).then(data=>{
this.msg=data.data
})*/
var myData=new URLSearchParams();
myData.append("username","小百强");
myData.append("password","888888");
axios({
url:"php/02.postData.php",
method:"post",
data:myData
}).then(data=>{
this.msg=data.data
})
}
Vue的生命周期以及钩子函数
所谓 生命周期 是指:从什么时候诞生 在什么时候销毁。
那么Vue的生命周期 就表示 Vue
实例从什么是创建,中间经历了哪些过程,最后什么时候销毁。
Vue
的生命周期 在每个阶段都会有对应的函数被系统自动执行,一旦当前Vue
对象过渡到了指定阶段,那么该阶段的声明周期对应的函数就会被调用,这些函数又叫钩子函数。(一共十个 我们目前学习八个)
beforeCreate
created
beforeMount
mounted
beforeUpdate
updated
beforeDestroy
destroyed
生命周期的钩子函数是跟data
同级定义的;
生命周期的钩子函数作用:
是为了能够帮助我们在Vue
实例的不同阶段暴露不同函数,从而我们可以做对应的事情;
实际开发中使用最多的就是mounted
方法,这个钩子函数有点 类似于 window.onload
。
钩子函数都可以通过 this.
调用当前Vue
实例中data
的变量 和 methods
里面的方法。
var vm=new Vue({
data:{
msg:"HelloWorld!"
},
methods:{
},
beforeCreate(){
alert("Vue实例创建之前")
},
created(){
alert("Vue实例创建成功!")
},
beforeMount(){
alert("Vue实例挂载之前")
},
mounted(){
alert("Vue实例挂载成功")
},
beforeUpdate(){
alert("data数据更新前")
},
updated(){
alert("data数据更新完成后")
},
beforeDestroy(){
alert("Vue实例销毁前");
},
destroyed(){
alert("Vue实例销毁成功")
}
});
//如果Vue对象创建时 没有定义el属性
//则可以通过动态的Vue对象调用$mount("选择器")方法来进行挂载
vm.$mount("#app");
//vm.destroy() 销毁当前Vue实例
Vue实例本身自带的属性跟方法
Vue
构造函数里面传入的 对象 绑定的属性跟方法,按原理来说并不属于Vue
对象本身的,但是为了能够方便访问,所以系统自动给Vue
对象也绑定一份一模一样的,只不过是$
开头的。
var options={
el:'#app',
data:{
msg:"HelloWorld!"
}
}
var vm=new Vue(options);
//获取data对象
console.log(vm.$data);
//获取el挂载目标
console.log(vm.$el);
vm.$mount() 动态挂载目标 如果已经定义el属性 那么该方法不生效
vm.$destroy() 销毁当前vue对象
Vue实例自定义属性跟方法
如果 Vue
的构造方法中的 options
对象绑定了自定义属性跟方法,那么 访问方式 : vm.$options.属性名
。
var vm=new Vue({
el:'#app',
data:{
msg:"HelloWorld!"
},
name:"小白白"
});
console.log(vm.$options);
console.log(vm.$options.name);
computed计算属性的使用
如果有需要是一个变量是根据另一个或者多个变量的值变化而发生变化时,需要用到计算属性,该变量需要定义到computed
里面。
格式:
computed:{
变量:function(){
此处可以写代码;
最后一定要return一个值,
return的这个值就是当前变量的新值
return 新值;
}
}
计算属性里面定义的变量 跟 data
里面定义的变量没有任何区别,页面该怎么用就怎么用;
计算属性的值 会随着 关联的变量的值 变化而变化,就是说只要变量出现在计算属性的代码中,那么这个变量值发生改变,计算属性就会被触发。
计算属性里面的变量的值 不能直接更改,涉及到set
和get
方法,所以暂时记住 计算属性的值不能直接更改。
<div id="app">
<button @click="change">点击改变a的值</button>
<h1>a的值:{{a}}</h1>
<h1>b的值:{{b}}</h1>
<h1>c的值:{{c}}</h1>
</div>
var vm=new Vue({
el:'#app',
data:{
a:10,
c:99
},
computed:{
b:function(){
console.log("b的计算属性方法被触发");
return this.a*10+5
}
},
methods:{
change(){
this.a=200;
}
}
});
Vue中使用key管理重复元素
因为 Vue
的虚拟 DOM
算法的原因,会导致有些时候使用v-if
或者v-for
时,如果元素内容相同时,会导致渲染错误,因为 vue
会默认的复用元素,从而减少 DOM
操作,如果不想复用元素,那么必须给当前元素绑定 key
属性,定义独一无二的值,防止复用!
<div id="app">
<template v-if="boo">
<h4>手机号注册</h4>
<label for="">手机号:</label>
<input type="text" key="mobile" placeholder="请输入手机号">
<input type="button" value="提交" >
</template>
<template v-else>
<h4>邮箱号注册</h4>
<label for="">邮箱号:</label>
<input type="text" key="email" placeholder="请输入邮箱号">
<input type="button" value="提交" >
</template>
<p>
<button @click="change">切换注册方式</button>
</p>
</div>
var vm=new Vue({
el:'#app',
data:{
boo:true
},
methods:{
change(){
this.boo=!this.boo;
}
}
});
通过上面切换注册方式的代码我们看到,尽管切换了另一套布局,但是因为两套布局里面都有input
,虽然input
的placeholder
属性值不一样,但是系统默认复用了切换之前的输入框对象,然后只是把placeholder
属性的值替换一下,所以如果不想保留用户输入的信息,也就是不想使用默认的复用,想要重新渲染,那么两个input
必须添加不同的key
就好了。
那么同理 v-for
也要给循环出来的每个元素添加 key
防止复用,在ws
开发工具中 v-for
不添加key
不报错,但是在vsCode
中v-for
不添加key会有报错提示,有红线<li v-for="(item,index) in arr" :key="index"></li>
。
Vue键盘事件的按键修饰符
Vue
中:
event.key
在按键事件中表示当前按键的名称;
event.keyCode
在按键事件中表示当前按键码。
如果键盘事件想要触发指定按键以前的做法:
if(event.key=="Enter"){
console.log("按回车了");
}
现在只需要使用案件修饰符即可:
@keydown.按键名称/键盘码="驱动函数"
表示触发指定按键才触发该事件。
<div id="app">
<input type="text" @keydown="show($event)">
<input type="text" @keydown.Enter="show($event)">
<input type="text" @keydown.up="show($event)">
<input type="text" @keydown.65="show($event)">
<input type="text" @keydown.a="show($event)">
</div>
var vm=new Vue({
el:'#app',
data:{
msg:"HelloWorld!"
},
methods:{
show(event){
console.log(event.key);
console.log(event.keyCode);
if(event.key=="Enter"){
console.log("按回车了");
}
console.log("触发了么?");
}
}
});
自定义过滤器
自定义过滤器的使用
能够监听指定的变量的值是否符合定制的规范
自定义过滤器格式: {{变量 | 过滤器名字}}
在Vue
里面跟data
同级的位置定义:
filters:{过滤器名字:function(参数){
参数就是当前 过滤器使用的那个位置的变量的值
return 当前变量的新值;
}
如果过滤器里面不return
那么当前变量没有值。
过滤器filter和计算属性computed的区别:
- 过滤器是针对当前过滤器所在的位置的那个变量格式的检查;
- 计算属性是至少两个变量 其中一个变量根据另一个变量的值变化而变化;
过滤器可以使用的位置:
mustache语法 和 v-bind指令
<div id="app">
<h1>{{a | check}}</h1>
<input type="text" v-model="a">
<input type="text" v-model="b">
<img src="image/chang.png" :width="b | checkNum" alt="">
</div>
var vm=new Vue({
el:'#app',
data:{
a:50,
b:"",
boo:false
},
filters:{
check:function(a){
// console.log(a);
if(a<0 || a>9999) {
return "Error!";
}
return a;
},
checkNum(a){
if(/^\d{1,}$/.test(a)){
return parseInt(a)
}else{
return 100;
}
}
}
});
过滤器之时间转换器案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
h1{
text-align: center;
color:orange;
}
</style>
</head>
<body>
<div id="app">
<h1>{{msg | change}}</h1>
</div>
<script src="vue.js"></script>
<script>
var vm=new Vue({
el:'#app',
data:{
msg:new Date(),
},
filters:{
change:function (d) {
let year = d.getFullYear();
let month = d.getMonth() + 1;
let day = d.getDate();
let hour = d.getHours();
let minute = d.getMinutes();
let second = d.getSeconds();
month = month > 9 ? month : "0" + month;
day = day > 9 ? day : "0" + day;
hour = hour > 9 ? hour : "0" + hour;
minute = minute > 9 ? minute : "0" + minute;
second = second > 9 ? second : "0" + second;
return year+"年 "+month+"月 "+day+"日 "+hour+"时 "+minute+"分 "+second+"秒";
}
},
mounted(){
//vue挂载成功以后 启动一个定时器
setInterval(()=>{
this.msg=new Date();
},1000)
}
});
</script>
</body>
</html>
全局注册过滤器的使用
目前为止我们学习的都是单个vue
对象,如果有多个vue
对象,那么就可以分别挂载不同的目标,实现不同的渲染。
如果我在 vm1
中定义 filters(过滤器)
,那么vm2是不能使用!!!
在Vue
的optipons
对象里面定义的 过滤器 那么只能在当前vue
对象中使用,也就是当前vue
对象挂载的目标可以使用 其他vue
对象挂载的目标不能使用!
如果想要所有Vue
对象都可以使用 那么就要定义全局的过滤器:
Vue.filter("过滤器名字",回调函数(参数就是当前变量的值){return 值})
<div id="app">
<h1>{{msg | check}}</h1>
<h1>{{msg | checkhaha}}</h1>
</div>
<div id="box">
<h1>{{msg | checkhaha}}</h1>
</div>
//全局注册过滤器
Vue.filter("checkhaha",function(a){
if(a.length>5){
return "Error!"
}
return a;
})
console.log(Vue.computed);
var vm1=new Vue({
el:'#app',
data:{
msg:"我是vm1的msg"
},
filters:{
check(a){
if(a.length>10){
return "字数超过了!!"
}
return a;
}
}
});
var vm2=new Vue({
el:'#box',
data:{
msg:"我是vm2的msg"
}
});
watch数据监听器的使用
目的是为了监听某些变量值变化时,我们需要做一些其他功能。
格式:
在Vue的$options里面 定义
watch:{
被监听的data里面的变量:function(参数1,参数2){
参数1,是当前变量改变后的值,参数2是变量改变前的旧值
}
}
浅层监听–监听器默认是浅层监听
如果监听器所监听的变量是基本数据类型,那么值改变监听器就会监听到;但是如果监听器监听的是对象类型,那么默认对象地址改变时才会监听到,换句话说,如果对象的属性发生变化时,默认无法监听。
局部监听器(只能在当前Vue中使用)
在Vue中注册的局部监听器进行深层监听
格式:
watch:{
被监听的变量:{
handler:function(newVal,oldVal){
},
deep:true
}
}
全局监听器:
浅层监听
vue实例对象.$watch("被监听的变量",function(newVal,oldVal){
//这种格式默认浅层监听
})
深层监听
vue实例对象.$watch("被监听的变量",{
handler:function(newVal,oldVal){
},
deep:true
})
<div id="app">
<input type="text" v-model="msg">
<h1>{{msg}}</h1>
<h1>per的值:{{per}}</h1>
<p> <button @click="change">改变per的值</button></p>
</div>
var vm=new Vue({
el:'#app',
data:{
msg:"HelloWorld!",
per:{name:"小白",age:16}
},
methods:{
change(){
/* 地址改变深浅监听无变化
this.per={
location:"文化大厦",
gender:"男"
}*/
/*地址不变值改变 浅层监听不能监听到*/
this.per.name="大黄";
}
},
watch:{
//每次msg的值发生改变都会触发该方法
msg:function(newVal,oldVal){
console.log("msg值发生变化了,新值:"+newVal+"--旧值:"+oldVal);
},
/* 这种格式默认浅层监听
per:function(newVal,oldVal){
console.log("per值发生变化了",newVal);
}*/
/*深层监听*/
per:{
handler:function (newVal,oldVal) {
console.log("per值发生变化了",newVal);
},
deep:true
}
}
});
//全局深层监听
vm.$watch("per",{
handler:function(newVal,oldVal){
console.log("我是全局监听per,被触发了",newVal);
},
deep:true
})
$watch()不是静态方法 而是 Vue实例的方法
filter()方法是Vue的静态方法 Vue.filter()
Vue结合Animtae.css框架的动画
Animate.css框架
主要针对盒子的进入和离开的动画
- 首先我们得定义一个盒子具有进入离开效果;
- 通过link标签引入
Animate.css
; - 把具有进入离开的盒子外面套一层
transition
标签;
transition标签
在vue
中加载完,是不显示的标签,专门用来设置动画的一个标签,功能类似template
- 在transition开始标签里面定义 进入和离开的属性;
进入:enter-active-class
;
离开:leave-active-class
; - 进入离开的class里面定义
animated
框架的动画类名
不要忘记animated 最基本的类名
<style>
#box{
width: 200px;
height: 200px;
background-color: hotpink;
}
</style>
<link rel="stylesheet" href="css/animate.css">
<div id="app">
<button @click="change">点击切换</button>
//两个类名
<transition
enter-active-class="animated bounceInDown"
leave-active-class="animated fadeOutDown"
>
<div id="box" v-show="boo"></div>
</transition>
</div>
var vm=new Vue({
el:'#app',
data:{
boo:true
},
methods:{
change(){
this.boo=!this.boo
}
}
});
Computed计算属性的set和get
在computed里面定义的 变量 都是 计算属性 ,不能直接更改计算属性本身的值,需要定义当前计算属性的get和set方法 来赋值。
每一个计算属性内部默认对应有两个方法:
get方法 和set方法;
每次我们获取当前计算属性的值 都是默认调用 get方法 进行获取值。
如果我们想要手动的修改当前计算属性的值
必须手动定义 set方法 因为每次给计算属性赋值都是通过 set方法;
在set方法中也不能直接给当前计算属性赋值
因为计算属性本来就是依赖于其他属性存在而存在的属性,要想改变计算属性的值 就得改变被依赖的变量的那个值。
var vm=new Vue({
el:'#app',
data:{a:10,msg:0},
computed:{
/* b:function () {
return this.a*10;
}*/
b:{
get:function () {
console.log("当前是get方法,你是不是要获取b的值???");
return this.a*10
},
set:function (val) {
this.a=val;
}
}
},
methods:{
show(){
// this.b=this.msg
// this.a=this.msg
this.b=this.msg
}
}
});
计算属性分get和set方法,我们每次再给他赋值的时候都默认调用set方法,每次获取值的时候默认调用get方法,如果想要改变计算属性本身的值,就要复写,自己定义get和set方法。
组件的概述
什么是组件? 组件的意义在哪里? 为什么说Vue是组件化开发
所谓组件分为广义和狭义的理解:
广义: 封装了自己独立的数据和页面的一个单独内容
狭义理解: 单独的一个标签 既包含html内容也包含css和js内容
原生html开发的弊端:
-
原来的开发html我们是按照页面级别来进行分块的
比如:index.html
index.css
index.js
detail.html
detail.css
detail.js
如果其中一块html不想要了 那么首先从这么大页面中删除一块html 比较费劲 -
原来的开发css我们也是按照页面级别来进行分块的
删除了html部分 也要找到对应的css部分删除 -
原来的开发js我们也是按照页面级别来进行分块的
删除html部分 也要找到对应js部分进行删除
总结: 也就是说 我们所有内容都是互相依赖 互相耦合度比较高的代码,所以vue推出了组件化的概念
组件化:
把html+css+js单独封装成一个标签内容
例如: <lunbo></lunbo>
就会呈现一个轮播图,有html 有css 同样也就js。
所以组件化开发的优点/意义:
让页面结构看起来更清晰 很方便的修改页面元素,页面的组合显得更简单。
全局组件的创建
Vue的组件分为全局组件和局部组件
全局组件的注册:
Vue.component("组件的标签名",{
组件的键值对配置(template属性 methods属性 data属性)
})
<div id="app">
<h1>当前是vm对象挂载的目标</h1>
<!-- 引用全局组件-->
<aaa></aaa>
<aaa></aaa>
</div>
<div id="app1">
<h1>当前是vm1对象挂载的目标</h1>
<aaa></aaa>
</div>
Vue.component("aaa",{
//template定义当前组件的页面内容
// template:"<h1>我是aaa组件</h1>"
template:"<ul><li>我是新闻1</li><li>我是新闻2</li><li>我是新闻3</li></ul>"
})
var vm=new Vue({
el:'#app',
data:{ }
});
var vm1=new Vue({
el:"#app1"
})
局部组件的创建
在vue的$options里面定义:
components:{
组件的标签名:{
template属性 methods属性 data属性
}
}
<div id="app">
<h1>{{msg}}</h1>
<aaa></aaa>
<bbb></bbb>
</div>
<div id="app1">
<h1>{{msg}}</h1>
<!-- 报错 因为aaa和bbb是vm的局部组件
<aaa></aaa>
<bbb></bbb>-->
</div>
var vm=new Vue({
el:'#app',
data:{msg:"我是vm的挂载目标"},
components:{
aaa:{
template:"<h1>我是aaa组件的内容</h1>"
},
bbb:{
template:"<h2>我是bbb组件的内容</h2>"
}
}
});
var vm1=new Vue({
el:"#app1",
data:{
msg:"我是vm1挂载的目标"
}
})
组件的数据和事件的渲染
<div id="app">
<aaa ></aaa>
<!--
<aaa ></aaa>
<aaa ></aaa>
<aaa ></aaa>
-->
<bbb></bbb>
</div>
全局组件的数据和事件的使用:
Vue.component("组件的标签名",{
template:"组件的模板",
methods:{
组件的驱动函数
},
data:function(){
return{
组件的数据
}
}
})
Vue.component("aaa",{
template:"<h1 @click='show'>我是aaa组件---{{msg}}</h1>",
data:function(){
return {msg:"我是组件变量"}
},
methods:{
show(){alert("点我aaa干嘛")}
}
})
Vue.component("aaa",{
template:"<h1 @click='show'>我是aaa组件---{{msg}}</h1>",
data:function(){
return {msg:"我是组件变量"},
methods:{
show(){alert("点我aaa干嘛")}
}
})
想要给组件绑定数据和事件 就要操作组件的template里面
因为只有组件的template才是组件真正页面所在位置
局部组件的数据和事件的使用:
在Vue的$options里面定义
components:{
组件标签名:{
template:"组件的模板",
data:function(){
return{
组件的数据
}
},
methods:{
组件的驱动函数
}
}
}
var vm=new Vue({
el:'#app',
data:{msg:"HelloWorld!"},
components:{
bbb:{
template:"<h2 @click='show'>我是bbb组件---{{msg}}</h2>",
data(){
return {msg:"我是bbb组件的数据"}
},
methods:{
show(){alert("点我bbb干嘛")},
},
},
},
});
转下篇。