Vue系列教程(一)之初识Vue
一、Vue和MVVM
Vue是一个渐进式的js框架,只注重视图层,结合了HTML+CSS+JS,非常的易用,并且有很好的生态系统,而且vue体积很小,速度很快,优化很到位。
Vue技术周四MVVM开发模式的实现者
MVC
M model V view C controller
MVVM
M model V view VM viewmodel 连接视图和数据的中间件
Model:模型层,在这里表示 JavaScript 对象
View:视图层,在这里表示 DOM(HTML 操作的元素)
ViewModel:连接视图和数据的中间件,Vue.js 就是 MVVM 中的 ViewModel 层的实现者
在 MVVM 架构中,是不允许 数据 和 视图 直接通信的,只能通过 ViewModel 来通信,而 ViewModel 就是定义了 一个 Observer 观察者 ViewModel 能够观察到数据的变化,并对视图对应的内容进行更新 ViewModel 能够监听到视图的变化,并能够通知数据发生改变 至此,我们就明白了,Vue.js 就是一个 MVVM 的实现者,他的核心就是实现了 DOM 监听 与 数据绑定
1. CDN内容分发
CDN是这是一种加速策略,能够从离自己最近的服务器上快速的获得外部的资源。
2. VM的实现原理
View-model中内置了一个观察者,这个观察者观察两个维度
1)观察视图的变化,当视图变化了,就通知数据进行变化
2)观察数据的变化:当数据变了,就通知视图进行变化
——MVVM通过VM实现了双向数据绑定
3. 为什么使用vue.js
- 轻量级,体积小是一个重要指标。Vue.js 压缩后有只有 20多kb (Angular 压缩后 56kb+,React 压缩后 44kb+)
- 移动优先。更适合移动端,比如移动端的 Touch 事件
- 易上手,学习曲线平稳,文档齐全
- 吸取了 Angular( 模块化 )和 React( 虚拟 DOM )的长处,并拥有自己独特的功能,如: 计算属性
- 开源,社区活跃度高
4. vue两大核心要素
- 数据驱动
当你把一个普通的 JavaScript 对象传给 Vue 实例的 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter 。Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是为什么 Vue 不支持 IE8 以及更低版本浏览器。 这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。 这里需要注意的问题是浏览器控制台在打印数据对象时 getter/setter 的格式化并不同,所以你可能需要安装 vuedevtools 来获取更加友好的检查接口。 每个组件实例都有相应的 watcher 实例对象,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会通知 watcher 重新计算,从而致使它关联的组件得以更新。
- 组件化
页面上每个独立的可交互的区域视为一个组件 每个组件对应一个工程目录,组件所需的各种资源在这个目录下就近维护 页面不过是组件的容器,组件可以嵌套自由组合(复用)形成完整的页面。
二、Vue快速开始
1. 如何获得Vue的cdn文件(引入Vue)
官网:https://cn.vuejs.org/v2/guide/
<!-- 开发环境版本,包含了有帮助的命令行警告 --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
或者:
<!-- 生产环境版本,优化了尺寸和速度 --> <script src="https://cdn.jsdelivr.net/npm/vue"></script>
2. 在页面中使用Vue
两个部分:1)html: <div id=”app”></div>
2)需要有一个vue对象(实例)
<div id="app"> 请输入您的专业:<input type="text" @input="changeMajor"/> <br>================<br> 我是一名{{major}}专业的程序员 </div> <script src="https://cdn.bootcss.com/vue/2.6.11/vue.js"></script> <script> new Vue({ el: "#app", data: { major: "Python", }, methods:{ changeMajor:function (event) { // console.log(event.target.value); this.major = event.target.value; } } }) </script>
3.Vue对象里有哪些东西,分别有什么用?
New Vue({ el:”该vue对象绑定在哪个div上 data:{} 提供数据的,体面存放键值对 methods:{} // 方法定义 })
4. 在html的被vue绑定的元素中,通过插值表达式来获取vue对象中的数据。
<body> <div id="app"> 欢迎您!您的姓名是{{name}}年龄是{{age}} </div> <script src="https://cdn.bootcss.com/vue/2.6.11/vue.js"></script> <script> var app = new Vue({ el: "#app", data: { name: "张亚飞", age: 23, } }) </script>
三、插值表达式
插值表达式是用在html中被绑定的元素中的,目的是通过差值表达式获取vue对象中的属性和方法。
语法格式:{{vue的内容}},注意,差值表达式不能写在html的标签中,不能作为属性的值的部分
- 文本
数据绑定最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值:
<span>Message: {{ msg }}</span>
Mustache 标签将会被替代为对应数据对象上 msg
property 的值。无论何时,绑定的数据对象上 msg
property 发生了改变,插值处的内容都会更新。
通过使用 v-once 指令,你也能执行一次性地插值,当数据改变时,插值处的内容不会更新。但请留心这会影响到该节点上的其它数据绑定:
<span v-once>这个将不会改变: {{ msg }}</span>
- Html
双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用 v-html
指令:
<p>Using mustaches: {{ rawHtml }}</p> <p>Using v-html directive: <span v-html="rawHtml"></span></p>
Using mustaches: <span style="color: red">This should be red.</span>
Using v-html directive: This should be red.
这个 span
的内容将会被替换成为 property 值 rawHtml
,直接作为 HTML——会忽略解析 property 值中的数据绑定。注意,你不能使用 v-html
来复合局部模板,因为 Vue 不是基于字符串的模板引擎。反之,对于用户界面 (UI),组件更适合作为可重用和可组合的基本单位。
Mustache 语法不能作用在 HTML attribute 上,遇到这种情况应该使用 v-bind
指令:
<div v-bind:id="dynamicId"></div>
对于布尔 attribute (它们只要存在就意味着值为 true
),v-bind
工作起来略有不同,在这个例子中:
<button v-bind:disabled="isButtonDisabled">Button</button>
如果 isButtonDisabled
的值是 null
、undefined
或 false
,则 disabled
attribute 甚至不会被包含在渲染出来的 <button>
元素中。
Vue对象中的属性时哪里提供? new Vue({ data:{} <=这个data就提供了属性 }) Vue对象中方法是哪里提供? new Vue({ Methods:{ sayHello:function(){ alert(“hello vue”); } } }) 除此之外,差值表达式还能这么使用:、 <body> <div id="app"> 我是一名{{major}}专业的程序员 {{[0,1,2,3,4][1]}} {{{name: "科比", age: 40}.name}} </div>
四、Vue中的关键字
1. v-mode
是将标签的value值与vue实例中的data属性值进行绑定
<div id="app"> 请输入您的专业:<input type="text" v-model="major"/> <br>================<br> 我是一名{{major}}专业的程序员 </div> <script src="https://cdn.bootcss.com/vue/2.6.11/vue.js"></script> <script> new Vue({ el: "#app", data: { major: "Python", }, methods:{} }) </script>
2.v-on
通过配合具体的事件名,来绑定vue中定义的函数
<div id="app"> <input type="text" v-on:click="changeMajor" /> </div> <script src="https://cdn.bootcss.com/vue/2.6.11/vue.js"></script> <script> new Vue({ el: "#app", data: { major: "Python", }, methods:{ changeMajor:function () { console.log("change title"); } } })
补充知识:
(1)event.target.value:比如在响应函数里,可以指明使用event内置的参数对象,该对象表示当前事件,可以通过event.target.value来获得当前事件对象的value值。
(2)this的用法
this表示当前vue对象 “new Vue()”,可以通过“this.”来调用当前vue对象的属性和方法。
(3)v-on还可以简写
v-on:input=”” ==> @input=””
3.v-bind
差值表达式是不能写在html的标签的属性内的,如果一定要用vue中的属性作为html标签的属性的内容,既可以通过v-bind进行属性绑定。
<div id="app"> {{link}} <a v-bind:href="link">我的博客</a> </div> <script src="https://cdn.bootcss.com/vue/2.6.11/vue.js"></script> <script> new Vue({ el: "#app", data: { link: "https://www.cnblogs.com/zhangyafei", }, }) </script> 注意:v-bind也可以简写为: <a v-bind:href="link"> ==> <a :href=”link”>
4.v-once
此时该标签中的差值表达式,只获取一次数据,之后数据的变化不影响差值表达式的值。
5.v-html/v-text
v-html会将vue中的属性的值作为html的元素来使用
v-text会将vue中的属性的值只作为纯文本来使用
<div id="app"> <span v-html="mylink"></span> <span v-text="mylink"></span> </div> <script src="https://cdn.bootcss.com/vue/2.6.11/vue.js"></script> <script> new Vue({ el: "#app", data: { mylink: "<a href='https://www.cnblogs.com/zhangyafei'>我的博客</a>", }, }) </script>
五、Vue事件
1. Vue中如何使用事件
<div id="app"> 请输入您的专业:<input type="text" @input="changeMajor"/> <br>================<br> 我是一名{{major}}专业的程序员 </div> <script src="https://cdn.bootcss.com/vue/2.6.11/vue.js"></script> <script> new Vue({ el: "#app", data: { major: "Python", }, methods:{ changeMajor:function (event) { // console.log(event.target.value); this.major = event.target.value; } } })
2. 事件的参数传递
<button type="button" v-on:click="increase(2)">click</button> methods:{ increase:function(step){ this.counter+=step; },
设参:<button type="button" @click="add_count(2)">增加</button>
传参:add_count:function (step)
接参:this.count += step;
3. vue中的事件修饰符
在事件处理程序中调用 event.preventDefault() 或 event.stopPropagation() 是非常常见的需求。尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。
为了解决这个问题,Vue.js 为 v-on 提供了事件修饰符。之前提过,修饰符是由点开头的指令后缀来表示的
@click.stop 阻止点击事件的传播 @mousemove.stop 阻止鼠标移动事件 @keyup.enter 回车键按起时 @keyup.space 空格键按起时 <!-- 阻止单击事件继续传播 --> <a v-on:click.stop="doThis"></a> <!-- 提交事件不再重载页面 --> <form v-on:submit.prevent="onSubmit"></form> <!-- 修饰符可以串联 --> <a v-on:click.stop.prevent="doThat"></a> <!-- 只有修饰符 --> <form v-on:submit.prevent></form> <!-- 添加事件监听器时使用事件捕获模式 --> <!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 --> <div v-on:click.capture="doThis">...</div> <!-- 只当在 event.target 是当前元素自身时触发处理函数 --> <!-- 即事件不是从内部元素触发的 --> <div v-on:click.self="doThat">...</div>
4. 计算属性
将常用的函数缓存起来,在调用的时候直接使用缓存中的过程(结果),以此来提高效率。
注意:computed里虽然放的是函数,但在调用时,computed里的东西是一个属性,所以我们在调用时不能使用(),因为()是调用函数,而不是在调用属性。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>布局篇 计算属性</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script> </head> <body> <div id="vue"> <p>调用当前时间的方法:{{currentTime1()}}</p> <p>当前时间的计算属性:{{currentTime2}}</p> </div> <script type="text/javascript"> var vm = new Vue({ el: '#vue', data: { message: 'Hello Vue' }, methods: { currentTime1: function () { return Date.now(); } }, computed: {
currentTime2: function () { this.message; return Date.now(); } } });
说明 methods :定义方法,调用方法使用 currentTime1() ,需要带括号 computed :定义计算属性,调用属性使用 currentTime2 ,不需要带括号; this.message 是为了能够让 currentTime2 观察到数据变化而变化 注意: methods 和 computed 里不能重名
调用方法时,每次都需要进行计算,既然有计算过程则必定产生系统开销,那如果这个结果是不经常变化的呢?此 时就可以考虑将这个结果缓存起来,采用计算属性可以很方便的做到这一点;计算属性的主要特性就是为了将不经 常变化的计算结果进行缓存,以节约我们的系统开销
5.watch监控属性
通过watch里的属性绑定函数,当属性的值发生变化时,该函数就会自动调用,调用时可以接收两个参数,第一个属性时改变后的值,第一个属性时属性改变前的值。
<div id="app"> {{title}} <input type="text" v-model="title"> </div> <script src="https://cdn.bootcss.com/vue/2.6.11/vue.js"></script> <script> var v1 = new Vue({ el: "#app", data: { title: "hello vue", }, watch:{ title: function (newvalue, oldvalue) { console.log(newvalue + ":" + oldvalue); } } }) </script>
六、Vue改变样式
1. 通过给html元素的class属性绑定vue中的属性值,得到样式的动态绑定
<div id="app"> <div v-bind:class="{red:temp}"></div> 如果temp为true <div class=”red”> 如果temp为false <div> </div> <script src="https://cdn.bootcss.com/vue/2.6.11/vue.js"></script> <script> new Vue({ el: "#app", data: { temp: false, }, }) </script>
2. 通过computed返回一个对象,对象里面放着对个键值对
<div id="app"> <div :class="myclassstyle" class="mydiv"></div> <hr> <button type="button" @click="temp=!temp">点我</button> </div> <script src="https://cdn.bootcss.com/vue/2.6.11/vue.js"></script> <script> new Vue({ el: "#app", data: { temp: false, }, computed: { myclassstyle:function () { return { red: this.temp, mywidth: this.temp, } } } }) </script>
3. 通过直接双向绑定中的vue的属性来改变样式
<style> .mydiv{ width: 400px; height: 200px; background-color: gray; } .red{ background-color: red; } .green{ background-color: green; } .yellow{ background-color: yellow; } .blue{ background-color: blue; } .mywidth{ width: 600px; } </style> </head> <body> <div id="app"> <div :class="mycolor" class="mydiv"></div> <hr> <button type="button" @click="temp=!temp">点我</button> <input type="text" v-model="mycolor"> </div> <script src="https://cdn.bootcss.com/vue/2.6.11/vue.js"></script> <script> new Vue({ el: "#app", data: { temp: false, mycolor: "green", }, }) </script>
4. 在html标签中使用多个样式的组合
.mydiv{ width: 400px; height: 200px; background-color: gray; } .red{ background-color: red; } .mywidth{ width: 600px; } <div :class="[mycolor,mv]" class="mydiv"></div> <script> new Vue({ el: "#app", data: { temp: false, mv: "mywidth", mycolor: "green", }, }) </script>
5. 在内嵌的css样式里指明style属性的值
<style> .mydiv{ width: 400px; height: 200px; background-color: gray; } </style> </head> <body> <div id="app"> <div :style="{backgroundColor: bc}" class="mydiv"></div> </div> 注意:style引用了vue中的内容,因此是一个键值对,所以需要一个大括号,对象的值不能出现”background-color”,应该改成”backgroundColor” <script src="https://cdn.bootcss.com/vue/2.6.11/vue.js"></script> <script> new Vue({ el: "#app", data: { temp: false, mv: "mywidth", mycolor: "green", bc: "blue", }, }) </script>
6. 在style中使用多个样式组合
<style> .mydiv{ width: 400px; height: 200px; background-color: gray; } </style> </head> <body> <div id="app"> <div :style="[mycolor, {height: myheight + 'px'}]" class="mydiv"></div> <hr> 颜色:<input type="text" v-model="bc"><br> 高度:<input type="text" v-model="myheight"><br> </div> <script src="https://cdn.bootcss.com/vue/2.6.11/vue.js"></script> <script> new Vue({ el: "#app", data: { bc: "blue", myheight: 300, }, computed: { mycolor:function () { return { backgroundColor: this.bc } }, } }) </script>
七、Vue的核心:虚拟DOM和diff算法
Vue高效的核心,就是虚拟的DOM和diff算法,vue不通过修改dom树来达到修改的效果,而是直接修改页面上的那个元素,此时这个元素就是一个虚拟的dom,通过diff算法,计算虚拟的dom修改后和修改前的区别,然后在虚拟dom的原基础上进行修改,这样的你效率就大大提高了。
八、分支语句
1. v-if
2. v-else-if
3. v-else
<div id="app"> <div v-if="temp">看到我了</div> 当temp为true时显示 <div v-else-if="temp1">!!!前方高鞥</div> 当temp为false,temp1为true时显示 <div v-else="temp">我消失了</div> 当temp为false,temp1为false时显示 <button type="button" @click="temp=!temp">点我</button> </div> <script src="https://cdn.bootcss.com/vue/2.6.11/vue.js"></script> <script> new Vue({ el: "#app", data:{ temp: false, temp1: true, } }) </script>
4.v-show: 实际上是让该元素的display属性为none,隐藏的效果。所以性能更好。
用法上和v-if是相同的,v-show的布尔值为true时,会显示内容,false的时候不显示,但是v-show改变的是元素的样式,display: none(不显示),而v-if是直接让元素消失和添加元素,效率上v-show更高。
5. template模板标签的使用
在vue中可以使用该标签配合v-if实现多个元素一起出现或消失,注意:template不能和v-show一起用。
<template v-if="temp"> <div>hello vue1</div> <p>hello vue2</p> </template>
九、循环语句
v-for是Vue中循环的关键字
vue中可以通过v-for循环遍历数据源,在使用差值表达式输出数据
1. 普通的v-for、
<div id="app"> <ul> <li v-for="a in args">{{a}}</li> </ul> </div> <script src="https://cdn.bootcss.com/vue/2.6.11/vue.js"></script> <script> new Vue({ el: "#app", data:{ args: [0,1,2,3,4,5] } }) </script>
2. 带着索引的v-for
<ul> <li v-for="(num,i) in args":key="i">{{i}}-{{num}}</li> </ul>
3. 遍历一个对象
<ul> <li v-for="(value,key,index) in student">{{index}}-{{key}}-{{value}}</li> </ul> <script> new Vue({ el: "#app", data:{ student: { name: "张亚飞", age: 24, }, } }) </script>
4. 遍历一个对象数组:嵌套的for循环
<ul> <li v-for="student in students"> <span v-for="(value,key,index) in student">{{index}}-{{key}}-{{value}}</span> </li> </ul> <script> new Vue({ el: "#app", data:{ students: [ { name: "张亚飞1", age: 22, }, { name: "张亚飞2", age: 23, }, { name: "张亚飞3", age: 24, }, ] } }) </script>