vue
vue基础
安装vue
-
使用CDN引入
-
下载和引入
-
npm安装
npm i vue
vue是声明式编程。
案例一
<div id="app">{
{message}}</div>
<script>
// let用于定义变量,const定义常量
const app = new Vue({
el: '#app',
data: {
//定义数据
message: '你好啊'
}
})
</script>
-
我们首先来阅读以下js代码,会发现创建了一个Vue对象。
-
创建vue对象的时候,传入了一些options:{}
- {}中包含了el属性,决定了这个vue对象挂载到哪一个元素上,很明显吗我们这里是挂载到了id为app的元素上。
- {}中包含了data属性,该属性会存储一些数据。这些数据是我们直接定义出来的,也有可能是来自网络,从服务器加载的。
-
代码是响应式的。
案例2展示列表
<div id="app">
<ul>
<li v-for="item in movies">{
{item}}</li>
</ul>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好',
movies: ['海贼王', '前任三', '星际穿越', '大话西游']
}
})
</script>
案例三计数器
<div id="app">
<h2>当前计数:{
{counter}}</h2>
<!-- v-on:click等价于@click -->
<!-- <button v-on:click="counter++">+</button> -->
<!-- <button v-on:click="counter--">-</button> -->
<button @click="add">+</button>
<button @click="sub">-</button>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
counter: 0
},
methods: {
add: function() {
console.log('add被执行');
this.counter += 1
},
sub() {
console.log('sub被执行');
this.counter -= 1
}
}
})
</script>
语法糖就是:这种写法太复杂了,我给你点甜头,用简单点的语句写。
Vue中的MVVM
- view层
表示视图层,在我们前端开发中,通常就是DOM层。主要作用是给用户展示各种信息
- model层
数据层,数据可能是我们固定死的数据,更多的是来自我们服务器从网络中请求下来的数据
- VueModel层
视图层模型。是view和model之间沟通的桥梁。一方面实现了数据绑定,将model的改变实时的反应到view中。另一方面,它实现了Dom Listener,也就是DOM监听,当DOM发生了一些事件(点击,滚动,touch等)时,可以监听到,并在需要的情况写改变对应的Data。
比如在案例二的计数器案例中
创建Vue实例传入的options
在创建vue实例中,传入了一个对象options。那么这个options可以包含哪些选项呢?
- el
- 类型:string|HTMLElement
- 作用:决定之后Vue实例会管理哪一个DOM
- data
- 类型:Object|Function(在组件化中,data必须是函数)
- 作用:Vue实例对应的数据对象
- methods
- 类型:{ [key:string] : Function }
- 作用:定义属于Vue的方法,可以在其他地方调用,也可以在指令中使用
开发中什么时候叫做方法,什么时候叫做函数?
方法叫做method, 定义在类里面的叫做方法,和一个实例对象挂钩的。函数叫function,是单独的
Vue的生命周期
生命周期,从字面上理解就是事物从诞生到消亡的整个过程。Vue有自己的生命周期。
通过new Vue()
创建实例,每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。
created和mounted的区别:
created:在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成视图。
mounted:在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作。
其实两者比较好理解,通常created使用的次数多,而mounted通常是在一些插件的使用或者组件的使用中进行操作,比如插件chart.js的使用: var ctx = document.getElementById(ID); 通常会有这一步,而如果你写入组件中,你会发现在created中无法对chart进行一些初始化配置,一定要等这个html渲染完后才可以进行,那么mounted就是不二之选。
定义vue的template
mustache
<div id="app">
<h2>{
{message}}</h2>
<!-- 在mustache语法中,不仅仅可以直接写变量,也可以写简单的表达式 -->
<h2>{
{firstName+" "+lastName}}</h2>
<h2>{
{firstName}} {
{lastName}}</h2>
<h2>{
{counter*2}}</h2>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
message: "你好啊",
firstName: 'Kobe',
lastName: 'bryant',
counter: 100
}
})
</script>
v-once不想要响应式
<div id="app">
<h2>{
{message}}</h2>
<!-- 加上once指令后,当我们在控制台修改app.message。 这个message不会修改 -->
<h2 v-once>{
{message}}</h2>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
message: "你好啊"
}
})
</script>
v-html 需要注意的是动态渲染的任意 HTML 可能会非常危险,因为它很容易导致 XSS 攻击。请只对可信内容使用 HTML 插值,绝不要对用户提供的内容使用插值。
<!-- v-html,表示以html的语法解析数据 -->
<h2 v-html="url"></h2>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
url: '<a href="http:www.baidu.com">百度一下</a>'
}
})
</script>
v-pre
<!-- v-pre的用法表示不要解析这个{
{}},页面显示{
{message}}-->
<h2 v-pre>{
{message}}</h2>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
message: "你好啊"
}
})
</script>
v-cloak(很少用)
<!-- 在vue解析之后,div没有一个属性v-cloak -->
<h2 v-cloak>{
{message}}</h2>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
message: "你好啊"
}
})
v-bind动态绑定
v-bind用于绑定一个或者多个属性值,或者向另一个组件传递props值,在开发中,图片的src链接,网站的链接href,动态绑定一些类和样式。比如通过vue实例中的data动态绑定元素的src和href如下:
<div id="app">
<!-- v-bind:的缩写是: -->
<!-- 也就是说v-bind的语法糖是 : -->
<img v-bind:src="imgUrl" alt="">
<a v-bind:href="url">百度一下</a>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
imgUrl: './img/1.jpeg',
url: 'http://www.baidu.com'
}
})
</script>
另外,v-bind还可以动态绑定class,意义在于在开发中,有时候我们需要加class,有时候我们不需要加class。
对象语法:
<!-- 对象语法 -->
<style>
.active {
color: red
}
</style>
<!-- <h2 :class="{key1:value1,key2:value2}">{
{message}}</h2> -->
<!-- <h2 :class="{类名1:true,类名2:false}">{
{message}}</h2> -->
<h2 :class="{active:isActive,line:isLine}">{
{message}}</h2>
<button @click="btnClick">我是按钮</button>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
active: 'active',
isActive: true,
isLine: true
},
methods: {
btnClick() {
this.isActive = !this.isActive
}
}
})
</script>
//也可以使用方法的形式,令该对象为方法getClasses
<h2 :class="getClasses()">{
{message}}</h2>
methods: {
btnClick() {
this.isActive = !this.isActive
},
getClasses() {
return {
active: this.isActive,
line: this.isLine
}
}
}
数组语法:
<div id="app">
<!-- 数组语法 -->
<h2 class="title" :class="getClasses()">{
{message}}</h2>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
active: 'aaa',
line: 'bbb'
},
methods: {
getClasses() {
return [this.active, this.line]
}
}
})
</script>
小案例:实现一个列表,初始情况下,第一个是红色,点击哪一个li,哪一个li就变为红色。
<style>
.active {
color: red
}
</style>
<div id="app">
<ul>
<li v-for="(item,index) in movies"
:class="{active:currentIndex === index}" @click="liClick(index)">{
{index}}=={
{item}}</li>
</ul>
</div>
<script>
const app = new Vue({
el: "#app",
data: {
movies: ['觉醒年代', '武林外传', '情深深', '你的荣耀'],
currentIndex: 0
},
methods: {
liClick(index) {
this.currentIndex = index
}
}
})
</script>
动态绑定属性
- 对象语法
<div id="app">
<!-- <h2 :style="{key(css属性名):value(属性值)}">{
{message}}</h2> -->
<!-- 需要注意的是font-size需要加单引号,color可加可不加 属性值必须加-->
<!-- <h2 :style="{'font-size':'50px',color:'red'}">{
{message}}</h2> -->
<h2 :style="{
'font-size':size+'px',color:col}">{
{message}}</h2>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好',
size: 100,
col: 'red'
}
})
</script>
- 数组语法 用的很少
<div id="app">
<h2 :style="[baseStyle]">{
{message}}</h2>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好',
baseStyle: {
backgroundColor: 'red'
}
}
})
</script>
计算属性的使用
我们知道,在模板中,可以直接通过插值语法显示一些data中的数据,但是在某些情况下,我们可以需要对数据进行一些转换后显示,或者需要将多个数据结合起来显示。比如:
- 我们有firstName和lastName两个变量,我们需要显示完整的名称
- 但是很多地方都需要完整的名称,我们就需要写多个{ {firstName}}{ {lastName}}
那么我们可以将代码转换为计算属性
<div id="app">
<h2>{
{firstName}} {
{lastName}}</h2>
<h2>{
{fullName}}</h2>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
firstName: 'Kobe',
lastName: 'bryant'
},
//计算属性
computed: {
fullName() {
return this.firstName + ' ' + this.lastName
}
}
})
</script>
计算属性复杂操作
<div id="app">
<!-- 输出总价格 -->
<h2>总价格:{
{totalPrice}}</h2>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
books: [{
id: 110,
name: 'Linux',
price: 119
}, {
id: 111,
name: 'web',
price: 109
}, {
id: 112,
name: '深入理解计算机原理',
price: 89
}]
},
//计算属性
computed: {
// filter/map/reduce
totalPrice() {
let result = 0
for (let i = 0; i < this.books.length; i++) {
result += this.books[i].price
}
return result
}
}
})
</script>
计算属性的getter和setter
//计算属性,属性没有set方法,是一个只读属性
computed: {
// fullName() {
// return this.firstName + ' ' + this.lastName
// }
//原本的写法应该是以下所示
fullName: {
set() {
},
get() {
return this.firstName + this.lastName
}
}
}
计算属性和methods的对比 (计算属性的性能更高)
<div id="app">
<!-- 计算属性和methods的区别 -->
<!-- 通过定义methods方法,会被调用了4次 -->
<h2>{
{getFullName()}}</h2>
<h2>{
{getFullName()}}</h2>
<h2>{
{getFullName()}}</h2>
<h2>{
{getFullName()}}</h2>
<!-- 通过computed 会被调用一次,所以computed性能更高-->
<h2>{
{fullName}}</h2>
<h2>{
{fullName}}</h2>
<h2>{
{fullName}}</h2>
<h2>{
{fullName}}</h2>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
firstName: 'Kobe',
lastName: 'Bryant'
},
//计算属性,属性没有set方法,是一个只读属性
//原本的写法应该是以下所示
computed: {
fullName() {
console.log('methods');
return this.firstName + ' ' + this.lastName
}
},
methods: {
getFullName() {
console.log('methods');
return this.firstName + ' ' + this.lastName
}
}
})
</script>
ES6的语法
let/const
事实上,var的设计可以看成是js语言设计上的错误,但这种错误多半不能修复和移除,以后需要向后兼容。我们可以把let当作更完美的var。
块级作用域
JS使用var来声明一个变量,变量的作用域主要是和函数的定义有关。针对其他块定义来说是没有作用域的,比如if/for等,这在我们开发中往往会引起一些问题。
//1、变量作用域,变量在什么范围内是可用
// var的块级作用域是全局,还有变量提升
{
var name = 'why'
console.log(name); //why
}
console.log(name); //why
{
let reason = "because"
console.log(reason); //because
}
console.log(reason); //reason is not defined
// var 的情况
console.log(foo); // 输出undefined
var foo = 2;
// let 的情况
console.log(bar); // 报错ReferenceError
let bar = 2;
上面代码中,变量foo
用var
命令声明,会发生变量提升,即脚本开始运行时,变量foo
已经存在了,但是没有值,所以会输出undefined
。变量bar
用let
命令声明,不会发生变量提升。这表示在声明它之前,变量bar
是不存在的,这时如果用到它,就会抛出一个错误。
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
上面代码中,存在全局变量tmp
,但是块级作用域内let
又声明了一个局部变量tmp
,导致后者绑定这个块级作用域,所以在let
声明变量前,对tmp
赋值会报错。
ES6 明确规定,如果区块中存在let
和const
命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
总之,在代码块内,使用let
命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。
const在开发中优先使用const,只有需要某一个标识符的时候才使用let。const定义常量,不能修改!
//注意1:一旦给const修饰的标识符被复制之后,不能修改
const a = 20
a = 30 //错误 Assignment to constant variable.
//注意2:在使用const定义标识符,必须进行赋值
const name
name = 'hahaha' // Missing initializer in const declaration
//注意3:常量的含义是指向的对象不能修改,但是可以改变对象内部的属性
const obj = {
name: 'why',
age: 19,
height: 188
}
console.log(obj); //{name: "why", age: 19, height: 188}
obj.name = 'koba'
console.log(obj); //{name: "koba", age: 19, height: 188}
对象字面量的增强写法
// 1. 属性的增强写法,当属性和值一样的时候,直接写属性名即可
const name = 'why'
const age = 18
const height = 1.88
const obj = {
name,
age,
height
}
console.log(obj);
//2. 函数的增强写法
// ES5语法
const obj = {
run: function() {
},
eat: function() {
}
}
// ES6语法 不需要写:function
const obj = {
run() {
},
eat() {
}
}
v-on事件监听
<div id="app">
<h2>{
{counter}}</h2>
<!-- <button v-on:click="counter++">加</button>
<button v-on:click="counter--">减</button> -->
<!-- v-on的语法糖叫做 @ -->
<button @click="increment">加</button>
<button @click="decrement">减</button>
</div>
<script>
const app = b = new Vue({
el: '#app',
data: {
counter: 0
},
methods: {
increment() {
this.counter++
},
decrement() {
this.counter--
}
}
})
</script>
当通过methods中定义方法,以供@click调用,需要注意参数问题:
-
如果该方法不需要额外参数,那么方法后面的()可以不添加。
但是注意,如果方法本身有一个参数,那么默将原生事件event参数传递进去
-
如果需要同时传入某个参数,同时需要event时,可以通过$event传入事件
<div id="app">
<!-- 1、事件调用的时候没有参数 -->
<button @click="btn1Click()">按钮1</button>
<button @click="btn1Click">按钮2</button>
<!-- 2、在事件定义时,写函数省略了小括号,但是方法本身时需要一个参数的 -->
<button @click="btn2Click(123)">按钮3</button>
<!-- 2.1、写了括号,没写参数。输出结果:undefined "-----" -->
<button @click="btn2Click()">按钮4</button>
<!-- 2.2、没写括号,输出结果:MouseEvent {isTrusted: true, screenX: 315, screenY: 159, clientX: 267, clientY: 23, …} -->
<button @click="btn2Click">按钮5</button>
<!-- 3、方法定义时,我们需要event对象,同时又需要其他参数 -->
<!-- 在调用方式,如何手动的获取到浏览器参数的event对象:$event -->
<button @click="btn3Click(123,$event)">按钮6</button>
</div>
<script>
const app = b = new Vue({
el: '#app',
data: {
counter: 0
},
methods: {
btn1Click() {
console.log('btn1');
},
btn2Click(a) {
console.log(a, '-----');
},
btn3Click(a, event)