奋斗是这么个过程,当时不觉累,过后不会悔。走一段再回头,会发现一个更强的本身,宛如新生。
你好,我是梦阳辰!期待与你相遇!
文章较长,切勿心急气躁,不然将一事无成!css
学习Vue前,咱们须要先了解一些MVVM,由于它很重要。
虽然没有彻底遵循 MVVM 模型,可是 Vue 的设计也受到了它的启发。html
1.什么是MVVM?
MVVM (Model-View-ViewModel)是一种软件架构设计模式,由微软WPF(用于替代
WinForm,之前就是用这个技术开发桌面应用程序的)和Silverlight(相似于Java Applet,简单点说就是在浏览器上运行的 WPF)的架构师Ken Cooper和Ted Peters开发,是一种简化用户界面的事件驱动编程方式。由John Gossman(一样也是WPF和Silverlight的架构师)于2005年在他的博客上发表。前端
MVVM源自于经典的MVC ( Model-View-Controller)模式。MVVM的核心是ViewModeA层,负责转换 Model中的数据对象来让数据变得更容易管理和使用,其做用以下:vue
该层向上与视图层进行双向数据绑定 向下与 Model层经过接口请求进行数据交互
MVVM已经至关成熟了,主要运用但不只仅在网络应用程序开发中。当下流行的MVVM框架有Vue.js , Angulars等。
02.为何要使用MVVMnode
MVVM模式和MVC模式同样,主要目的是分离视图(View)和模型(Model),有几大好处
。
低耦合:视图(View)能够独立于Model变化和修改,一个ViewModel能够绑定到不一样的View 上,当View变化的时候Model能够不变,当Model变化的时候View 也能够不变。webpack
可复用:你能够把一些视图逻辑放在一个ViewModel里面,让不少View重用这段视图逻辑。ios
独立开发:开发人员能够专一于业务逻辑和数据的开发(ViewModel),设计人员能够专一于页面设计。git
可测试:界面素来是比较难于测试的,而如今测试能够针对ViewModel来写。
3.MVVM的组成部分
View
View是视图层,也就是用户界面。前端主要由 HTNL和Css来构建,为了更方便地展示ViewNodel或者Model层的数据,已经产生了各类各样的先后端模板语言,好比FreeMarker.Thymeleaf等等,各大 MVVM框架如Vue.js,AngularJS,EJS等也都有本身用来构建用户界面的内置模板语言。es6
Model
Model是指数据模型,泛指后端进行的各类业务逻辑处理和数据操控,主要围绕数据库系统展开。这里的难点主要在于须要和前端约定统一的接口规则
ViewModel
ViewModel是由前端开发人员组织生成和维护的视图数据层。在这一层,前端开发者对从后端获取的 Model数据进行转换处理,作二次封装,以生成符合View层使用预期的视图数据模型。github
须要注意的是ViewModel所封装出来的数据模型包括视图的状态和行为两部分,而Model层的数据模型是只包含状态的。
好比页面的这一块展现什么,那一块展现什么这些都属于视图状态(展现)。
页面加载进来时发生什么,点击这一块发生什么,这一块滚动时发生什么这些都属于视图行为(交互)视图状态和行为都封装在了ViewModel里。这样的封装使得ViewModel能够完整地去描述View层`。因为实现了双向绑定,ViewModel的内容会实时展示在View层,这是激动人心的,由于前端开发者不再必低效又麻烦地经过操纵DOM去更新视图。
MVVM框架已经把最脏最累的一块作好了,咱们开发者只须要处理和维护ViewModel,更新数据视图就会自动获得相应更新,真正实现事件驱动编程。
View层展示的不是Model层的数据,而是viewModel 的数据,由ViewModel负责与Model层交互,这就彻底解耦了View层和Model层,这个解耦是相当重要的,它是先后端分离方案实施的重要一环。
Vue(读音/vju/,相似于view)是一套用于构建用户界面的渐进式框架,发布于2014年2月。与其它大型框架不一样的是,Vue被设计为能够自底向上逐层应用。Vue的核心库只关注视图层,不只易于上手,还便于与第三方库(如: vue-router,vue-resource,vuex)或既有项目整合。
渐进式意味着你能够将Vue做为你应用的一部分嵌入其中,带来更丰富的交互体验。
或者若是你但愿将更多的业务逻辑使用Vue实现,那么Vue的核心库以及其生态系统。
好比Core+Vue-router+Vuex,也能够知足你各类各样的需求。
Vue.js(读音 /vjuː/, 相似于 view) 是一套构建用户界面的渐进式框架。
Vue 只关注视图层, 采用自底向上增量开发的设计。
Vue 的目标是经过尽量简单的 API 实现响应的数据绑定和组合的视图组件。
1.MVVM模式的实现者
Model:模型层,在这里表示JavaScript对象
View:视图层,在这里表示 DOM(HTML操做的元素)
ViewModel:链接视图和数据的中间件,Vue.js 就是 MVVM中的ViewModel层的实现者在MVVM架构中,是不容许数据和视图直接通讯的,只能经过ViewModel来通讯,而ViewModel就是定义了一个 Observer观察者
ViewModel可以观察到数据的变化,并对视图对应的内容进行更新
ViewModel可以监听到视图的变化,并可以通知数据发生改变
至此,咱们就明白了,Vue.js 就是一个MVVM的实现者,他的核心就是实现了DOM监听与据绑定
Vue有不少特色和Web开发中常见的高级功能
解耦视图和数据
可复用的组件
前端路由技术
状态管理
虚拟DOM
2.为何要使用Vue.js
轻量级,体积小是一个重要指标。Vue.js压缩后有只有20多kb (Angular压缩后56kb+,React压缩后44kb+)
移动优先。更适合移动端,好比移动端的Touch事件·易上手,学习曲线平稳,文档齐全
吸收了Angular(模块化)和React(虚拟DOM)的长处,并拥有本身独特的功能,如:计算属性
开源,社区活跃度高
3.vue初体验
Vue.js的安装
方式一:
导入在线的cdn
对于制做原型或学习,你能够这样使用最新版本:
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
方式二:到官网下载文件:
https://vuejs.org/js/vue.js
方式三:NPM安装(重点)
在用 Vue 构建大型应用时推荐使用 NPM 安装[1]。NPM 能很好地和诸如 webpack 或 Browserify 模块打包器配合使用。同时 Vue 也提供配套工具来开发单文件组件。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>helloVue</title> <!--1.导入vue.js--> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script></head><body><div id="app"> {{message}}</div><script> var vm = new Vue({ el: "#app", data: { message: "helloVue" } });</script></body></html>
为了可以更直观的体验Vue 带来的数据绑定功能,咱们须要在浏览器测试一番,操做流程以下:
一、在浏览器上运行第一个Vue应用程序,进入开发者工具
二、在控制台输入vm.message = ‘Hello World’,而后回车,你会发现浏览器中显示的内容会直接变成Hello World
此时就能够在控制台直接输入vm.message来修改值,中间是能够省略data的,在这个操做中,我并无主动操做DOM,就让页面的内容发生了变化,这就是借助了Vue的数据绑定功能实现的;MVVM模式中要求ViewModel层就是使用观察者模式来实现数据的监听与绑定,以作到数据与视图的快速响应。
建立Vue实例传入的选项(options)
目前掌握这些选项:
el
√类型: string | HTMLlement
√做用∶决定以后Vue实例会管理哪个DOM。
data:
√类型:Object | Function(组件中data必须是一个函数)
√做用:Vue实例对应的数据对象。
methods:
√类型∶{ [key: string]: Function }
√做用∶定义属于Vue的一些方法,能够在其余地方调用,也能够在指令中使用。
Mustache语法:双括号表达式。
mustache语法中,不只能够直接写变量,也能够写简单的表达式。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> {{message}} {{message + name}} {{price*3}}</div><script> const app = new Vue({ el:"#app", data:{ message:"梦阳辰你好!", name:"梦阳辰", price:1000 } });</script></body></html>
不随数据的改变而改变
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> {{message}} <h3 v-once>{{name}}</h3><!--不会随着数据的改变而改变--></div><script> const app = new Vue({ el:"#app", data:{ message:"梦阳辰你好!", name:"梦阳辰", price:1000 } });</script></body></html>
服务器返回的是带html标签的数据,v-html将数据展现。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <h3 v-html="url"></h3><!----></div><script> const app = new Vue({ el:"#app", data:{ message:"梦阳辰你好!", url:'<a href="https://www.baidu.com">百度一下</a>' } });</script></body></html>
做用和Mustache比较相似。但mustache更加灵活。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <h3 v-html="url"></h3> <h2 v-text="message"></h2></div><script> const app = new Vue({ el:"#app", data:{ message:"梦阳辰你好!", url:'<a href="https://www.baidu.com">百度一下</a>' } });</script></body></html>
将标签中的内容原封不动的输出。不进行任何解析。
解决js代码执行慢而致使的内容闪烁问题。(后面采用虚拟dom,就不会存在这个问题)
由于是先加载标签,在运行js代码。
在vue解析以前,div中有一个属性v-cloak
在vue解析以后,div中没有一个属性v-cloak.
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script> <style> [v-cloak]{ display: none; } </style></head><body><div id="app" v-cloak> <h2>{{message}}</h2></div><script> setTimeout(function () { const app = new Vue({ el:"#app", data:{ message:"梦阳辰你好!", url:'<a href="https://www.baidu.com">百度一下</a>' } }); },1000)</script></body></html>
注意咱们再也不和 HTML 直接交互了。一个 Vue 应用会将其挂载到一个 DOM 元素上 (对于这个例子是 #app) 而后对其进行彻底控制。那个 HTML 是咱们的入口,但其他都会发生在新建立的 Vue 实例内部。
除了文本插值,咱们还能够像这样来绑定元素 attribute:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body><!--view层 模板--><div id="app2"> <span v-bind:title="message">鼠标悬停几秒钟查看此处动态绑定的提示信息!</span></div></body><!--导入js--><script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script><script> var vm = new Vue({ el: "#app2", data: { message: "hello,vue" } })</script></html>
语法糖::
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script> <style> [v-cloak]{ display: none; } </style></head><body><div id="app" v-cloak> <img :src="imgUrl" alt="风景"></div><script> setTimeout(function () { const app = new Vue({ el:"#app", data:{ message:"梦阳辰你好!", imgUrl:"https://dss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=2853553659,1775735885&fm=26&gp=0.jpg" } }); },1000)</script></body></html>
v-bind attribute 被称为指令。指令带有前缀 v-,以表示它们是 Vue 提供的特殊 attribute。可能你已经猜到了,它们会在渲染的 DOM 上应用特殊的响应式行为。在这里,该指令的意思是:“将这个元素节点的 title attribute 和 Vue 实例的 message property 保持一致”。
若是你再次打开浏览器的 JavaScript 控制台,输入 app2.message = ‘新消息’,就会再一次看到这个绑定了 title attribute 的 HTML 已经进行了更新。
绑定classs
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script> <style> .first{ color: lawngreen; } </style></head><body><div id="app"> <h3 :class="active">{{message}}</h3></div><script> const app = new Vue({ el:"#app", data:{ message:"梦阳辰你好!", active:'first' } });</script></body></html>
案例二(对象语法)
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script> <style> .active{ color: lawngreen; } </style></head><body><div id="app"> <!--<h3 :class="active">{{message}}</h3>--> <h3 :class="{active:isActive,line:isLine}">{{message}}</h3><!--对象--> <h3 :class="getClasses()">{{message}}</h3><!--对象--> <button v-on:click="btn">改变颜色</button></div><script> const app = new Vue({ el:"#app", data:{ message:"梦阳辰你好!", isActive:true, isLine:false }, methods:{ btn:function () { this.isActive=!this.isActive; }, getClasses:function () { return {active:this.isActive,line:this.isLine}; } } });</script></body></html>
案例三(数组语法)了解
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script> <style> .active{ color: lawngreen; } </style></head><body><div id="app"> <h3 class="title" :class="[active,line]">{{message}}</h3></div><script> const app = new Vue({ el:"#app", data:{ message:"梦阳辰你好!", active:"active", line:"fasd" } });</script></body></html>
v-bind动态绑定样式(style)
组件开发时经常使用。
若是不加单或双引号会看成变量使用。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script> <style> .active{ color: lawngreen; } </style></head><body><div id="app"><!--<h3 class="title" :style="{key(属性名):value(属性值))}">{{message}}</h3>--> <h3 class="title" :style="{color:'red'}">{{message}}</h3> <h3 class="title" :style="{color:red}">{{message}}</h3></div><script> const app = new Vue({ el:"#app", data:{ message:"梦阳辰你好!", red:"yellow" } });</script></body></html>
数组语法:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script> <style> .active{ color: lawngreen; } </style></head><body><div id="app"> <h3 class="title" :style="[style1,style2]">{{message}}</h3></div><script> const app = new Vue({ el:"#app", data:{ message:"梦阳辰你好!", style1:{fontSize:"50px"}, style2:{color:"green"} } });</script></body></html>
控制切换一个元素是否显示至关简单:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body><!--view层 模板--><div id="app-3"> <p v-if="seen">如今你看到我了</p></div></body><!--导入js--><script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script><script> var app3 = new Vue({ el: '#app-3', data: { seen: true } })</script></html>
继续在控制台输入 app3.seen = false,你会发现以前显示的消息消失了。
例二:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body><!--view层 模板--><div id="app"> <h3 v-if="type==='A'">A</h3> <h3 v-else-if="type==='B'">B</h3> <h3 v-else>C</h3></div></body><!--导入js--><script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script><script> var vm = new Vue({ el: "#app", data: { type: "1" } })</script></html>
登陆切换:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <span v-if="isUser"> <label for="userName" key="userName">用户帐号</label> <input type="text" id="userName" placeholder="用户帐号"> </span> <span v-else> <label for="email" key="email">用户邮箱</label> <input type="text" id="email" placeholder="用户邮箱"> </span> <button @click="isUser = !isUser">切换登陆</button></div><script> const app = new Vue({ el:"#app", data:{ message:"你好,梦阳辰!", isUser:true } });</script></body></html>
vue在进行Dom渲染时,出于性能的考虑会进行复用已经存在的元素,会根据key的值决定是否复用。
和v-if做用相同。
区别:
当v-show为false不显示时:它的元素仍是存在,只不过它的display属性的值为none。
而v-if为false时:它的元素根本就不会存在在dom中。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <h3 v-if="isUser">你好,梦阳辰!</h3> <h3 v-show="isUser">你好,梦阳辰!</h3></div><script> const app = new Vue({ el:"#app", data:{ message:"你好,梦阳辰!", isUser:false } });</script></body></html>
遍历数组:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <ul> <li v-for="(item,index) in names"> {{index+1}}.{{item}} </li> </ul></div><script> const app = new Vue({ el:"#app", data:{ message:"你好,梦阳辰!", names:["梦阳辰","mengyangchen"] } });</script></body></html>
遍历对象:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <ul> <li v-for="(value,key) in info"> {{key}}.{{value}} </li> </ul> <ul> <li v-for="(value,key,index) in info"> {{key}}:{{value}}---{{index}} </li> </ul></div><script> const app = new Vue({ el:"#app", data:{ message:"你好,梦阳辰!", info:{ name:"梦阳辰", age:20, height:171 } } });</script></body></html>
v-for绑定key与不绑定key区别:
绑定key能够高效的更新虚拟DOM。
在中间插入元素:(diff算法)
绑定的key若是值没有变化,能够复用。
可是没有绑定的话,会将指定的值改成插入的值,后续的值依次改(效率较低)
绑定的key的值应该和显示的内容一致。
数组哪些方法是响应式的:
数据改变,界面内容也随之改变。
push()后面添加 pop()最后一个删除 shift()第一个删除 unshift()数组最前面添加元素 splice()删除/插入/替换元素 splice(start,删除元素的个数) splice(start,0,你要插入的元素) splice(start,替换元素的个数,新的替换值) sort()排序 reverse()反转
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <ul> <li v-for="item in names" :key="item" > {{item}} </li> </ul> <button @click="way">操做数组</button></div><script> const app = new Vue({ el:"#app", data:{ message:"你好,梦阳辰!", names:["梦阳辰","mengyangchen"] }, methods:{ way(){ this.names.splice(0,1,"你好"); /*Vue.set(this.names,0,"fafd");*/ } } });</script></body></html>
点击哪一个值,哪一个值就亮色
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script> <style> .active{ color: lawngreen; } </style></head><body><div id="app"> <ul> <li v-for="(item,index) in moives" :class="{active:currentIndex===index}" @click="way(index)">{{item}}</li> </ul></div><script> const app = new Vue({ el:"#app", data:{ message:"梦阳辰你好!", moives:["海王","海贼王","魁拔"], currentIndex:0 }, methods:{ way(index){ this.currentIndex=index; } } });</script></body></html>
为了让用户和你的应用进行交互,咱们能够用 v-on 指令添加一个事件监听器,经过它调用在 Vue 实例中定义的方法:
<!DOCTYPE html><html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml"><head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script></head><body><div id="app-5"> <p>{{ message }}</p> <button v-on:click="reverseMessage">反转消息</button></div><script> var app5 = new Vue({ el: '#app-5', data: { message: 'Hello Vue.js!' }, methods: { reverseMessage: function () { this.message = this.message.split('').reverse().join('') } } })</script></body></html>
计数器:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body> <div id="app"> <h2>当前计数:{{counter}}</h2> <!--<button v-on:click="counter++">+</button> <button v-on:click="counter--">-</button>--> <button v-on:click="way1">+</button> <button @click="way2">-</button> </div> <script> const app = new Vue({ el:"#app", data:{ counter:0, }, methods:{ way1:function () { this.counter++; }, way2:function () { this.counter--; } } }); </script></body></html>
@click为v-on:click的简写。
methods属性:定义方法。
注意在 reverseMessage 方法中,咱们更新了应用的状态,但没有触碰 DOM——全部的 DOM 操做都由 Vue 来处理,你编写的代码只须要关注逻辑层面便可。
当经过methods中定义方法,以供@click调用时,须要注意参数问题:状况一∶若是该方法不须要额外参数,那么方法后的()能够不添加。
可是注意:若是方法自己中有一个参数,那么会默认将原生事件event参数传递进去
状况二∶若是须要同时传入某个参数,同时须要event时,能够经过**$event**传入事件。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <button @click="way1">1</button> <button @click="way1('你好')">2</button> <button @click="way2('梦阳辰',$event)">3</button></div><script> const app = new Vue({ el:"#app", data:{ counter:0, }, methods:{ way1:function (abc) { alert(abc); }, way2:function (abc,event) { alert(event); } } });</script></body></html>
v-on的修饰符:
Vue提供了修饰符来帮助咱们方便的处理一些事件
.stop-调用event.stopPropagation()阻止冒泡 .prevent -调用event.preventDefault() .{(keyCode | kelyAlias}-只当事件是从特定键触发时才触发回调。 .native -监听组件根元素的原生事件。 .once -只触发一次回调。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <!--.stop--> <div @click="divClick"> aaaaa <button @click.stop="btnClick">按钮</button> </div> <!--2.prevent修饰符--> <form action="baidu"> <input type="submit" value="提交" @click.prevent="submitClick"> </form> <!--监听某个键帽--> <input type="text" @keyup.enter="keyUp"></div><script> const app = new Vue({ el:"#app", data:{ counter:0, }, methods:{ divClick(){ alert("div触发") }, btnClick(){ alert("按钮触发") }, submitClick(){ alert("阻止提交") }, keyUp(){ alert("它按我了!") } } });</script></body></html>
Vue 还提供了 v-model 指令,它能轻松实现表单输入和应用状态之间的双向绑定。
1. 什么是双向绑定
Vue.js是一个MVVM框架,即数据双向绑定,即当数据发生变化的时候,视图也就发生变化,当视图发生变化的时候,数据也会跟着同步变化。这也算是Vue.js的精髓之处了。
值得注意的是,咱们所说的数据双向绑定,必定是对于UI控件来讲的,非UI控件不会涉及到数据双向绑定。单向数据绑定是使用状态管理工具的前提。若是咱们使用vuex,那么数据流也是单项的,这时就会和双向数据绑定有冲突。
2. 为何要实现数据的双向绑定
在Vue.js 中,若是使用vuex ,实际上数据仍是单向的,之因此说是数据双向绑定,这是用的UI控件来讲,对于咱们处理表单,Vue.js的双向数据绑定用起来就特别舒服了。即二者并不互斥,在全局性数据流使用单项,方便跟踪;局部性数据流使用双向,简单易操做。
3. 在表单中使用双向数据绑定
你能够用v-model指令在表单 、 及 元素上建立双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但v-model本质上不过是语法糖。它负责监听户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
本身实现双向绑定:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"><!--<input type="text" v-model= "message">--><input type="text" :value="message" @input="valuechange"><!--<input type="text" :value="message" @input= "message =$event.target.value">--> <h2 :key="message">{{message}}</h2><!--key表示--></div><script>const app = new Vue({ el:"#app", data: { message: "你好" }, methods: { valuechange(event){ this.message = event.target.value; } }})</script></body></html>
注意:v-model会忽略全部元素的value、checked、selected特性的初始值而老是将Vue实例的数据做为数据来源,你应该经过JavaScript在组件的data选项中声明。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script></head><body><div id="app-6"> <p>{{ message }}</p> <input v-model="message"></div><script> var app6 = new Vue({ el: '#app-6', data: { message: 'Hello Vue!' } });</script></body></html>
radio:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <input type="radio" value="男" v-model="gender">男 <input type="radio" value="女" v-model="gender">女 <h3 :key="gender">你选择的是:{{gender}}</h3></div><script> const app = new Vue({ el:"#app", data: { message: "你好", gender:"" } })</script></body></html>
select:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script></head><body><!--view层 模板--><div id="app"> 下拉框: <select v-model="selected"> <option value="" disabled>-请选择-</option> <option>A</option> <option>B</option> <option>C</option> </select> <p>value:{{selected}}</p></div></body><script> var vm = new Vue({ el: "#app", data: { selected: "" } })</script></html>
在select标签上加multiple
能够选择多个值。
单选框和多选框:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <label for="agree"> <input type="checkbox" id="agree" v-model="isAgree">赞成协议 </label> <h3>你选择的是:{{ isAgree}}</h3> <button :disabled=!isAgree>下一步</button> <!--多选框--><p>---------------------爱好-------------------</p> <input type="checkbox" value="篮球" v-model="hobbies">篮球 <input type="checkbox" value="足球" v-model="hobbies">足球 <input type="checkbox" value="乒乓球" v-model="hobbies">乒乓球 <h3 :key="hobbies">你的爱好是:{{hobbies}}</h3></div><script> const app = new Vue({ el:"#app", data: { message: "你好", isAgree:false, hobbies:[] } })</script></body></html>
值绑定
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <label v-for="item in originHobbies" > <input type="checkbox" :value=item v-model="hobbies">{{item}} </label> <h3 :key="hobbies">你的爱好是:{{hobbies}}</h3></div><script> const app = new Vue({ el:"#app", data: { message: "你好", isAgree:false, hobbies:[], originHobbies:['篮球','足球','乒乓球'] } })</script></body></html>
v-model的修饰符
lazy 取消实时绑定,当按下回车键或失去焦点时进行数据的更新。 number v-model默认给变量赋值的时候,赋值为string类型。加上number修饰符后... trim 去除左右两边的空格
组件系统是 Vue 的另外一个重要概念,由于它是一种抽象,容许咱们使用小型、独立和一般可复用的组件构建大型应用。仔细想一想,几乎任意类型的应用界面均可以抽象为一个组件树:
它提供了一种抽象,让咱们能够开发出一个个独立可复用的小组件来构造咱们的应用。
任何的应业用都会被抽象出一颗组件树。
有了组件化的思想,咱们在以后的开发中就要充分的利用它。尽量的将页面拆分红一个个小的、可复用的组件。
这样让咱们的代码更加方便组织和管理,而且扩展性也更强。
组件的使用分红三个步骤:
建立组件构造器
注册组件
使用组件
原始方式(不推荐使用,建议使用语法糖)
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><cpn></cpn><div id="app"> <my-cpn></my-cpn> <my-cpn></my-cpn> <my-cpn></my-cpn></div><script> /*es6可使用`来代替"和' * */ //1.建立组件构造器对象 const cpn = Vue.extend({ template:`<div> <h3>我是标题</h3> <p>我是内容1</p> <p>我是内容2</p> </div>` }) //2.注册组件 Vue.component('my-cpn',cpn) const app = new Vue({ el:"#app", data:{ message:"梦阳辰你好!", } })</script></body></html>
在 Vue 里,一个组件本质上是一个拥有预约义选项的一个 Vue 实例。在 Vue 中注册组件很简单:
语法糖:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script></head><body><ol id="app"> <!-- 建立一个 todo-item 组件的实例 --> <todo-item></todo-item></ol></body><script> // 定义名为 todo-item 的新组件 Vue.component('todo-item', { template: '<li>这是个待办项</li>' }); var app = new Vue({ el:"#app" });</script></html>
可是这样会为每一个待办项渲染一样的文本,这看起来并不炫酷。咱们应该能从父做用域将数据传到子组件才对。让咱们来修改一下组件的定义,使之可以接受一个 prop:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script></head><body><ol id="app"> <!-- 如今咱们为每一个 todo-item 提供 todo 对象 todo 对象是变量,即其内容能够是动态的。 咱们也须要为每一个组件提供一个“key”,稍后再 做详细解释。 --> <todo-item v-for="item in groceryList" v-bind:todo="item" v-bind:key="item.id" ></todo-item> </ol></body><script> Vue.component('todo-item', { // todo-item 组件如今接受一个 // "prop",相似于一个自定义 attribute。 // 这个 prop 名为 todo。 props: ['todo'], template: '<li>{{ todo.text }}</li>' }) var app7 = new Vue({ el: '#app', data: { groceryList: [ { id: 0, text: '蔬菜' }, { id: 1, text: '奶酪' }, { id: 2, text: '随便其它什么人吃的东西' } ] } })</script></html>
咱们已经设法将应用分割成了两个更小的单元。子单元经过 prop 接口与父单元进行了良好的解耦。咱们如今能够进一步改进 <todo-item>
组件,提供更为复杂的模板和逻辑,而不会影响到父单元。
全局组件和局部组件
能够在多个vue实例下使用。
在Vue实例中注册就是局部组件:
//1.建立组件构造器对象 const cpn = Vue.extend({ template:`<div> <h3>我是标题</h3> <p>我是内容1</p> <p>我是内容2</p> </div>` }) var app = new Vue({ el:"#app", components:{//mycpn就是使用组件时的标签名mycpn:cpn} });
父组件和子组件的区别:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <mycpn2></mycpn2></div><script> /*es6可使用`来代替"和' * */ //1.建立组件构造器对象 //子 const cpn1 = Vue.extend({ template:`<div> <h3>我是标题</h3> <p>我是内容1</p> <p>我是内容2</p> </div>` }) //父 const cpn2 = Vue.extend({ template:`<div> <h3>我是头部</h3> <p>我是内容1</p> <p>我是尾部</p> <cpn></cpn> </div>` , components:{ cpn:cpn1 } }) //2.注册组件 Vue.component('my-cpn',cpn1); const app = new Vue({ el:"#app", data:{ message:"梦阳辰你好!", }, components:{ mycpn2:cpn2 } });</script></body></html>
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><cpn></cpn><div id="app"> <my-cpn></my-cpn></div><!--方法1--><!--<script type="text/x-template" id="cpn"> <div> <h3>我是标题</h3> <p>我是内容1</p> <p>我是内容2</p> </div></script>--><!--方法二--><template id="cpn"> <div> <h3>我是标题</h3> <p>我是内容1</p> <p>我是内容2</p> </div></template><script> /*es6可使用`来代替"和' * */ //2.注册组件 Vue.component('my-cpn',{ template:id='#cpn' }) const app = new Vue({ el:"#app", data:{ message:"梦阳辰你好!", } })</script></body></html>
咱们发现不能访问,并且即便能够访问,若是将全部的数据都放在Vue实例中,Vue实例就会变的很是臃肿。
结论: Vue组件应该有本身保存数据的地方。
组件对象也有一个data属性(也能够有methods等属性,下面咱们有用到)只是这个data属性必须是一个函数。
并且这个函数返回一个对象,对象内部保存着数据
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><cpn></cpn><div id="app"> <my-cpn></my-cpn></div><template id="cpn"> <div> <h3>{{title}}</h3> <p>我是内容1</p> <p>我是内容2</p> </div></template><script> /*es6可使用`来代替"和' * */ //2.注册组件 Vue.component('my-cpn',{ template:`#cpn`, data(){ return{ title:'有点东西!' } } }) const app = new Vue({ el:"#app", data:{ message:"梦阳辰你好!", } })</script></body></html>
data属性为何必须是一个函数?
若是是一个属性(对象),应用重复来利用这个主键,可是但愿各个组件中的数据是互不影响的,data是属性就没法作到,可是是函数的话就能够作到各个组件实例互不影响。
咱们提到了子组件是不能引用父组件或者Vue实例的数据的。可是,在开发中,每每一些数据确实须要从上层传递到下层∶
好比在一个页面中,咱们从服务器请求到了不少的数据。
其中一部分数据,并不是是咱们整个页面的大组件来展现的,而是须要下面的子组件进行展现。
这个时候,并不会让子组件再次发送一次网络请求,而是直接让大组件(父组件)将数据传递给小组件(子组件)。
如何进行父子组件的通讯呢?
经过props向子组件传递数据 经过事件向父组件发送消息
vue实例能够看做是根组件。
props的使用
在组件中,使用选项props来声明须要从父级接收到的数据。
props的值有两种方式︰
方式一︰字符串数组,数组中的字符串就是传递时的名称。
方式二∶对象,对象能够设置传递时的类型,也能够设置默认值等。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><cpn></cpn><div id="app"> <mycpn v-bind:cmovies="movies" :cmessage="message"></mycpn></div><template id="cpn"> <div> <p>我是内容1</p> <p>我是内容2</p> {{cmessage}} <ul> <li v-for="item in cmovies">{{item}}</li> </ul> </div></template><script> const cpn ={ template:`#cpn`, // props:['cmovies','cmessage'], //类型限制 /* props:{ cmovies:Array, cmessage:String, },*/ //提供默认值 /* props:{ cmessage:{ type:String, default:"fasdf", required:true//加上后表示必传的值 } }*/ //类型是对象或者数组时,默认值必须时一个函数 props:{ cmovies:{ type:Array, default(){ return [] } } } , data(){ return{ title:'有点东西!' } }, methods:{ } } const app = new Vue({ el:"#app", data:{ message:"梦阳辰你好!", movies: ["海王","海贼王"] }, components:{ mycpn:cpn } })</script></body></html>
对于命名问题:
标签(如img)、属性名(如class) 均会自动在浏览器转化为小写,对大小写不敏感,因此用驼峰命名对存在问题。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><cpn></cpn><div id="app"> <mycpn v-bind:c-info="info" ></mycpn></div><template id="cpn"> <div> <p>我是内容1</p> <p>我是内容2</p> <h3>{{cInfo}}</h3> </div></template><script> const cpn ={ template:`#cpn`, //类型是对象或者数组时,默认值必须时一个函数 props:{ cInfo:{ type:Object, default(){ return {} } } }, data(){ return{ title:'有点东西!' } }, methods:{ } } const app = new Vue({ el:"#app", data:{ message:"梦阳辰你好!", info:{ name:"梦阳辰", age:20, gender:"男" } }, components:{ mycpn:cpn } })</script></body></html>
当子组件须要向父组件传递数据时,就要用到自定义事件了。
咱们以前学习的v-on不只仅能够用于监听DOM事件,也能够用于组件间的自定义事件。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <mycpn v-bind:c-info="info" v-on:item-click="cpnClick"></mycpn></div><template id="cpn"> <div> <button v-for="item in categories" @click="btn(item)"> {{item.name}} </button> </div></template><script> /*子组件*/ const cpn ={ template:`#cpn`, //类型是对象或者数组时,默认值必须时一个函数 props:{ cInfo:{ type:Object, default(){ return {} } } }, data(){ return{ categories:[ {id:"a",name:"热门推荐"}, {id:"b",name:"笔记本电脑"}, {id:"c",name:"手机"}, {id:"d",name:"化妆品"}, ] } }, methods:{ btn(item){ /*将信息传递给父组件,自定义事件*/ this.$emit('item-click',item); } } } /*父组件*/ const app = new Vue({ el:"#app", data:{ message:"梦阳辰你好!", info:{ name:"梦阳辰", age:20, gender:"男" } }, components:{ mycpn:cpn }, methods:{ cpnClick(item){ console.log(item) } } })</script></body></html>
父子互相影响数据
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body> <div id="app"> <cpn :number1="num1" :number2="num2" @num1_change="num1_change" @num2_change="num2_change" ></cpn> </div><template id="cpn"> <div> <h3 :key="number1">{{number1}}</h3> <h3 :key="temp_number1">{{temp_number1}}</h3> <input type="text" :value="temp_number1" @input="num1Input"> <h3 :key="number2">{{number2}}</h3> <h3 :key="temp_number2">{{temp_number2}}</h3> <input type="text" :value="temp_number2" @input="num2Input"> </div></template><script> //子组件 //父组件 const app = new Vue({ el:"#app", data:{ message:"梦阳辰", num1:0, num2:1 }, methods:{ num1_change(num){ this.num1=parseFloat(num) }, num2_change(num){ this.num2=parseFloat(num) } }, components:{ cpn:{//子组件 template:`#cpn`, props:{ number1:Number, number2:Number }, data(){ return{ temp_number1:this.number1, temp_number2:this.number2, } }, methods:{ num1Input(event){ this.temp_number1=event.target.value; /*将信息传递给父组件,自定义事件*/ this.$emit("num1_change",this.temp_number1); }, num2Input(event){ this.temp_number2=event.target.value; /*将信息传递给父组件,自定义事件*/ this.$emit("num2_change",this.temp_number2) } } } } })</script></body></html>
有时候咱们须要父组件直接访问子组件,子组件直接访问父组件,或者是子组件访问根组件。
父组件访问子组件:使用$children $refs reference
(引用)
子组件访问父组件:使用$parent
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <cpn></cpn> <cpn></cpn> <cpn ref="aa"></cpn> <button @click="btn">按钮</button></div><template id="cpn"> <div> <div>子组件</div> </div></template><script> //子组件 //父组件 const app = new Vue({ el:"#app", data:{ message:"梦阳辰", }, methods:{ btn(){ console.log(this.$children); this.$children[0].showMessage(); //alert(this.$children[2].name);//下标会改变,因此尽可能不要用下标拿属性(这种适合遍历拿全部的) /*$refs是对象类型,默认是一个空的对象,必须在组件上加ref属性*/ alert(this.$refs.aa.name);//用这种方式最佳 } }, components:{ cpn:{//子组件 template:`#cpn`, data(){ return{ name:"我是梦阳辰!" } }, methods:{ showMessage(){ alert("你好!") } } } } })</script></body></html>
子组件访问父组件:使用$parent
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"> <cpn></cpn></div><template id="cpn"> <div> <div>子组件1</div> <cpn1></cpn1> </div></template><template id="cpn1"> <div> <div>子组件2</div> <button @click="btn">按钮</button> </div></template><script> //子组件 //父组件 const app = new Vue({ el:"#app", data:{ message:"梦阳辰", }, components:{ cpn:{//子组件 template:`#cpn`, /*第二个子组件,这里不建议嵌套,只为练习使用(由于耦合度高,复用性差)*/ data(){ return{ name:"我是梦阳辰1" } }, components: { cpn1:{ template: `#cpn1`, methods:{ btn(){ //访问父组件 console.log(this.$parent) alert(this.$parent.name) /*访问根组件*/ console.log(this.$root) } } } } } } })</script></body></html>
计算属性的重点突出在属性两个字上(属性是名词),首先它是个属性其次这个属性有计算的能力(计算是动词),这里的计算就是个函数;简单点说,它就是一个可以将计算结果缓存起来的属性(将行为转化成了静态的属性),仅此而已;能够想象为缓存!
模板内的表达式很是便利,可是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板太重且难以维护。例如:
<div id="example"> {{ message.split('').reverse().join('') }}</div>
在这个地方,模板再也不是简单的声明式逻辑。你必须看一段时间才能意识到,这里是想要显示变量 message 的翻转字符串。当你想要在模板中的多处包含此翻转字符串时,就会更加难以处理。
因此,对于任何复杂逻辑,你都应当使用计算属性。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body><!--view层 模板--><div id="app"> <div>currentTime1: {{currentTime1()}}</div> <div>currentTime2: {{currentTime2}}</div></div></body><!--导入js--><script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script><script> var vm = new Vue({ el: "#app", data: { message: "hello,world!" }, methods: { currentTime1: function () { return Date.now(); // 返回一个时间戳 } }, computed: { //计算属性:methods,computed 方法名不能重名,重名字后,只会调用methods的方法 currentTime2: function () { this.message; // 返回一个时间戳 return Date.now(); } } })</script></html>
结论:
调用方法时,每次都须要进行计算,既然有计算过程则一定产生系统开销,那若是这个结果是不常常变化的呢?此时就能够考虑将这个结果缓存起来,采用计算属性能够很方便的作到这一点,计算属性的主要特性就是为了将不常常变化的计算结果进行缓存,以节约咱们的系统开销。
实例生命周期钩子
每一个 Vue 实例在被建立时都要通过一系列的初始化过程——例如,须要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程当中也会运行一些叫作生命周期钩子的函数,这给了用户在不一样阶段添加本身的代码的机会。
好比 created 钩子能够用来在一个实例被建立以后执行代码:
new Vue({ data: { a: 1 }, created: function () { // `this` 指向 vm 实例 console.log('a is: ' + this.a) }})// => "a is: 1"
也有一些其它的钩子,在实例生命周期的不一样阶段被调用,如 mounted、updated 和 destroyed。生命周期钩子的 this 上下文指向调用它的 Vue 实例。
不要在选项 property 或回调上使用箭头函数,好比 created: () => console.log(this.a) 或 vm.$watch('a', newValue => this.myMethod())。由于箭头函数并无 this,this 会做为变量一直向上级词法做用域查找,直至找到为止,常常致使 Uncaught TypeError: Cannot read property of undefined 或 Uncaught TypeError: this.myMethod is not a function 之类的错误。
生命周期图示
Vue 实例有一个完整的生命周期,也就是从开始建立、初始化数据、编译模板、挂载DOM、渲染→更新→渲染、卸载等一系列过程,咱们称这是Vue的生命周期。通俗说就是Vue 实例从建立到销毁的过程,就是生命周期。
在Vue的整个生命周期中,它提供了一系列的事件,可让咱们在事件触发时注册JS方法,可让咱们用本身注册的JS方法控制整个大局,在这些事件响应方法中的this直接指向的是Vue 的实例。
1. 什么是Axios
Axios是一个开源的能够用在浏览器端和NodeJS 的异步通讯框架,它的主要做用就是实现AJAX异步通讯,其功能特色以下:
从浏览器中建立XMLHttpRequests
从node.js建立http请求
支持Promise API [JS中链式编程]
拦截请求和响应
转换请求数据和响应数据
取消请求
自动转换JSON数据
客户端支持防护XSRF (跨站请求伪造)
GitHub: https://github.com/ axios/axios
中文文档: http://www.axios-js.com/
cdn:
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.19.2/axios.min.js"></script>
2. 为何要使用Axios
因为Vue.js是一个视图层框架且做者(尤雨溪) 严格准守SoC (关注度分离原则),因此Vue.js并不包含Ajax的通讯功能,为了解决通讯问题,做者单独开发了一个名为vue-resource的插件,不过在进入2.0 版本之后中止了对该插件的维护并推荐了Axios 框架。少用jQuery,由于它操做Dom太频繁 !
测试:
模拟后台返回的json数据:
{ "name": "mengyangchen", "age": "20", "sex": "男", "url":"https://www.baidu.com", "address": { "street": "文苑路", "city": "南京", "country": "中国" }, "links": [ { "name": "bilibili", "url": "https://www.bilibili.com" }, { "name": "baidu", "url": "https://www.baidu.com" }, { "name": "cqh video", "url": "https://www.4399.com" } ]}
vue
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body><!--view层 模板--><div id="vue"> <div>{{info.name}}</div> <div>{{info.address.street}}</div> <a v-bind:href="info.url">点我进入</a></div></body><!--1.导入vue.js--><script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script><!--导入axios--><script src="https://cdn.bootcdn.net/ajax/libs/axios/0.19.2/axios.min.js"></script><script> var vm = new Vue({ el: "#vue", data: { items: ['Java','Python','Php'] }, //data:vm的属性 //data():vm方法 data(){ return{ //请求的返回参数,必须和json字符串同样 info:{ name: null, age: null, sex: null, url: null, address: { street: null, city: null, country: null } } } }, //钩子函数,链式编程,ES6新特性 mounted(){ axios.get("../res/package.json").then(res => (this.info=res.data)) } })</script></html>
首页
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="style.css" > <script src="../res/js/vue.js"></script></head><body><div id="app"> <div v-if="books.length"> <table> <thead> <tr> <th></th> <th>书籍名称</th> <th>出版日期</th> <th>价格</th> <th>购买数量</th> <th>操做</th> </tr> </thead> <tbody> <tr v-for="(item,index) in books"> <td>{{item.id}}</td> <td>{{item.name}}</td> <td>{{item.date}}</td> <td>{{item.price | showPrice}}</td> <td> <button @click="way1(index)">+</button> {{item.count}} <button @click="way2(index)" v-bind:disabled="item.count<=1">-</button> </td> <td><button @click="remove(index)">移除</button></td> </tr> </tbody> </table> <h3>总价为:{{totalPrice | showPrice}}</h3> </div> <h3 v-else>购物车为空!</h3></div><script src="main.js"></script></body></html>
js代码
const app = new Vue({ el:"#app", data:{ books:[ {id:23,name:"算法第四版",date:"1999-9-26",price:198,count:5}, {id:24,name:"计算机基础",date:"1999-9-26",price:198,count:5}, {id:25,name:"Java核心卷",date:"1999-9-26",price:198,count:5}, {id:26,name:"深刻理解计算机原理",date:"1999-9-26",price:198,count:5} ] }, methods:{ way1(index){ this.books[index].count++; }, way2(index){ this.books[index].count--; }, remove(index){ this.books.splice(index,1) } }, /*过滤器*/ filters:{ showPrice(price){ return '¥'+price.toFixed(2); } }, computed:{ totalPrice(){ let totalPrice=0; for(let i=0;i<this.books.length;i++){ totalPrice+=this.books[i].price*this.books[i].count; } return totalPrice; } }});
css代码
table { border: 1px solid #e9e9e9; border-collapse: collapse; border-spacing: 0;}th,td { padding: 8px 16px; border: 1px solid #e9e9e9; text-align: left;}th { background-color: #f7f7f7; color: #5c6b77; font-weight: 600;}
for of直接取出数组的内容 i即表明数组中的每一项。 for(let i of this.books){ }
filter/map/reduce filter中的回调函数:必须返回一个boolean值 当返回true时,函数内部会自动将此次回调的n假如到新的数组中。若是为false,函数内部就会过滤掉此次的n。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="../res/js/vue.js"></script></head><body><div id="app"></div><script> const app = new Vue({ el:"#app", data:{ message:"你好,梦阳辰!", isTrue:1 } }); const nums=[1,344,5,64,45,78]; /*filter函数的使用*/ let newNums = nums.filter(function (n) { return n < 100 }) console.log(newNums) /*map函数的使用,对原数组进行操做*/ let newNums2 = nums.map(function (n) { return n*2; }) alert(newNums2) /*reduce函数,对数组中全部的内容进行汇总*/ let newNums3 = nums.reduce(function (preValue,n) { return preValue+n; },0) alert(newNums3)</script></body></html>
简洁的写法(箭头函数):
let total = nums.filter(n => n <100).map(n=>n*2).reduce((pre,n)=>pre+n);
If you find a path with no obstacles, it probably doesn’t lead anywhere.