目录
1、Vue简介
一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
2、MVVM
vue.js 是当前一个js的 MVVM库,它以数据驱动和组件化的思想构造而成,比其它框架,简洁,上手快。
(1)vue实现挂载到某个元素上
(2)当vue实现创建后,形成双向绑定,上面dom listeners和data binding二个工具
(3)从view侧看,vue中datalistener工具帮助我们监听dom变化,如果dom变化更新model数据
(4)如果从model侧看,当我们更新mode数据,vue中的data bindings工具会帮我们更新view数据.
3、安装
(1)<script>标签引入(我使用的方法)
开发一般用开发版本 https://vuejs.org/js/vue.js
(2)CDN
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
(3)NPM
在用 Vue 构建大型应用时推荐使用 NPM 安装[1]。NPM 能很好地和诸如 webpack 或 Browserify 模块打包器配合使用。同时 Vue 也提供配套工具来开发单文件组件。
# 最新稳定版
$ npm install vue
如果慢的话 用
npm install --registry=https://registry.npm.taobao.org
最好不要 用cnpm,可能会报bug
(4)命令行工具CLI
vue 提供了一个官方的 CLI,为单页面应用 (SPA) 快速搭建繁杂的脚手架。它为现代前端工作流提供了 batteries-included 的构建设置。只需要几分钟的时间就可以运行起来并带有热重载、保存时 lint 校验,以及生产环境可用的构建版本。
4、First Of Vue
创建index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Vue入门</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="root">hello {{msg}}</div>
<script>
new Vue({
el:"#root",
data:{
msg:"world"
}
})
</script>
</body>
</html>
结果:
new vue()表示创建VUE实例
el :#id 与页面元素做绑定
data: 存放标签内容,标签中使用{{}}调用data的数据 这里充分体现了VUE只关注与数据的变化,而不关心DOM操作
4.1 挂载点、模板、实例
(1)挂载点:这个div标签为VUE实例的挂载点
<div id="root">hello {{msg}}</div>
(2)模板:挂载点内部的内容成为模板内容
除了以上写法,还可以写到实例里面的template属性中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Vue入门</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="root"></div>
<script>
new Vue({
el:"#root",
template:'<h1>hello {{msg}}</h1>',
data:{
msg:"world"
}
})
</script>
</body>
</html>
(3)实例需要指定挂载点,VUE会自动结合模板和数据生成最终的内容放入挂在点中
4.2 VUE实例中的数据、事件与方法
4.2.1 数据
{{}}取数据的方法叫插值表达式
结果:
这里插值表达式{{}}也可改为 v-text或v-html
<div id="root">
<h1 v-text="number"></h1>
</div>
v-text、v-html 区别
(1) v-text
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Vue入门</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="root">
<div v-text="content"></div>
</div>
<script>
new Vue({
el:"#root",
data:{
content:"<h1>hello</h1>"
}
})
</script>
</body>
</html>
结果
<h1>hello</h1>
(2) v-html
结果
hello
4.2.2 事件与方法 v-on
(1)事件处理方法
用v-on绑定事件与方法,用于监听DOM事件,可简写为@
实现效果:
点击hello后变为world
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Vue入门</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="root">
<div v-on:click="handleClick">{{content}}</div>
<!-- 或<div @click="handleClick">{{content}}</div> -->
</div>
<script>
new Vue({
el: "#root",
data: {
content: "hello",
},
methods: {
handleClick: function () {
this.content = "world"
}
}
})
</script>
</body>
</html>
(2)内联处理器中的方法
除了直接绑定到一个方法,也可以在内联 JavaScript 语句中调用方法:
<div id="example-2">
<!-- `greet` 是在下面定义的方法名 -->
<button v-on:click="greet">Greet</button>
</div>
new Vue({
el: '#example-3',
methods: {
say: function (message) {
alert(message)
}
}
})
5、属性绑定和双向数据绑定 v-bind, v-model
5.1 属性绑定
v-bind 实现属性的绑定,下面当鼠标悬停时会显示data中的内容,<div>中title的内容是JS表达式
v-bind 可以简写为 :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>属性绑定和双向数据绑定
</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="root">
<div v-bind:title="'shawn, ' + aa">hello world</div>
<!-- 或<div :title="'shawn, ' + aa">hello world</div> -->
</div>
<script>
new Vue({
el: "#root",
data:{
aa:"this is hello world"
}
})
</script>
</body>
</html>
5.2 双向绑定
v-model 实现输入值和页面数据的双向绑定
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>属性绑定和双向数据绑定
</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="root">
<div :title="'shawn, ' + aa">hello world</div>
<input v-model="content"/>
<div>{{content}}</div>
</div>
<script>
new Vue({
el: "#root",
data:{
aa:"this is hello world",
content:"this is content"
}
})
</script>
</body>
</html>
结果
6、计算属性和侦听器
6.1 计算属性
VUE实例中的computed 属性
计算属性本质是方法,只不过我们在运用时把它当成属性使用,并不会把它当做方法调用
注意1:计算属性在引用时不要加(),当成属性就好
注意2:只要计算属性这个function内部,所用到的任何data 中的数据发生了变化,就会立即重新计算这个计算属性的值
注意3:计算属性的求职结果会被缓存起来,方便下次直接使用
(1)实现效果:输入姓和名后,在底下显示fullName = firstName + lastName
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>属性绑定和双向数据绑定
</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="root">
姓: <input v-model="lastName"/>
名: <input v-model="firstName"/>
<div>{{fullName}}</div>
</div>
<script>
new Vue({
el: "#root",
data:{
firstName:'',
lastName:''
},
computed:{
fullName:function () {
return this.firstName + ' ' + this.lastName
}
}
})
</script>
</body>
</html>
结果
(2) 实现效果:统计已完成/未完成任务
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>计算属性
</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="root">
<h2>Tasks</h2>
<ul>
<li v-for="task in tasks" v-text="task.description"></li>
</ul>
<h2>Completed Tasks</h2>
<ul>
<li v-for="task in tasks" v-text="task.description" v-if="task.completed"> </li>
</ul>
<h2>inCompleted Tasks</h2>
<ul>
<!-- 法一
<li v-for="task in tasks" v-text="task.description" v-if="!task.completed"> </li> -->
<li v-for="task in inCompletedTasks" v-text="task.description"></li>
</ul>
</div>
<script>
new Vue({
el: "#root",
data: {
tasks:[
{description:'Go to store',completed:false},
{description:'Make dinner',completed:true},
{description:'Clean room',completed:false}
]
},
computed:{
inCompletedTasks:function() {
return this.tasks.filter(task => ! task.completed);
}
}
})
</script>
</body>
</html>
结果
6.2 侦听器
作用:1、侦听data中数据的变化,若发生变化则触发对应的function
2、监听路由地址的变化
实现效果:在data中定义count,计算姓名字母的个数
在VUE实例中添加watch属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>属性绑定和双向数据绑定
</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="root">
姓: <input v-model="lastName"/>
名: <input v-model="firstName"/>
<div>{{fullName}}</div>
<div>{{count}}</div>
</div>
<script>
new Vue({
el: "#root",
data:{
firstName:'',
lastName:'',
count:0
},
computed:{
fullName:function () {
return this.firstName + ' ' + this.lastName
}
},
watch:{
firstName:function(){
this.count++
},
lastName:function(){
this.count++
}
}
})
</script>
</body>
</html>
结果
改进:监听fullName的变化
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>属性绑定和双向数据绑定
</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="root">
姓: <input v-model="lastName"/>
名: <input v-model="firstName"/>
<div>{{fullName}}</div>
<div>{{count}}</div>
</div>
<script>
new Vue({
el: "#root",
data:{
firstName:'',
lastName:'',
count:0
},
computed:{
fullName:function () {
return this.firstName + ' ' + this.lastName
}
},
watch:{
fullName:function(){
this.count++
}
}
})
</script>
</body>
</html>
结果:
7、v-if、v-show、v-for
7.1 v-if
实现效果:点击按钮实现内容的隐藏与显示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>属性绑定和双向数据绑定
</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="root">
<div v-if="show">hello world</div>
<button @click="handleClick">toggle</button>
</div>
<script>
new Vue({
el: "#root",
data:{
show: true
},
methods:{
handleClick:function(){
this.show = !this.show
}
}
})
</script>
</body>
</html>
结果:
7.2 v-show
将上面代码改变
<div v-show="show">hello world</div>
实现效果与v-if一致,但查看页面元素发现:
v-show
属性改变
v-if
元素消失
7.3 v-for
7.3.1 把一个数组对应为一组元素
循环list数据项,每项内容存到item,展示时输出item
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>v-if,v-show,v-for
</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="root">
<div v-show="show">hello world</div>
<button @click="handleClick">toggle</button>
<ul>
<li v-for= "(item, index) of list" :key = "index">{{item}}</li>
</ul>
</div>
<script>
new Vue({
el: "#root",
data:{
show: true,
list:[1,2,3]
},
methods:{
handleClick:function(){
this.show = !this.show
}
}
})
</script>
</body>
</html>
7.3.2 使用对象
(1) 显示值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>v-if,v-show,v-for
</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="root">
<ul >
<li v-for="value in object">
{{value}}
</li>
</ul>
</div>
<script>
new Vue({
el: "#root",
data:{
object:{
title:"How to do lists in Vue",
author:"shawn jing",
publishedAt:"2019-06-04"
}
}
})
</script>
</body>
</html>
结果:
(2) 显示键值对
结果:
(3) 显示索引
建议写上 key为index,确保它们在每个索引位置正确渲染
结果:
7.3.3、显示过滤/排序后的结果
效果:列出能被2整除的数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>v-if,v-show,v-for
</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="root">
<ul>
<li v-for="n in evenNumbers">
{{n}}
</li>
</ul>
</div>
<script>
new Vue({
el: "#root",
data:{
numbers: [ 1, 2, 3, 4, 5 ]
},
computed:{
evenNumbers:function(){
return this.numbers.filter(function(number){
return number % 2 === 0
})
}
}
})
</script>
</body>
</html>
结果:
在计算属性不适用的情况下 (例如,在嵌套 v-for
循环中) 可以使用一个方法:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>v-if,v-show,v-for
</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="root">
<ul>
<li v-for="n in(evenNumbers)">
{{n}}
</li>
</ul>
</div>
<script>
new Vue({
el: "#root",
data:{
numbers: [ 1, 2, 3, 4, 5 ]
},
methods:{
evenNumbers: function(numbers){
return number % 2 === 0
}
}
})
</script>
</body>
</html>
7.3.4 在v-for里使用值范围
<div>
<span v-for="n in 10">{{ n }} </span>
</div>
结果
1 2 3 4 5 6 7 8 9 10
7.4 自定义指令
除了核心功能默认内置的指令 (v-model
和 v-show
),Vue 也允许注册自定义指令。
当页面加载时,该元素将获得焦点
在模板中任何元素上使用新的 v-focus
属性
7.4.1 钩子函数
一个指令定义对象可以提供如下几个钩子函数 (均为可选):
-
bind
:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。 -
inserted
:元素插入到DOM中的时候。 -
update
:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。 -
componentUpdated
:指令所在组件的 VNode 及其子 VNode 全部更新后调用。 -
unbind
:只调用一次,指令与元素解绑时调用。
和JS行为相关的,放到inserted
样式相关的,放到bind
接下来我们来看一下钩子函数的参数 (即 el
、binding
、vnode
和 oldVnode
)。
7.4.2 钩子函数参数
指令钩子函数会被传入以下参数:
如binging.name是自定义命令的名字
el
:指令所绑定的元素,可以用来直接操作 DOM 。binding
:一个对象,包含以下属性:name
:指令名,不包括v-
前缀。value
:指令的绑定值,例如:v-my-directive="1 + 1"
中,绑定值为2
。oldValue
:指令绑定的前一个值,仅在update
和componentUpdated
钩子中可用。无论值是否改变都可用。expression
:字符串形式的指令表达式。例如v-my-directive="1 + 1"
中,表达式为"1 + 1"
。arg
:传给指令的参数,可选。例如v-my-directive:foo
中,参数为"foo"
。modifiers
:一个包含修饰符的对象。例如:v-my-directive.foo.bar
中,修饰符对象为{ foo: true, bar: true }
。
vnode
:Vue 编译生成的虚拟节点。oldVnode
:上一个虚拟节点,仅在update
和componentUpdated
钩子中可用。
例1 只有一个参数
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.2.3/css/bulma.css">
<style type="text/css">
body {
padding-top: 40px;
}
</style>
<script src="./vue.js"></script>
</head>
<body>
<div id="root">
<div>
<input v-focus>
</div>
</div>
<script>
Vue.directive('focus', {
inserted: function(el) {
el.focus()
}
})
new Vue({
el: "#root",
data: {
}
})
</script>
</body>
</html>
结果
例2 有两个参数
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.2.3/css/bulma.css">
<style type="text/css">
body {
padding-top: 40px;
}
</style>
<script src="./vue.js"></script>
</head>
<body>
<div id="root">
<div>
<input v-focus v-color="'blue'">
</div>
</div>
<script>
Vue.directive('focus', {
//和JS行为相关的,放到inserted
inserted: function(el) {
el.focus()
}
})
Vue.directive('color', {
//和样式相关的,放到bzind
bind: function(el,binding) {
el.style.color = binding.value
}
})
new Vue({
el: "#root",
data: {
}
})
</script>
</body>
</html>
结果
注意:'blue'是字符串,“’blue‘”是变量
8 生命周期函数
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.2.3/css/bulma.css">
<style type="text/css">
body {
padding-top: 40px;
}
</style>
<script src="./vue.js"></script>
</head>
<body>
<div id="root">
<div>
<h3 id="h3">{{msg}}</h3>
<input type="button" value="修改msg" @click="msg='no'"/>
</div>
</div>
<script>
new Vue({
el: "#root",
data: {
msg:"ok"
},
methods:{
show(){
alert("执行了show方法")
}
},
beforecreated(){
console.log(this.msg)//空
console.log(this.show())//空
//注意在beforecreated生命周期函数 data和methods都没有被初始化
},
created(){
console.log(this.msg)//执行
console.log(this.show())//执行
//注意在 created()生命周期函数 data和methods都被初始化
//所以如果要调用data和methods,最早只能在created中操作
},
beforeMount(){
//表示div和模板已经编译完成,但是没有把模板渲染到页面中
console.log(document.getElementById('h3').innerText)//输出为{{msg}}
},
mounted(){
//页面渲染好了,是实例创建期间的最后一个生命周期函数
//如果在用某些插件操作DOM,最早要在mounted中执行
console.log(document.getElementById('h3').innerText)//显示Ok
},
//以下是运行中的两个事件
beforeUpdate(){
console.log("界面上的元素内容: "+document.getElementById('h3').innerText)//ok
console.log("data中的msg数据是:"+this.msg)//no
//结论:当执行beforeUpdate时,页面的数据还是旧的,此时数据是最新的,但页面尚未保持同步
},
updated(){
console.log("界面上的元素内容: "+document.getElementById('h3').innerText)//no
console.log("data中的msg数据是:"+this.msg)//no
//结论:当执行update时,页面和数据保持同步
}
})
</script>
</body>
</html>