Vue 基本语法
Vue 介绍
什么是Vuejs?
- 官网
- Vue 读音 /vjuː/,类似于 view
- 渐近式框架
- 高级功能
- 解耦视图和数据
- 可复用的组件
- 前端路由技术
- 状态管理
- 虚拟DOM
安装Vue
- 直接CDN引入
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
npm install vue
简单案例
显示普通信息
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>index</title>
<script src="vue.js"></script>
</head>
<body>
<div id="app">
<h1>{{message}}</h1>
</div>
</body>
<script>
// 编成范式:声明式编程
const app = new Vue({
el: "#app", // 用于挂载要管理的元素
data: { // 定义数据
message: "Hello Vue"
}
})
</script>
</html>
显示个列表信息
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>index</title>
<script src="vue.js"></script>
</head>
<body>
<div id="app">
<ul>
<li v-for="item in movies">
{{item}}
</li>
</ul>
</div>
</body>
<script>
const app = new Vue({
el: "#app",
data: {
movies: ['流浪地球', '无名之辈', '恶人传', '寄生虫']
}
})
</script>
</html>
实现计数器
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>index</title>
<script src="vue.js"></script>
</head>
<body>
<div id="app">
<h3>当前计数:{{counter}}</h3>
<!-- <p><button v-on:click="counter++">+</button></p> -->
<!-- <p><button v-on:click="counter--">-</button></p> -->
<button v-on:click="plus">+</button>
<button @click="reduce">-</button>
</div>
</body>
<script>
const app = new Vue({
el: "#app",
data: {
counter: 0
},
methods: {
plus: function() {
this.counter++
},
reduce () {
this.counter--
}
}
})
</script>
</html>
MVVM

