个人微信公众号:程序猿的月光宝盒
最近项目上需要用到Vue,又重新学习了一遍.期望10天左右完全掌握并能用于生产吧.
好记性不如烂笔头
一. 邂逅Vuejs
1.1. 认识Vuejs
-
为什么学习Vuejs
- 可能你的公司正要将原有的项目使用Vue进行重构。
- 可能是你的公司新项目决定使用Vue的技术栈。
- 如果你现在正在换工作,你会发现招聘前端或者后端的需求中,10个有8个都对Vue有或多或少的要求。
- 作为终生学习者我们知道Vuejs目前非常火,可以说是前端必备的一个技能。
-
Vue的读音
- (读音
/vjuː/
,类似于 view)
- (读音
-
Vue的渐进式
-
渐进式
渐进式意味着你可以将Vue作为你应用的一部分嵌入其中,带来更丰富的交互体验。
或者如果你希望将更多的业务逻辑使用Vue实现,那么将会用到Vue的核心库以及其生态系统。
比如
Core+Vue-router+Vuex
,也可以满足你各种各样的需求。
-
-
Vue的特点
- 解耦视图和数据
- 可复用的组件
- 前端路由技术
- 状态管理
- 虚拟DOM
1.2. 安装Vue
-
CDN引入
-
你可以选择引入开发环境版本还是生产环境版本
<!-- 开发环境版本,包含了有帮助的命令行警告 --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <!-- 生产环境版本,优化了尺寸和速度 --> <script src="https://cdn.jsdelivr.net/npm/vue"></script>
-
-
下载引入
开发环境 https://vuejs.org/js/vue.js 生产环境 https://vuejs.org/js/vue.min.js
-
npm安装
- 后续通过
webpack
和CLI
的使用,项目上大多数用到
- 后续通过
1.3. Vue的初体验
-
Hello Vuejs
-
mustache 语法-> 体验vue响应式
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Vue初体験</title> <script src="../js/vue.js"></script> </head> <body> <div id="vm"> <span>{{message}}</span> </div> </body> <script> /* * let(变量)/const(常量) * 此编程范式为: * 声明式编程 * * 传统js做法 * 元素js的做法(编程范式: 命令式编程) * 1.创建div元素,设置id属性 * * 2.定义一个变量叫message * * 3.将message变量放在前面的div元素中显示 * * 4.修改message的数据: 今天天气不错! * * 5.将修改后的数据再次替换到div元素 * 是一步一步做的,故编程范式为: * 命令式编程 * */ const vm = new Vue({ el: "#vm",//用户挂载要管理的id为vm的元素 data: {//定义数据 message: "初めまして、Vue さん。僕は金聖聰と申します" } }) </script> </html>
以上代码做了那些事?
- JavaScript代码中,创建了一个Vue对象。
- 创建Vue对象的时候,传入了一些options:{}
- {}中包含了el属性:该属性决定了这个Vue对象挂载到哪一个元素上,很明显,我们这里是挂载到了id为app的元素上
- {}中包含了data属性:该属性中通常会存储一些数据
- data中的数据可以是我们直接定义出来的,比如像上面这样。也可能是来自网络,从服务器加载的。
浏览器执行代码的流程:
- 执行到9~11行代码显然出对应的HTML
- 执行第33行代码创建Vue实例,并且对原HTML进行解析和修改。并且,目前的代码是可以做到响应式的。
-
-
Vue列表展示
-
v-for
-
后面给数组追加元素的时候, 新的元素也可以在界面中渲染出来
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>列表展示</title> <script src="../js/vue.js"></script> </head> <body> <div id="vm"> <ul> <li v-for="item in movieList">{{item}}</li> </ul> </div> </body> <script> const vm = new Vue({ el: "#vm", data: { movieList: ["大话西游", "情癫大圣", "大圣娶亲"] } }) </script> </html>
代码做了那些事?
- HTML代码中,使用v-for指令,该指令后面会详细讲解,这里先学会使用。
- 再也不需要在JavaScript代码中完成DOM的拼接相关操作了,更重要的是,它还是响应式的。
-
-
Vue计数器小案例
-
事件监听: click -> methods
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>计数器</title> <script src="../js/vue.js"></script> </head> <body> <div id="vm"> <h2>当前计数{{count}}</h2> <!--@click是v-on:click的语法糖--> <button @click="add">+</button> <button @click="sub">-</button> </div> </body> <script> const vm = new Vue({ el: '#vm',//接管对应区域的管理 data: { count: 0 }, methods: {//在vue对象中定义方法 add: function () { this.count++; }, sub: function () { this.count--; } } }) </script> </html>
新的指令和属性
新的属性:``methods``,该属性用于在Vue对象中定义方法。 新的指令:``@click``, 该指令用于监听某个元素的点击事件,并且需要指定当发生点击时,执行的方法(方法通常是methods中定义的方法)
-
1.4. Vue中的MVVM
View层
:
视图层
在前端开发中,通常就是DOM层。
主要的作用: 给用户展示各种信息。
Model层
:
数据层
数据可能是我们固定的死数据,更多的是来自我们服务器,从网络上请求下来的数据。
在计数器的案例中,就是后面抽取出来的obj,当然,里面的数据可能没有这么简单。
ViewModel层
:
视图模型层
视图模型层是View和Model沟通的桥梁。
一方面它实现了Data Binding,也就是数据绑定,将Model的改变实时的反应到View中
另一方面它实现了DOM Listener,也就是DOM监听,当DOM发生一些事件(点击、滚动、touch等)时,可以监听到,并在需要的情况下改变对应的Data。
1.4.5 计数器的MVVM
上面的计数器中就有严格的MVVM思想
View
依然是DOM
Model
就是抽离出来的obj
ViewModel
就是创建的Vue对象实例
它们之间如何工作呢?
首先ViewModel通过Data Binding让obj中的数据实时的在DOM中显示。
其次ViewModel通过DOM Listener来监听DOM事件,并且通过methods中的操作,来改变obj中的数据。
1.5. 创建Vue时, options可以放那些东西
- el:
- 类型:string | HTMLElement
- 作用:决定之后Vue实例会管理哪一个DOM。
- data:
- 类型:Object | Function (组件当中data必须是一个函数)
- 作用:Vue实例对应的数据对象。
- methods:
- 类型:{ [key: string]: Function }
- 作用:定义属于Vue的一些方法,可以在其他地方调用,也可以在指令中使用。
- 生命周期函数
二.插值语法
-
mustache语法
-
可以通过Mustache语法(也就是双大括号)。
-
Mustache: 胡子/胡须.
-
-
v-once
-
该指令后面不需要跟任何表达式(比如之前的v-for后面是由跟表达式的)
-
该指令表示元素和组件(组件后面才会学习)只渲染一次,不会随着数据的改变而改变。
-
-
v-html
-
某些情况下,我们从服务器请求到的数据本身就是一个HTML代码
-
如果我们直接通过{{}}来输出,会将HTML代码也一起输出。
-
但是我们可能希望的是按照HTML格式进行解析,并且显示对应的内容。
Ø该指令后面往往会跟上一个string类型
Ø会将string的html解析出来并且进行渲染
-
-
v-text
-
和Mustache比较相似:都是用于将数据显示在界面中
-
v-text通常情况下,接受一个string类型
-
-
v-pre:
-
跳过这个元素和它子元素的编译过程,用于显示原本的Mustache语法。
-
第一个p元素中的内容会被编译解析出来对应的内容
第二个p元素中会直接显示{{message}}
-
-
v-cloak: 斗篷
-
在某些情况下,比如网络原因,浏览器可能会直接显然出未编译的Mustache标签。这时候就用他来影藏.但是一般后面也不这么用
-
三. v-bind
作用:动态绑定属性
缩写(语法糖)::
预期:any (with argument) | Object (without argument)
参数:attrOrProp (optional)
3.1. v-bind绑定基本属性
-
v-bind:src
-
:href
3.2. v-bind动态绑定class
-
对象语法:
-
对象语法的含义是:class后面跟的是一个对象。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .active { color: red; } </style> </head> <body> <div id="app"> <!--<h2 class="active">{{message}}</h2>--> <!--<h2 :class="active">{{message}}</h2>--> <!--<h2 v-bind:class="{key1: value1, key2: value2}">{{message}}</h2>--> <!--<h2 v-bind:class="{类名1: true, 类名2: boolean}">{{message}}</h2>--> <h2 class="title" v-bind:class="{active: isActive, line: isLine}">{{message}}</h2> <h2 class="title" v-bind:class="getClasses()">{{message}}</h2> <button v-on:click="btnClick">你倒是变啊</button> </div> <script src="../js/vue.js"></script> <script> const app = new Vue({ el: '#app', data: { message: '我变', isActive: true, isLine: true }, methods: { btnClick: function () { this.isActive = !this.isActive }, getClasses: function () { return {active: this.isActive, line: this.isLine} } } }) </script> </body> </html>
-
-
数组语法:
用法一:直接通过[]绑定一个类 <h2 :class="['active']">Hello World</h2> 用法二:也可以传入多个值 <h2 :class=“[‘active’, 'line']">Hello World</h2> 用法三:和普通的类同时存在,并不冲突 注:会有title/active/line三个类 <h2 class="title" :class=“[‘active’, 'line']">Hello World</h2> 用法四:如果过于复杂,可以放在一个methods或者computed中 注:classes是一个计算属性 <h2 class="title" :class="classes">Hello World</h2>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <h2 class="title" :class="[active, line]">{{message}}</h2> <h2 class="title" :class="getClasses()">{{message}}</h2> </div> <script src="../js/vue.js"></script> <script> const app = new Vue({ el: '#app', data: { message: '你好', active: 'aaa', line: 'bbb' }, methods: { getClasses: function () { return [this.active, this.line] } } }) </script> </body> </html>
3.3. v-bind动态绑定style
绑定一些CSS内联样式。
在写CSS属性名的时候,比如font-size
可以使用驼峰式 (camelCase) fontSize
或短横线分隔 (kebab-case,记得用单引号括起来) ‘font-size’
-
对象语法:
:style="{color: currentColor, fontSize: fontSize + 'px'}" style后面跟的是一个对象类型 对象的key是CSS属性名称 对象的value是具体赋的值,值可以来自于data中的属性
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .title { font-size: 50px; color: red; } </style> </head> <body> <div id="app"> <!--<h2 :style="{key(属性名): value(属性值)}">{{message}}</h2>--> <!--'50px'必须加上单引号, 否则是当做一个变量去解析--> <!--<h2 :style="{fontSize: '50px'}">{{message}}</h2>--> <!--finalSize当成一个变量使用--> <!--<h2 :style="{fontSize: finalSize}">{{message}}</h2>--> <h2 :style="{fontSize: finalSize + 'px', backgroundColor: finalColor}">{{message}}</h2> <h2 :style="getStyles()">{{message}}</h2> </div> <script src="../js/vue.js"></script> <script> const app = new Vue({ el: '#app', data: { message: '你好啊', finalSize: 100, finalColor: 'red', }, methods: { getStyles: function () { return {fontSize: this.finalSize + 'px', backgroundColor: this.finalColor} } } }) </script> </body> </html>
-
数组语法:
<div v-bind:style="[baseStyles, overridingStyles]"></div> style后面跟的是一个数组类型 多个值以 , 分割即可
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<h2 :style="[baseStyle, baseStyle1]">{{message}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
baseStyle: {backgroundColor: 'red'},
baseStyle1: {fontSize: '100px'},
}
})
</script>
</body>
</html>
四. 计算属性
什么是计算属性
在模板中可以直接通过插值语法显示一些data中的数据。
但是在某些情况,我们可能需要对数据进行一些转化后再显示,或者需要将多个数据结合起来进行显示
比如我们有firstName和lastName两个变量,我们需要显示完整的名称。
但是如果多个地方都需要显示完整的名称,我们就需要写多个{{firstName}} {{lastName}}
故,我们可以将上面的代码换成计算属性:
然后,我们发现计算属性是写在实例的computed选项中的。
-
案例一: firstName+lastName
-
案例二: books -> price
这个是更加复杂的操作
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <h2>总价格: {{totalPrice}}</h2> </div> <script src="../js/vue.js"></script> <script> const app = new Vue({ el: '#app', data: { books: [ {id: 110, name: 'Java从入门到入坟', price: 119}, {id: 111, name: 'Oracle从入库到删库', price: 105}, {id: 112, name: 'Mysql从入门到跑路', price: 98}, {id: 113, name: 'Python从摸蛇到摸鱼', price: 87}, ] }, computed: { totalPrice: function () { let result = 0; //方式1 // for (let i=0; i < this.books.length; i++) { // result += this.books[i].price // } //方式2 // for (let i in this.books) { // result += this.books[i].price // } //方式3 for (let book of this.books) { result += book.price } return result; } } }) </script> </body> </html>
五. 练习
需求:一个列表 默认第一行红色,之后点某行某行变红
用到v-for="(m,index) in movieList"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>鼠标点击变色</title>
<style>
.Red {
color: red;
}
</style>
</head>
<body>
<div id="vm">
<ul>
<li v-for="(m,index) in movieList" @click="changeColor(index)"
:class="{Red: index === currentIndex}">
{{m}}
</li>
</ul>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
const vm = new Vue({
el:"#vm",
data:{
movieList:["西游记","东成西就","大圣娶亲","大话西游"],
// 初始化0,表示默认选中第一个li
currentIndex: 0
},
methods:{
// 传的index 就是当前的li的index
changeColor(index) {
//改变 currentIndex 为 传入的值
this.currentIndex =index
}
}
})
</script>
</html>