1. Vue是渐进式框架,什么是渐进式呢?
打一个不恰当的比喻,买房时可以选择精装房,或者只买一个空房,里面没有任何装饰。后面可以自己一步一步装修,需要什么家具就买什么家具。使用Vue框架就如同买空房,以后遇到需要的某项功能时,只需要按照特定的插件就可以了,而不是刚使用时就必须安装全套插件。
2. Vue.js安装
方式一:直接CDN引入
(你可以选择引入开发环境版本还是生产环境版本)
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
方式二:下载和引入
下载地址:
开发环境 vuejs.org/js/vue.js
方式三:NPM安装
通过webpack和CLI的使用进行安装
3. Vue的初体验
展示单一数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!-- 执行到这里时,显然出对应的HTML -->
<h2>{{message}}</h2>
<h1>{{name}}</h1>
</div>
<div>{{message}}</div>
<!-- 引入vue.js -->
<script src="../js/vue.js"></script>
<script>
// let(变量)/const(常量)
// 编程范式: 声明式编程,比命令式编程更简单
//执行到这里,创建Vue实例,并且对原HTML进行解析和修改
const app = new Vue({
el: '#app', // 用于挂载要管理的元素
data: { // 定义数据
message: '你好啊,CodingKid!',
name: 'CodingKid'
}
})
// 元素js的做法(编程范式: 命令式编程)
// 1.创建div元素,设置id属性
// 2.定义一个变量叫message
// 3.将message变量放在前面的div元素中显示
// 4.修改message的数据: 今天天气不错!
// 5.将修改后的数据再次替换到div元素
</script>
</body>
</html>
展示列表(v-for)
- 利用
v-for
进行迭代
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<ul>
<li v-for="item in movies">{{item}}</li>
</ul>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
movies: ['星际穿越', '大话西游', '少年派', '盗梦空间']
}
})
</script>
</body>
</html>
-
取数组的索引值:
v-for=(item, index) in array
-
取对象的索引值和
key
、value
:v-for=(value, key, index) in obj
-
官方推荐我们在使用v-for时,给对应的元素或组件添加上一个:key属性
-
n为什么需要这个key属性呢(了解)?
-
这个其实和Vue的虚拟DOM的Diff算法有关系
-
这里我们借用React's diff algorithm中的一张图来简单说明一下(上层结点为虚拟dom中的结点,下层结点为实际dom中的结点)
-
当没有key时,虚拟dom结点按顺序与实际dom进行比对,看是否一致,不一致则对实际dom进行调整,由此当往中间插入(或改变)一个结点时,其后的结点都会改变
-
当有key时,虚拟dom结点按key值与实际dom进行配对,故插入新结点时,其他结点不需要改变,不过key值需要**唯一****
-
-
响应式
以上两种展示方式都是响应式的,当Vue实例中的data变化时,对应的dom中的内容也会随之改变
初探method(与v-on结合)
下面实现了一个简易计数器,v-on
是为了监听,监听什么事件呢?毫无疑问click
事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<h2>当前计数: {{counter}}</h2>
<!-- 下面的实现没有错误,但是监听事件后需要很多操作时,这样写就不方便了 -->
<!--<button v-on:click="counter++">+</button>-->
<!--<button v-on:click="counter--;">-</button>-->
<button v-on:click="add">+</button>
<button v-on:click="sub">-</button>
<!--下面是语法糖写法-->
<!--<button @click="sub">-</button>-->
</div>
<script src="../js/vue.js"></script>
<script>
// 语法糖: 简写
// proxy
const obj = {
counter: 0,
message: 'abc'
}
new Vue()
const app = new Vue({
el: '#app',
data: obj,
methods: {
add: function () {
console.log('add被执行');
this.counter++
},
sub: function () {
console.log('sub被执行');
this.counter--
}
}
})
</script>
</body>
</html>
4.Vue中的MVVM(Model-View-ViewModel)
什么是MVVM呢?
维基百科传送门MVVM
Vue的MVVM
View层(视图层)
- 在我们前端开发中,通常就是DOM层。
- 主要的作用是给用户展示各种信息。
Model层(数据层)
-
数据可能是我们固定的死数据,更多的是来自我们服务器,从网络上请求下来的数据。
-
在我们计数器的案例中,就是后面抽取出来的obj,当然,里面的数据可能没有这么简单。
-
VueModel层(视图模型层)
-
视图模型层
-
视图模型层是View和Model沟通的桥梁。
-
一方面它实现了Data Binding,也就是数据绑定,将Model的改变实时的反应到View中
-
另一方面它实现了DOM Listener,也就是DOM监听,当DOM发生一些事件(点击、滚动、touch等)时,可以监听到,并在需要的情况下改变对应的Data。
5.Vue实例中的Option
-
官方文档中的介绍,点这里
-
目前需要掌握的:
-
el:
- 类型:string | HTMLElement
- 作用:决定之后Vue实例会管理哪一个DOM
-
data:
- 类型:Object | Function (组件当中data必须是一个函数)
- 作用:Vue实例对应的数据对象。
-
methods:
- 类型:{ [key: string]: Function }
- 作用:定义属于Vue的一些方法,可以在其他地方调用,也可以在指令中使用。
-
6.Vue的生命周期
示意图
7.基础语法
插值操作
-
Mustache语法
-
v-once
- p该指令后面不需要跟任何表达式(比如之前的v-for后面是由跟表达式的)
- 该指令表示元素和组件(组件后面才会学习)只渲染一次,不会随着数据的改变而改变
-
v-html
- 某些情况下,我们从服务器请求到的数据本身就是一个HTML代码,p如果我们直接通过{{}}来输出,会将HTML代码也一起输出。但是我们可能希望的是按照HTML格式进行解析,并且显示对应的内容。
- 可以使用v-html指令
- 该指令后面往往会跟上一个string类型
- 会将string的html解析出来并且进行渲染 image-20200727194227961.png
-
v-text
- nv-text作用和Mustache一致
- nv-text通常情况下,接受一个string类型,可以是vue实例data中的变量,最后会在浏览器中渲染出来
-
v-pre
- v-pre用于跳过这个元素和它子元素的编译过程,用于显示原本
-
v-cloak
- 这个指令保持在元素上直到关联实例结束编译。
- 和 CSS 规则如
[v-cloak] { display: none }
一起用时,这个指令可以隐藏未编译的 Mustache 标签直到实例准备完毕。 - 防止HTML 绑定 Vue实例,在页面加载时闪烁(闪烁原因:在形成Vue实例时,Vue重新解析页面,导致之前加载的值发生变化,渲染的内容也改变了,所以会有闪烁的情况)
绑定属性
- v-bind
- v-bind用于绑定属性值,如图片的链接src、网站的链接href、动态绑定一些类、样式等等,也可以绑定value,也称为值绑定
- 向另一个组件传递props值(这个复习到组件时再介绍)
绑定class的两种方式
-
对象语法
-
用法一:直接通过{}绑定一个类
<h2 :class="{'active': isActive}">Hello World</h2>
-
用法二:也可以通过判断,传入多个值
<h2 :class="{'active': isActive, 'line': isLine}">Hello World</h2>
-
用法三:和普通的类同时存在,并不冲突
<!--如果isActive和isLine都为true,那么会有title/active/line三个类--> <h2 class="title" :class="{'active': isActive, 'line': isLine}">Hello World</h2>
-
-
数组语法
-
用法一:直接通过
[]
绑定一个类<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>
在写CSS属性名的时候,比如font-size
我们可以使用驼峰式 (camelCase) fontSize
p或短横线分隔 (kebab-case,记得用单引号括起来) ‘font-size’
绑定style的两种方式
-
对象语法
- style后面跟的是一个对象类型
-
对象的key是CSS属性名称
- 对象的value是具体赋的值,值可以来自于data中的属性
<div v-bind:style="{color: currentColor, fontSize: fontSize + 'px'}"></div>
-
数组语法
-
style后面跟的是一个数组类型,数组元素为对象类型
<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>
-
计算属性(computed)
-
每个计算属性都包含一个getter和一个setter
-
使用计算属性时,其后之所以不用加
()
是因为会自动调用get()
方法,返回相应的值 -
当给计算属性赋值时,会调用
set(value)
方法,并把赋予的值传递给value
-
由于计算属性常用来计算,所以
set()
方法不常用,故可使用简略写法,从而显得和methods中的方法很相似,但仍然是一个属性,不是方法,是一个只读属性
示例:
data: {
firstName: 'Kobe',
lastName: 'Bryant'
},
computed: {
// 常规写法 fullName只读
// fullName: function () {
// return this.firstName + ' ' + this.lastName
// }
// 完整写法 fullName可读,可写
fullName: {
set: function(newValue) { //当执行 fullName = 'Value' 时,会把Value传给newValue
console.log(newValue);
},
get: function () {
return this.firstName + ' ' + this.lastName
}
}
}
- 计算属性会进行缓存,如果多次使用时,计算属性只会调用一次,而多次使用methods中的方法时,会重复调用,当然当其中涉及到的数据发生改变时,计算属性也是响应式的,也就是
get()
函数可以监听函数体中变量的变化
事件监听
-
v-on
基础:在前面的小节中:初探method(与v-on结合) -
v-on
参数-
如果该方法不需要额外参数,那么方法后的()可以不添加
-
如果方法本身中有一个参数,那么会默认将原生事件event参数传递进去
-
如果需要同时传入某个参数,同时需要event时,可以通过$event传入事件
<div id="app"> <!--1.事件调用的方法没有参数--> <button @click="btn1Click()">按钮1</button> <button @click="btn1Click">按钮1</button> <!--2.在事件定义时, 写方法时省略了小括号, 但是方法本身是需要一个参数的, 这个时候, Vue会默认将浏览器生产的event事件对象作为参数传入到方法--> <!--<button @click="btn2Click(123)">按钮2</button>--> <!--<button @click="btn2Click()">按钮2</button>--> <button @click="btn2Click">按钮2</button> <!--3.方法定义时, 我们需要event对象, 同时又需要其他参数--> <!-- 在调用方式, 如何手动的获取到浏览器参数的event对象: $event--> <button @click="btn3Click(abc, $event)">按钮3</button> </div> <script src="../js/vue.js"></script> <script> const app = new Vue({ el: '#app', data: { message: '你好啊', abc: 123 }, methods: { btn1Click() { console.log("btn1Click"); }, btn2Click(event) { console.log('--------', event); }, btn3Click(abc, event) { console.log('++++++++', abc, event); } } }) // 如果函数需要参数,但是没有传入, 那么函数的形参为undefined // function abc(name) { // console.log(name); // } // // abc() //而在v-on中如果方法本身中有一个参数,那么会默认将原生事件event参数传递进去 </script>
-
-
v-on
修饰符-
.stop -调用event.stopPropagation(), 阻止事件冒泡
-
.prevent - 调用 event.preventDefault(),阻止默认事件
-
.{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调
-
.native - 监听组件根元素的原生事件
-
.once - 只触发一次回调
<div id="app"> <!--1. .stop修饰符的使用,点击button,防止冒泡到div--> <div @click="divClick"> <button @click.stop="btnClick">按钮</button> </div> <!--2. .prevent修饰符的使用,阻止提交按钮的默认事件--> <br> <form action="baidu"> <input type="submit" value="提交" @click.prevent="submitClick"> </form> <!--3. .KeyAlias修饰符的使用,监听某个键盘的键帽,此时监听回车键--> <input type="text" @keyup.enter="keyUp"> <!-- 4. .native-修饰符的使用 假如cpn标签是一个组件,则必须加上.native才能触发事件--> <cpn @click.native="btn2Click"></cpn> <!--5. .once修饰符的使用,只有第一次点击button的时候有用--> <button @click.once="btn3Click">按钮2</button> </div>
-
条件指令
nv-if
、v-else-if
、v-else
的使用
-
Vue的条件指令可以根据表达式的值在DOM中渲染或销毁元素或组件
-
v-if后面的条件为false时,对应的元素以及其子元素不会渲染
-
也就是根本没有不会有对应的标签出现在DOM中
<!-- 用法和普通语言的if...else if... else相似,如当成绩为99时,显示优秀 --> <div id="app"> <h2 v-if="score>=90">优秀</h2> <h2 v-else-if="score>=80">良好</h2> <h2 v-else-if="score>=60">及格</h2> <h2 v-else>不及格</h2> </div>
-
案例
<div id="app"> <!-- v-if --> <span v-if="isUser"> <label for="username">用户账号</label> <input type="text" id="username" placeholder="用户账号" key="username"> </span> <!-- v-else --> <span v-else> <label for="email">用户邮箱</label> <input type="text" id="email" placeholder="用户邮箱" key="email"> </span> <button @click="isUser = !isUser">切换类型</button> </div> <script src="../js/vue.js"></script> <script> const app = new Vue({ el: '#app', data: { isUser: true } }) </script>
- 在
input
没加key
属性之前,会出现一个小问题- 切换了类型,我们会发现文字依然显示之前的输入的内容
- 但是按道理讲,我们应该切换到另外一个input元素中了
- 在另一个input元素中,我们并没有输入内容
- 问题解答
- 这是因为Vue在进行DOM渲染时,出于性能考虑,会尽可能的复用已经存在的元素,而不是重新创建新的元素,否则dom树会改变,消耗性能
- 在上面的案例中,Vue内部会发现原来的input元素不再使用,直接作为else中的input来使用了
- 解决方案
- p如果我们不希望Vue出现类似重复利用的问题,可以给对应的input添加key,表示需要创建一个新的标签
- p并且我们需要保证key的不同
- 在
-
与
v-show
的对比- v-if当条件为false时,压根不会有对应的元素在DOM中
- v-show当条件为false时,仅仅是将元素的display属性设置为none而已
- 当需要在显示与隐藏之间切片很频繁时,使用v-show(出于性能的考虑,否则dom树会频繁改变)
- 当只有一次切换时,通过使用v-if
表单绑定:v-model的使用
Vue中使用v-model指令来实现表单元素和数据的双向绑定
<div id="app">
<input type="text" v-model="message">
<h2>{{message}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'CodingKid'
}
})
</script>
当表单中输入值时,v-model会实时监听,并将message修改成和表单对应的值,因此h2标签显示的内容和表单中的内容一致,因此当页面的内容改变时会影响模型中的data数据,data数据的改变也会显示在页面,故实现了双向绑定。
-
原理(通过
v-bind
和v-on
来理解)<div id="app"> <input type="text" :value="message" @input="message = $event.target.value"> <h2>{{message}}</h2> </div> <script src="../js/vue.js"></script> <script> const app = new Vue({ el: '#app', data: { message: 'CodingKid' } }) </script>
-
v-model
与radio
类型结合首先说一下radio的默认特性,当多个radio都有name属性,且一样时,为单选框,也就是只可选中其中一个,当name属性的值一致或者没有name属性时,每个radio都是独立的,也就是可以同时选中
-
使用v-model会改变radio的特性,只要v-model指定了相同的变量时,radio不管有没有name属性,或者name的值是否一样,每个radio都是想关联的,也会是只能选中其中一个,radio主要的作用也是如此
<div id="app"> <!-- 即使没有name属性,这两个radio也是相关联的,只能选中其中一个 --> <label for="male"> <input type="radio" id="male" value="男" v-model="sex">男 </label> <label for="female"> <input type="radio" id="female" value="女" v-model="sex">女 </label> <h2>您选择的性别是: {{sex}}</h2> </div> <script src="../js/vue.js"></script> <script> const app = new Vue({ el: '#app', data: { message: '你好啊', sex: '女' } }) </script>
-
-
v-model
与checkbox
类型结合checkbox作用就是多选,名字也叫做复选框,不过当只有一个 复选框时,也能当单选框使用,但不能像radio一样,有多个复选框时,能实现只选中一个并取消其他选中的功能
-
当多个checkbox的v-model绑定一个变量时,当该变量是数组类型,则选中一个复选框,就会把一个复选框的value加入数组
-
注意:当v-model类型绑定的不是数组时,v-model会强行将变量类型改成布尔类型,也就是只有true和false,因为全部的checkbox全部都绑定了这个变量,于是当一个checkbox选中时,变量的值为true,所有的checkbox全会变成选中状态,同理,当取消如何一个checkbox的选中状态时,全部的checkbox全会取消选中状态(此时checkbox中的value值不起作用)
-
由上面两点知,v-model所绑定变量的类型会影响其所实现的功能
<div id="app"> <!-- 1.checkbox单选框--> <label > <input type="checkbox" v-model="isAgree" >同意协议 </label> <h2>您选择的是: {{isAgree}}</h2> <!-- 2.checkbox多选框 --> <input type="checkbox" value="篮球" v-model="hobbies">篮球 <input type="checkbox" value="足球" v-model="hobbies">足球 <input type="checkbox" value="乒乓球" v-model="hobbies">乒乓球 <input type="checkbox" value="羽毛球" v-model="hobbies">羽毛球 <h2>您的爱好是: {{hobbies}}</h2> </div> <script src="../js/vue.js"></script> <script> const app = new Vue({ el: '#app', data: { message: '你好啊', isAgree: false, // 单选框 只要数据类型不是数组,就会变成boolean类型 hobbies: [] // 多选框,必须是数组类型,否则会变成boolean类型,导致checkbox中的value不起作用 } }) </script>
-
-
v-model
与select
类型结合-
select与checkbox比较类似,但v-model所绑定的类型不会影响多选的功能实现,当其不为数组时,会强制转换成数组,因为select中有multiple属性决定了其必须为多选
<div id="app"> <!--1.选择一个--> <select name="abc" v-model="fruit"> <option value="苹果">苹果</option> <option value="香蕉">香蕉</option> <option value="榴莲">榴莲</option> <option value="葡萄">葡萄</option> </select> <h2>您选择的水果是: {{fruit}}</h2> <!--2.选择多个--> <select name="abc" v-model="fruits" multiple> <option value="苹果">苹果</option> <option value="香蕉">香蕉</option> <option value="榴莲">榴莲</option> <option value="葡萄">葡萄</option> </select> <h2>您选择的水果是: {{fruits}}</h2> </div> <script src="../js/vue.js"></script> <script> const app = new Vue({ el: '#app', data: { message: '你好啊', fruit: '香蕉', fruits: [] //不为数组时,会强行转换成数组 } }) </script>
-
-
v-model
的修饰符-
lazy修饰符
- 默认情况下,v-model默认是在input事件中同步输入框的数据的
- 也就是说,一旦有数据发生改变对应的data中的数据就会自动发生改变
- lazy修饰符可以让数据在失去焦点或者回车时才会更新
-
number修饰符
- 默认情况下,在输入框中无论我们输入的是字母还是数字,都会被当做字符串类型进行处理
- 但是如果我们希望处理的是数字类型,那么最好直接将内容当做数字处理
- number修饰符可以让在输入框中输入的内容自动转成数字类型
-
trim修饰符
-
如果输入的内容首尾有很多空格,通常我们希望将其去除
-
ptrim修饰符可以过滤内容左右两边的空格
-
<div id="app"> <!--1.修饰符: lazy--> <input type="text" v-model.lazy="message"> <h2>{{message}}</h2> <!--2.修饰符: number--> <input type="number" v-model.number="age"> <h2>{{age}}-{{typeof age}}</h2> <!--3.修饰符: trim--> <input type="text" v-model.trim="name"> <h2>您输入的名字:{{name}}</h2> </div> <script src="../js/vue.js"></script> <script> const app = new Vue({ el: '#app', data: { message: 'Ki', age: 0, name: '' } }) </script>
写在最后
- 码字不易,点赞鼓励
- 此文为本人学习Vue的总结,适合有一定vue基础的人阅读
- 希望广大读者斧正
- 之后会继续更新的,有兴趣的来波关注吧!
-