一、介绍
1.Vue.js是什么
1.Vue是一套用于构建用户界面的渐进式框架。
2.Vue的核心库只关注视图层,不仅容易上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue也完全能够为复杂的单页应用提供驱动。
- M (Model)
- V (View)
- VM(View-Model)
- 官方网站:https://cn.vuejs.org
2.初始Vue.js
<!-- id标识vue作用的范围 ,vue有明确的作用范围-->
<div id="app">
<!-- {{}} 插值表达式,绑定vue中的data数据 -->
{{ message }}
</div>
<!-- 引入vue.js-->
<script src="vue.min.js"></script>
<script>
// 创建一个vue对象
var app = new Vue({
el: '#app',//绑定vue作用的范围
data: {//定义页面中显示的模型数据
message: 'Hello Vue!'
}
})
</script>
这就是声明式渲染:Vue.js的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进DOM的系统。
核心思想:没有繁琐的DOM操作,如果是在JQuery中,我们需要先找到div节点,获取到DOM对象,然后进行一系列的节点操作。
二、基本语法
1.基本数据渲染和指令
你看到是 v-bind 特性被称为指令。指令带有前缀 v-
除了使用插值表达式{{}}进行数据渲染,也可以使用v-bind,v-bind可以简写为 :
<body>
<div id="app">
<!-- 未简写版 -->
<h1 v-bind:title="message">{{content}}</h1>
<!-- 简写形式 v-bind 指令简写形式 : -->
<h1 :title='message'>{{content}}</h1>
</div>
<script src="vue.min.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
content:'你好,这是北京',
message:'北京时间'+new Date().toLocaleString()
}
})
</script>
</body>
2.双向数据绑定
首先说明一下双向数据绑定与单向数据绑定的区别。
单向数据绑定:把Model绑定到View,当我们用JavaScript代码更新Model时,View就会自动更新。因此,我们不需要进行额外的DOM操作,只需要进行Model的操作就可以实现视图的联动更新。
双向数据绑定:把Model绑定到View的同时也将View绑定到Model上,这样就既可以通过更新Model来实现View的自动更新,也可以通过更新View来实现Model数据的更新。所以,当我们用JavaScript代码更新Model时,View就会自动更新,反之,如果用户更新了View,Model的数据也自动被更新了。
弄清楚了它的这种数据绑定机智,我们再来看Vue.js代码就会很清晰了,Vue.js主要是三种数据绑定形式,并且都是基于单向绑定与双向绑定的。
插值形式:插值形式就是{{data}}的形式,它就是单向数据绑定。
<body>
<div id="app">
<label >
<!-- 双向数据绑定 -->
<input type="text" v-model="meassage">
<!-- 单向数据绑定 -->
<input type="text" :value="meassage">
8\ </label>
<h1>{{meassage}}</h1>
</div>
<script src="vue.min.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
meassage:"窗前明月光"
}
})
</script>
</body>
3.事件
绑定事件使用 v-on:click 简写使用 @
<body>
<div id="app">
<h1>{{message}}</h1>
<!-- 未简写版 -->
<p><button v-on:click="search()">点我</button></p>
<!-- 简写版 -->
<!-- v-on 指令的简写形式 @ -->
<p><button @click="search()">点我</button></p>
</div>
<script src="vue.min.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
message:{}
},methods: {
search(){
this.message="窗前明月光"
}
}
})
</script>
</body>
4.修饰符
修饰符是以半角句号 . 指明的特殊后缀,修饰符用于指出一个指令应该以特殊方式绑定,例如**.prevent修饰符告诉v-on**指令对于触发事件调用 **event.preventDefault()**即阻止事件原本的默认行为。
<body>
<div id="app">
<!-- .prevent加上该修饰符取消默认操作,取消提交 -->
<!-- 表单就有自动提交的功能,如果不取消默认提交会自动提交-->
<form action="" v-on:submit.prevent="onSubmit()">
<label for="username">请输入</label>
<input type="text" id="username" v-model="user.username">
<button type="submit">保存</button>
</form>
<!-- 通过这个实验,如果不加上阻止事件默认行为修饰符,在控制台中看不到输出语句(会一闪而过),
当加上该修饰符后就可以在控制台看到输出语句,因为修饰符阻止了默认操作 -->
</div>
<script src="vue.min.js"></script>
<script
var app = new Vue({
el: '#app',
data: {
user:{}
},
methods: {
onSubmit(){
console.log("你好,北京-----------------------")
}
}
})
</script>
</body>
5.条件渲染
v-if条件指令
v-show条件指令
<body>
<div id="app">
<label> 你是否同意<input type="checkbox" v-model='ok'></label>{{ok}}
<p v-if='ok'>同意</p>
<p v-else>查看条件</p>
</div>
<!-- show 与if的不同,内存开销不同,
show在初始化的时候内存开销比较大,适用于频繁修改场景
if在切换的时候开销比较大,比较适用用修改频率较低的时候
-->
<div id="app2">
<label> 你是否同意<input type="checkbox" v-model='ok'></label>{{ok}}
<p v-show='ok'>同意</p>
<p v-show='!ok'>查看条件</p>
</div>
<script src="vue.min.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
ok:false
}
})
var app2 = new Vue({
el: '#app2',
data: {
ok:false
}
})
</script>
</body>
- v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件当地被销毁和重建。
- v-if也是惰性的:如果在初始渲染时条件为假,则什么也不做—直到条件变为真时,才会渲染条件块。
- 相比之下,v-show就简单的多—不管初始条件是什么,元素总是会被渲染,并且只是简单地基于css进行切换。
- 一般来说,v-if有更高的切换开销,而v-show有更高的初始渲染开销,因此,如果需要非常频繁的切换,则使用v-show较好,如果在运行时条件很少改变,则使用v-if比较好。
6.列表渲染
v-for列表循环指令
举例:简单列表渲染,表格渲染,表单渲染
<body>
<div id="app">
<!-- 简单的列表渲染 -->
<ul>
<!-- 第一个参数n是属性的值 ,第二个参数是坐标,坐标是从零开始的-->
<li v-for="(n,i) in 2">{{n}}-坐标是{{i}}</li>
</ul>
<ul>
<li v-for='val in numbers'>
{{val}}
</li>
</ul>
<!-- 简单列表:渲染计算集合里的值 -->
<ul>
<li v-for='val in evenNumbers'>
{{val}}
</li>
</ul>
<!-- 表格渲染,第一个参数是集合里的变量,第二个是索引值 -->
<table border="1">
<tr v-for="(val,index) in userList">
<td>{{index}}</td>
<td>{{val.id}}</td>
<td>{{val.username}}</td>
<td>{{val.age}}</td>
</tr>
</table>
<!-- 表单渲染 -->
<!-- 第一个val是user对象,第二个是属性值的key值,第三个是索引值 -->
<form action="">
<p v-for='(val,key,index) in user'>
<label>{{index+1}}--{{key}}:</label>
<input type="text" v-model='val'>
</p>
</form>
</div>
<script src="vue.min.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
numbers: [1, 2, 3, 4, 5],
userList: [
{ id: 1, username: 'zhang3', age: 33 },
{ id: 2, username: 'lisi', age: 43 },
{ id: 3, username: 'wangwu', age: 53 }
],
user: {
id: 18,
name: 'zhangsan',
age: 11
}
},
computed: {//计算属性,这里的数据是通过某中方式计算出来的
evenNumbers() {
return this.numbers.filter(function (number) {
return number % 2 === 0
})
}
}
})
</script>
</body>
7.计算属性
body>
<div id="app">
<p>{{message}}</p>
<!-- 翻转后的文字 -->
<!-- 1、插值数据绑定中使用表达式 -->
<p>插值模板中使用js表达式:{{message.split('').reverse().join('')}}</p>
<!--模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑 会让模板过重且难以维护。所以,对于任何复杂逻辑,你都应当使用计算属性-->
<!--2、使用计算属性-->
<p>计算器翻转:{{reversedMessage}}</p>
<p>计算器翻转:{{reversedMessage}}</p>
<!--3、使用方法-->
<p>调用方法翻转的消息:{{reversed()}}</p>
<p>调用方法翻转的消息:{{reversed()}}</p>
<!--
计算属性与方法的区别
计算属性是基于缓存的,如果计算相关依赖没有发生改变他们会从缓存中取值
而方法总是再次执行,每次调用都会执行,没有缓存
如果不想有缓存就使用方法
-->
</div>
<script src="vue.min.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
message:'八级大狂风'
},
computed: {
reversedMessage(){
console.log('计算属性翻转')
return this.message.split('').reverse().join('')
}
},
methods: {
reversed(){
console.log('方法翻转')
return this.message.split('').reverse().join('')
}
}
})
</script>
</body>
计算属性缓存VS方法
- 计算属性基于缓存:在相关依赖发生改变时他们才会重新求值。
- 方法将总会再次执行
- 我们为什么需要缓存?假设我们有个性能开销比较大的计算属性A,它需要遍历一个巨大的数组并且做大量的计算。然后我们可能有其他的计算属性依赖于A。如果没有缓存,我们将不可避免的多次执行A的计算!如果不希望有缓存,就用方法来替代。
8.侦听属性
当你有一些数据需要随着其他数据变动而变动的时候,就可以使用侦听属性。
例1:实际上这个例子是对watch的滥用,我们完全可以用计算属性更高效的完成同样操作。
<body>
<div id="app">
<label >姓: <input type="text" v-model='firstName'> </label>
<label >名: <input type="text" v-model='lastName'> </label>
<!-- 计算属性方式获取改变后的值-->
<p>{{getFullName}}</p>
<!-- 侦听属性方式获取改变后的值 -->
<p>{{fullName}}</p>
</div>
<script src="vue.min.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
firstName:'尼古拉斯',
lastName:'赵四',
fullName:'尼古拉斯 赵四',
},
watch: {//当监听的值发生改变的时候,做出相应的反应
firstName(val){
console.log("firstName changend")
this.fullName=val+' '+this.lastName
},
lastName(val){
console.log('lastName changend')
this.fullName=this.firstName+' '+val
}
},
computed: {//计算属性同样可以高效的完成
getFullName(){
return `${this.firstName} ${this.lastName}`
}
}
})
</script>
</body>
例2
模拟一个真实场景,当有内容输入的时候自动获取数据
<body>
<div id="app">
<p>
你可以问我一个问题我会如实回答你:
<input type="text" v-model="question">
<!-- 使用按钮点击查询 -->
<!-- <button @click='getAnswer()'>提问</button> -->
</p>
<p>来自灵魂的回答:{{answer}}</p>
</div>
<script src="vue.min.js"></script>
<!-- 引入jQuery -->
<script src="jquery-1.7.2.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
question:'',
answer:"请提问"
},
methods: {
getAnswer(){
this.answer='让我想象--------'
let vm=this
$.ajax(
{
url:'https://yesno.wtf/api',
type:'get',
success(data){
console.log(data)
vm.answer=data.answer
},
error(error){
vm.answer="找不到该API接口"+error
}
}
)
}
},watch: {
question(newQuestion, oldQuestion){
//当监听到有问题输入的时候自动调用该方法
this.getAnswer()
}
}
})
</script>
</body>
使用watch:当需要在数据变化时执行异步或者开销比较大的操作时,这个方法最有用。
9.过滤器
过滤器分为局部过滤器和全局过滤器
过滤器常用来处理文本格式化的操作,可以用在两个地方:双花括号插值和v-bind表达式。过滤器应该被添加在JavaScript表达式的尾部,由“管道 | "符号指示
<body>
<div id="app">
<table>
<tr v-for='user in userList'>
<td>{{user.id}}</td>
<!-- 该处使用全局过滤器,全局过滤器可以应用在不同的vue实例的渲染范围中 -->
<td>{{user.name|caseFilter}}</td>
<td>{{user.age}}</td>
<!-- 该处使用局部过滤器 ,局部过滤器只能应用在定义的Vue实例中-->
<td>{{user.gender|genderFilter}}</td>
</tr>
</table>
</div>
<script src="vue.min.js"></script>
<!-- 引入外部过滤器文件 -->
<script src="filters/caseFilter.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
userList:[
{id:1,name:'zhang3',age:33,gender:1},
{id:2,name:'li4',age:44,gender:0},
{id:3,name:'wang5',age:55,gender:1}
]
},
filters: {
//局部过滤器
genderFilter(gender){
return gender===1?'男':'女'
}
}
})
</script>
</body>
10.组件
- 组件(Component)是Vue.js最强大的功能之一。
- 组件可以扩展HTML元素,封装可重复的代码。
- 组件系统让我们可以用独立可重复的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树。
1.局部组件
定义组件
var app = new Vue({
el: '#app',
// 定义局部组件,这里可以定义多个局部组件
components: {
//组件的名字
'Navbar': {
//组件的内容
template: '<ul><li>首页</li><li>学员管理</li></ul>'
}
}
})
使用组件
<div id="app">
<!--将定义好的组件直接拿来用就可以-->
<Navbar></Navbar>
</div>
2.全局组件
定义全局组件
在项目目录下新建一个js文件,用于定义全局组件
// 定义全局组件
Vue.component('Navbar', {
template: '<ul><li>首页</li><li>学员管理</li><li>讲师管理</li></ul>'
})
使用全局组件
<div id="app">
<Navbar></Navbar>
</div>
<script src="vue.min.js"></script>
<script src="components/Navbar.js"></script>
<script>
var app = new Vue({
el: '#app'
})
</script>