v-if,顾名思义,条件判断。当获得结果为true时,所在的元素才会被渲染。javascript
语法:v-if="布尔表达式"html
示例:
<div id="app"> <button v-on:click="show = !show">点我呀</button> <br> <h1 v-if="show"> 看到我啦?! </h1> <h1 v-show="show"> 看到我啦?!show </h1> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script type="text/javascript"> var app = new Vue({ el: "#app", data: { show: true } }) </script>
效果:前端
当v-if和v-for出如今一块儿时,v-for优先级更高。也就是说,会先遍历,再判断条件。vue
修改v-for中的案例,添加v-if:java
<ul> <li v-for="(user, index) in users" v-if="user.gender == '女'"> { {index + 1}}. { {user.name}} - { {user.gender}} - { {user.age}} </li> </ul>
你可使用 v-else
指令来表示 v-if
的“else 块”:node
<div id="app"> <h1 v-if="Math.random() > 0.5"> 看到我啦?!if </h1> <h1 v-else> 看到我啦?!else </h1> </div>
v-else
元素必须紧跟在带 v-if
或者 v-else-if
的元素的后面,不然它将不会被识别。webpack
v-else-if
,顾名思义,充当 v-if
的“else-if 块”,能够连续使用:web
<div id="app"> <button v-on:click="random=Math.random()">点我呀</button><span>{ {random}}</span> <h1 v-if="random >= 0.75"> 看到我啦?!if </h1> <h1 v-else-if="random > 0.5"> 看到我啦?!if 0.5 </h1> <h1 v-else-if="random > 0.25"> 看到我啦?!if 0.25 </h1> <h1 v-else> 看到我啦?!else </h1> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script type="text/javascript"> var app = new Vue({ el: "#app", data: { random: 1 } }) </script>
相似于 v-else
,v-else-if
也必须紧跟在带 v-if
或者 v-else-if
的元素以后。vue-router
演示:npm
另外一个用于根据条件展现元素的选项是 v-show
指令。用法大体同样:
<h1 v-show="ok">Hello!</h1>
不一样的是带有 v-show
的元素始终会被渲染并保留在 DOM 中。v-show
只是简单地切换元素的 CSS 属性 display
。
示例:
<div id="app"> <!--事件中直接写js片断--> <button v-on:click="show = !show">点击切换</button><br/> <h1 v-if="show"> 你好 </h1> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script type="text/javascript"> var app = new Vue({ el:"#app", data:{ show:true } }) </script>
html属性不能使用双大括号形式绑定,只能使用v-bind指令。
在将 v-bind
用于 class
和 style
时,Vue.js 作了专门的加强。表达式结果的类型除了字符串以外,还能够是对象或数组。
<div id="app"> <!--能够是数据模型,能够是具备返回值的js代码块或者函数--> <div v-bind:title="title" style="border: 1px solid red; width: 50px; height: 50px;"></div> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script type="text/javascript"> var app = new Vue({ el: "#app", data: { title: "title", } }) </script>
在将 v-bind
用于 class
和 style
时,Vue.js 作了专门的加强。表达式结果的类型除了字符串以外,还能够是对象或数组。
在插值表达式中使用js表达式是很是方便的,并且也常常被用到。
可是若是表达式的内容很长,就会显得不够优雅,并且后期维护起来也不方便,例以下面的场景,咱们有一个日期的数据,可是是毫秒值:
data:{
birthday:1529032123201 // 毫秒值
}
<h1>您的生日是:{ { new Date(birthday).getFullYear() + '-'+ new Date(birthday).getMonth()+ '-' + new Date(birthday).getDay() }} </h1>
虽然能获得结果,可是很是麻烦。
Vue中提供了计算属性,来替代复杂的表达式:
var vm = new Vue({ el:"#app", data:{ birthday:1429032123201 // 毫秒值 }, computed:{ birth(){// 计算属性本质是一个方法,可是必须返回结果 const d = new Date(this.birthday); return d.getFullYear() + "-" + d.getMonth() + "-" + d.getDay(); } } })
计算属性本质就是方法,可是必定要返回数据。而后页面渲染时,能够把这个方法当成一个变量来使用。
页面使用:
咱们能够将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是彻底相同的。然而,不一样的是计算属性是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变时才会从新求值。这就意味着只要birthday
尚未发生改变,屡次访问 birthday
计算属性会当即返回以前的计算结果,而没必要再次执行函数。
watch可让咱们监控一个值的变化。从而作出相应的反应。
示例:.
<div id="app"> <input type="text" v-model="message"> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script type="text/javascript"> var vm = new Vue({ el:"#app", data:{ message:"" }, watch:{ message(newVal, oldVal){ console.log(newVal, oldVal); } } }) </script>
在大型应用开发的时候,页面能够划分红不少部分。每每不一样的页面,也会有相同的部分。例如可能会有相同的头部导航。
可是若是每一个页面都独自开发,这无疑增长了咱们开发的成本。因此咱们会把页面的不一样部分拆分红独立的组件,而后在不一样页面就能够共享这些组件,避免重复开发。
在vue里,全部的vue实例都是组件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <hello></hello> <hello></hello> </div> <script src="node_modules/vue/dist/vue.js"></script> <script> Vue.component("hello",{ template:"<button @click='num++'>{ {num}}点我一下</button>", data(){ return { num:0 } } }) const app=new Vue({ el:"#app" }) </script> </body> </html>
组件的data属性必须是函数!
<counter>
组件时,它的data 并非像以前直接提供一个对象:<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <hello></hello> <hello></hello> <hello></hello> <hello></hello> </div> <script src="node_modules/vue/dist/vue.js"></script> <script> const constr={ template:"<button @click='num++'>点我一下{ {num}}</button>", data(){ return{ num:0 } } } const app=new Vue({ el:"#app", components:{ hello:constr } }) </script> </body> </html>
效果:
父组件使用子组件时,自定义属性(属性名任意,属性值为要传递的数据)
子组件经过props接收父组件数据,经过自定义属性的属性名
父组件使用子组件,并自定义了title属性:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <hello :nu="num"></hello> <hello :nu="num"></hello> </div> <script src="node_modules/vue/dist/vue.js"></script> <script> Vue.component("hello",{ template:"<button @click='nu++'>点我一下{ {nu}}</button>", props:["nu"] }) const app=new Vue({ el:"#app", data:{ num:0 } }) </script> </body> </html>
咱们定义一个子组件,并接收复杂数据:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <hello :nu="num"></hello> <hello :nu="num"></hello> </div> <script src="node_modules/vue/dist/vue.js"></script> <script> Vue.component("hello",{ template:"<button @click='nu++'>点我一下{ {nu}}</button>", props:{ nu:{ require:true, type:Number } } }) const app=new Vue({ el:"#app", data:{ num:0 } }) </script> </body> </html>
这个是校验得小练习
来看这样的一个案例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <hello :ti="num" @incrs="inc()"></hello> </div> <script src="node_modules/vue/dist/vue.js"></script> <script> Vue.component("hello",{ template:"<button @click='sub' >{ {ti}}点我一下</button>", props:["ti"], methods:{ sub(){ this.$emit("incrs") } } }) const app=new Vue({ el:"#app", data:{ num:0 }, methods:{ inc(){ this.num++; } } }) </script> </body> </html>
效果:
使用vue-router和vue能够很是方便的实现 复杂单页应用的动态路由功能。
官网:https://router.vuejs.org/zh-cn/
使用npm安装:npm install vue-router --save
在index.html中引入依赖:
<script src="../node_modules/vue-router/dist/vue-router.js"></script>
新建vue-router对象,而且指定路由规则:
const router=new VueRouter({ routes:[ { path:"/login", component: loginForm },{ path:"/register", component:registerForm } ] })
建立VueRouter对象,并指定路由参数
routes:路由规则的数组,能够指定多个对象,每一个对象是一条路由规则,包含如下属性:
path:路由的路径
component:组件名称
在父组件中引入router对象:
const app=new Vue({ el:"#app", components:{ loginForm, registerForm } ,router })
页面跳转控制:
<div id="app"> <span> <router-link to="/login"> 登陆 </router-link> </span> <span> <router-link to="/register"> 注册 </router-link> </span> <hr> <div> <router-view></router-view> </div> </div>
经过<router-view>
来指定一个锚点,当路由的路径匹配时,vue-router会自动把对应组件放到锚点位置进行渲染
经过<router-link>
指定一个跳转连接,当点击时,会触发vue-router的路由功能,路径中的hash值会随之改变
效果:
注意:单页应用中,页面的切换并非页面的跳转。仅仅是地址最后的hash值变化。
事实上,咱们总共就一个HTML:index.html
你应该注意到,这里并无node_modules文件夹,方便给你们下发,已经把依赖都删除了。不过package.json中依然定义了咱们所需的一切依赖:
咱们只须要打开终端,进入项目目录,输入:npm install
命令,便可安装这些依赖。
理一下:
index.html:html模板文件。定义了空的div
,其id为app
。
main.js:实例化vue对象,而且经过id选择器绑定到index.html的div中,所以main.js的内容都将在index.html的div中显示。main.js中使用了App组件,即App.vue,也就是说index.html中最终展示的是App.vue中的内容。index.html引用它以后,就拥有了vue的内容(包括组件、样式等),因此,main.js也是webpack打包的入口。
index.js:定义请求路径和组件的映射关系。至关于以前的<vue-router>
App.vue中也没有内容,而是定义了vue-router的锚点:<router-view>
,咱们以前讲过,vue-router路由后的组件将会在锚点展现。
最终结论:一切路由后的内容都将经过App.vue在index.html中显示。
访问流程:用户在浏览器输入路径,例如:http://localhost:9001/#/item/brand --> index.js(/item/brand路径对应pages/item/Brand.vue组件) --> 该组件显示在App.vue的锚点位置 --> main.js使用了App.vue组件,并把该组件渲染在index.html文件中(id为“app”的div中)
Vue虽然会帮咱们进行视图的渲染,但样式仍是由咱们本身来完成。这显然不是咱们的强项,所以后端开发人员通常都喜欢使用一些现成的UI组件,拿来即用,常见的例如:
BootStrap
LayUI
EasyUI
ZUI
然而这些UI组件的基因天生与Vue不合,由于他们更多的是利用DOM操做,借助于jQuery实现,而不是MVVM的思想。
而目前与Vue吻合的UI框架也很是的多,国内比较知名的如:
element-ui:饿了么出品
i-view:某公司出品
然而咱们都不用,咱们今天推荐的是一款国外的框架:Vuetify
官方网站:https://vuetifyjs.com/zh-Hans/
有中国的为何还要用外国的?缘由以下:
Vuetify几乎不须要任何CSS代码,而element-ui许多布局样式须要咱们来编写
Vuetify从底层构建起来的语义化组件。简单易学,容易记住。
Vuetify基于Material Design(谷歌推出的多平台设计规范),更加美观,动画效果酷炫,且风格统一
这是官网的说明:
缺陷:
目前官网虽然有中文文档,但由于翻译问题,几乎不太能看。
基于官方网站的文档进行学习:
一个典型的三块布局。包含左,上,中三部分:
里面使用了Vuetify中的2个组件和一个布局元素:
v-navigation-drawer
:导航抽屉,主要用于容纳应用程序中的页面的导航连接。
v-toolbar
:工具栏一般是网站导航的主要途径。能够与导航抽屉一块儿很好地工做,动态选择是否打开导航抽屉,实现可伸缩的侧边栏。
v-content
:并非一个组件,而是标记页面布局的元素。能够根据您指定的app组件的结构动态调整大小,使得您能够建立高度可定制的组件。
那么问题来了:v-content
中的内容来自哪里?
Layout映射的路径是/
除了Login之外的全部组件,都是定义在Layout的children属性,而且路径都是/
的下面
所以当路由到子组件时,会在Layout中定义的锚点中显示。
而且Layout中的其它部分不会变化,这就实现了布局的共享。