MVVM:Model View ViewModel
view层:视图层,在前端通常是DOM层,主要用来展示信息
Model层:数据层,通常都是从后端请求过来的数据
VueModel层:视图模型层,
Data Binding,数据绑定,将Model的改变实时的反应到View中;
DOM Listenter,DOM监听,当DOM发生事件,可以被监听到,并在需要的情况下改变对应的Data
使用到Vue的options
- el:
- 类型:string | HTMLElement
- 作用:决定之后Vue实例管理的一个DOM
- data:
- 类型:Object(字典) | Function(组件当中data必须是一个函数)
- 作用:Vue实例对应的数据对象
- methods:
- 类型:{[key: string]: Function()
- 作用:定义属于Vue的一些方法
生命周期

Vue基本语法
插值操作
- Mustache
表示:{{}}
用法:括号内JS表达式
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
-
v-once
说明:执行一次性地插值,当数据改变时,插值处的内容不会更新。
用法:<span v-once>{{ msg }}</span> -
v-html
说明:输出真正的HTML,为防止XSS攻击,不要对用户提供的内容使用
用法:
<p v-html="rawHtml"></p>
data: {
rawHtml: "<span style='color: red'>This should be red.</span>"
}
-
v-text
说明:插入文本,不够灵活,会自动覆盖标签内的值
用法:<span v-text="msg"></span> -
v-pre
说明:不解析{{}}的值
用法:<span v-pre>{{ msg }}</span>渲染的结果仍是{{msg}} -
v-cloak
说明:可以用来隐藏未编译的Mustache标签直到实例准备完成。
<style>
[v-cloak]{
display: none;
}
</style>
<div id="app">
<h1 v-cloak>{{message}}</h1>
</div>
<script>
// 在vue解析之前,div中有一个属性v-cloak
// 在vue解析之后,会自动删除v-cloak
setTimeout(function(){
const app = new Vue({
el: "#app",
data: {
message: "Hello Vue",
}
});
}, 3000)
</script>
v-bind 属性绑定
说明:动态绑定属性
语法糖::
用法:<a v-bind:href="url"> click </a>
v-bind绑定class属性
- 对象语法
用法:<div :class="{ 属性名: 变量 }"></div>,变量的值为true或false
<div class="static" :class="{ active: isActive}">
Hello Vue
</div>
data: {
isActive: true,
}
绑定的数据对象可以不用在在模板里
<div v-bind:class="classObject"></div>
data: {
classObject: {
active: true,
}
}
还可以把数据对象放到计算属性上
<div :class="classObject"></div>
data: {
isActive: true,
},
computed: {
classObject: function () {
return {
active: this.isActive && !this.error,
}
}
}
- 数组语法
<div :class="[active, error]"></div>
data: {
active: 'active',
error: 'text-danger'
}
可以在数组中使用三元表达式
<div :class="[isActive ? 'active' : '', error]"></div>
在数组中加上引号就是字符串,不加引号就是变量,数组和对象可以混合使用
在组件上的使用
当在一个自定义组件上使用 class 属性时,这些 class 将被添加到该组件的根元素上面。这个元素上已经存在的 class 不会被覆盖。
Vue.component('my-component', {
template: '<p class="foo bar">Hi</p>'
})
<my-component :class="{ active: isActive }"></my-component>
# 结果:
<p class="foo bar active">Hi</p>
v-bind绑定style属性
- 对象方法
key:值为属性名称,驼峰式(fontSize)或短横线分隔(font-size引号括起来)
value:值为变量
<div :style="{ color: color, fontSize: fontSize }"></div>
data: {
color: 'red',
fontSize: '30px'
}
也可以直接绑定一个样式对象
<div :style="styleObject"></div>
data: {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
- 数组语法
<div :style="[baseStyles, ]"></div>
计算属性
- 基本使用
当一个变量改变时另一个变量可以发生改变,或者模板中插值操作的表达式太过复杂时,都可以把变量拿出来放到computed内。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>index</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
<h1>{{msg}}</h1>
<h1>{{reverseMsg}}</h1>
</div>
</body>
<script>
const app = new Vue({
el: "#app",
data: {
msg: "Hello Vue",
},
computed: {
reverseMsg: function () {
return this.msg.split("").reverse().join('')
}
}
});
</script>
</html>
- 和方法比较
通过方法也能实现相同效果:
<h1>{{reverseMsg()}}</h1>
methods: {
reverseMsg: function () {
return this.msg.split('').reverse().join('')
}
}
不同点:计算属性是基于它们的响应式依赖进行缓存的,只用相关响应式依赖发生改变时它们才会重新求值,这就意味着只要 message 还没有发生改变,多次访问 reversedMsg 计算属性会立即返回之前的计算结果,而不必再次执行函数;而每当触发重新渲染时,对于方法渲染,将总会再次执行函数。
- 和侦听属性比较
侦听属性watch,当用数据改变时,调用watch,如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>index</title>
<script src="../vue.js"></script>
</head>
<body>
<div id="app">
<h1>{{fullname}}</h1>
</div>
</body>
<script>
const app = new Vue({
el: "#app",
data: {
firstName: "Foo",
lastName: "Bar",
fullname: "Foo Bar"
},
watch: {
firstName: function(newVal, oldVal){
this.fullname = newVal + " " + this.lastName
},
lastName: function(newVal, oldVal){
this.fullname = this.firstName + " " + newVal
}
}
});
</script>
</html>
使用计算属性
computed: {
fullname: function () {
return this.firstName + " " + this.lastName
}
},
虽然计算属性在大多数情况下更合适,但当需要在数据变化时执行异步或开销较大的操作时,watch方式是最有用的。
- 计算属性的setter
计算属性默认只有getter,不过在需要时也提供一个setter:
computed: {
fullName: {
// getter
get: function () {
return this.firstName + ' ' + this.lastName
},
// setter
set: function (newVal) {
let names = newVal.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
事件监听
指令:v-on
作用:绑定事件监听
语法糖:@
预期:Function | Inline Statement | Object
参数:event
简单示例,点击按钮实现数字加减
<div id="app">
<h3>{{count}}</h3>
<button @click="increment">+</button>
<button @click="decrement">-</button>
</div>
<script>
const app = new Vue({
el: "#app",
data: {
count: 0
},
methods: {
increment () {
this.count++
},
decrement () {
this.count--
},
}
});
</script>
事件监听也可以传参数
- 当不需要传参数时,模板中可以省略()
- 模板有(),但是没传参数,方法的参数值为
undefined - 模板中事件传参数,方法得到相对应的值
- 当模板中省略(),但是方法内有形参,得到的结果时监听事件
<div id="app">
<button @click="btn1">按钮1</button>
</div>
<script>
const app = new Vue({
el: "#app",
methods: {
btn1 (event) {
console.log(event);
}
}
});
</script>
- 当方法内既想得到普通参数,又想得到监听事件,使用
$event
<div id="app">
<button @click="btn(123, "abc", $event)">按钮</button>
</div>
<script>
const app = new Vue({
el: "#app",
methods: {
btn (num, chr, event) {
console.log(num, chr, event);
}
}
});
</script>
v-on的修饰符:
- .stop,调用event.stopPropagation(),当父、子标签上都有事件时,阻止事件冒泡,加在子标签上
- .prevent,调用event.preventDefault(),阻止默认事件
- .(keyCode | keyAlias),只有当事件是从特定键触发时才能触发回调,如:
@keyup.a=funcName - .native,监听组件根元素的原生事件
- .once,只能触发一个回调
条件判断指令
指令:v-if, v-else-if, v-else
使用方式:
<div id="app">
<h2 v-if="score>100">S</h2>
<h2 v-else-if="score>80">A</h2>
<h2 v-else-if="score>60">B</h2>
<h2 v-else>C</h2>
</div>
<script>
const app = new Vue({
el: "#app",
data: {
score: 0
},
});
</script>
案例:切换登录方式
<div id="app">
<span v-if="loginStyle">
<label for="username">账号</label>
<input type="text" id="username" placeholder="用户账号">
</span>
<span v-else>
<label for="email">邮箱</label>
<input type="text" id="email" placeholder="用户邮箱">
</span>
<button @click="loginStyle = !loginStyle">切换类型</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
loginStyle: true
}
})
</script>
问题:容易出现input复用问题,当一个输入框内有用户输入,切换登录方式时,用户输入的内容还在
原因:因为Vue使用虚拟DOM渲染,出于性能考虑,会尽可能地复用已经存在地元素,而不是重新创建新的元素
解决:给每个input加上不同地key属性
<span v-if="loginStyle">
<label for="username">账号</label>
<input type="text" id="username" placeholder="用户账号" key="username">
</span>
<span v-else>
<label for="email">邮箱</label>
<input type="text" id="email" placeholder="用户邮箱" key="email">
</span>
类似可以隐藏标签的指令还有v-show。
v-show和v-if一样,都是决定标签是否被渲染
不同点时,v-if为false时,标签就根本不会存在;而v-show的实质是样式为display: none,适用于需要频繁切换显示和隐藏的标签
循环指令
指令:v-for
使用:
<div id="app">
<ul>
<li v-for="movie in movies">{{movie}}</li>
</ul>
</div>
<script>
const app = new Vue({
el: "#app",
data: {
movies: ['无名之辈', "流浪地球", '寄生虫', '魔童降世', "战狼2"]
},
});
</script>
在遍历时可以获得索引值v-for="(movie, index) in movies",如果遍历对象时,也可以获得key、value和index值v-for="value, key, index in object"
官方推荐使用v-for时,使用key属性,但要保证key的唯一性,不建议使用索引值。原因是当数组插入数据时,index发生变化,就不能利用key的特性
为什么使用key属性?这个Vue的虚拟DOM的Diff算法有关。
参考React's diff algorithm
一般来讲,在5个组件数组中插入一个组件,得到新的数组,两个组件数组形成映射关系是非常难的,
默认的,diff算法是把两个数组按顺序形成映射。但是如果你加入key属性,就可以帮助diff快速形成映射。
哪些数组方法是响应式的?
push(); pop(); shift(); unshift(); splice(); sort(); reverse()
用法参考:数组方法的使用
注意:通过索引值修改数组中的元素不是响应式 ,如果要修改元素可以通过splice(),或者使用Vue.set(要修改的对象, 索引值, 修改后的值)
表单绑定
指令:v-model
作用:实现表单元素与数据的双向绑定
基本使用:
<div id="app">
<input type="text" v-model="message">
<h3>{{message}}</h3>
</div>
<script>
const app = new Vue({
el: "#app",
data: {
message: "hello"
},
});
</script>
<!--这里的v-model绑定的就是input的value值-->
相当于:v-bind和v-on搭配使用
<div id="app">
<input type="text" :value="message" @input="valueChange">
<h3>{{message}}</h3>
<!--另外写法-->
<input type="text" :value="message" @input="message=$event.target.value">
</div>
<script>
const app = new Vue({
el: "#app",
data: {
message: "hello"
},
methods: {
valueChange (event) {
this.message = event.target.value;
}
}
});
</script>
其他使用:
- radio,单选框,当有 v-model 时,可以省略 name 属性
<div id="app">
<input type="radio" value="男" v-model="sex">男
<input type="radio" value="女" v-model="sex">女
<h3>性别:{{sex}}</h3>
</div>
<script>
const app = new Vue({
el: "#app",
data: {
sex: "男" // 默认值
},
});
</script>
- checkbox,复选框
<!--单选框-->
<div id="app">
<label for="agreement">
<input type="checkbox" id="agreement" v-model="isAgree">用户协议
</label>
<p><button :disabled="!isAgree">Next</button></p>
</div>
<script>
const app = new Vue({
el: "#app",
data: {
isAgree: false
},
});
<!--多选框使用-->
<div id="app">
<input type="checkbox" value="篮球" v-model="hobby">篮球
<input type="checkbox" value="足球" v-model="hobby">足球
<input type="checkbox" value="羽毛球" v-model="hobby">羽毛球
<h2>{{hobby}}</h2>
</div>
<script>
const app = new Vue({
el: "#app",
data: {
hobby: ['篮球']
},
});
</script>
- select
<!--单选-->
<div id="app">
<select name="province" id="" v-model="province">
<option value="安徽">安徽</option>
<option value="江苏">江苏</option>
<option value="上海">上海</option>
</select>
<h2>{{provice}}</h2>
</div>
<script>
const app = new Vue({
el: "#app",
data: {
province: "上海"
},
});
</script>
<!--多选-->
<div id="app">
<select name="province" id="" v-model="provinces" multiple>
<option value="安徽">安徽</option>
<option value="江苏">江苏</option>
<option value="上海">上海</option>
</select>
<h2>{{provice}}</h2>
</div>
<script>
const app = new Vue({
el: "#app",
data: {
provinces: ["上海"]
},
});
</script>
修饰符:
- lazy:可以让数据失去焦点或者回车时才会更新
- number:把输入的内容自动转换成数字类型,和type="number"(只能输入数字)配合使用
- trim:可以过滤内容左右两边的空格
Vue的options之过滤器
<div>{{price|showPrice}}</div>
<script>
const app = new Vue({
el: "#app",
data: {
price: 56.00
},
filters: {
showPrice (price) {
return "¥" + price.toFixed(2) // 显示小数点后2位
}
}
});
</script>



浙公网安备 33010602011771号