v-if,顾名思义,条件判断。当得到结果为true时,所在的元素才会被渲染。
语法:v-if="布尔表达式"
示例:
看到我啦?!
看到我啦?!show
效果:
当v-if和v-for出现在一起时,v-for优先级更高。也就是说,会先遍历,再判断条件。
修改v-for中的案例,添加v-if:
-
{{index + 1}}. {{user.name}} - {{user.gender}} - {{user.age}}
你可以使用 v-else
指令来表示 v-if
的“else 块”:
看到我啦?!if
看到我啦?!else
v-else
元素必须紧跟在带 v-if
或者 v-else-if
的元素的后面,否则它将不会被识别。
v-else-if
,顾名思义,充当 v-if
的“else-if 块”,可以连续使用:
{{random}}
看到我啦?!if
看到我啦?!if 0.5
看到我啦?!if 0.25
看到我啦?!else
类似于 v-else
,v-else-if
也必须紧跟在带 v-if
或者 v-else-if
的元素之后。
演示:
另一个用于根据条件展示元素的选项是 v-show
指令。用法大致一样:
Hello!
不同的是带有 v-show
的元素始终会被渲染并保留在 DOM 中。v-show
只是简单地切换元素的 CSS 属性 display
。
示例:
你好
html属性不能使用双大括号形式绑定,只能使用v-bind指令。
在将 v-bind
用于 class
和 style
时,Vue.js 做了专门的增强。表达式结果的类型除了字符串之外,还可以是对象或数组。
在将 v-bind
用于 class
和 style
时,Vue.js 做了专门的增强。表达式结果的类型除了字符串之外,还可以是对象或数组。
在插值表达式中使用js表达式是非常方便的,而且也经常被用到。
但是如果表达式的内容很长,就会显得不够优雅,而且后期维护起来也不方便,例如下面的场景,我们有一个日期的数据,但是是毫秒值:
data:{
birthday:1529032123201 // 毫秒值
}
您的生日是:{{
new Date(birthday).getFullYear() + '-'+ new Date(birthday).getMonth()+ '-' + new Date(birthday).getDay()
}}
虽然能得到结果,但是非常麻烦。
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可以让我们监控一个值的变化。从而做出相应的反应。
示例:.
在大型应用开发的时候,页面可以划分成很多部分。往往不同的页面,也会有相同的部分。例如可能会有相同的头部导航。
但是如果每个页面都独自开发,这无疑增加了我们开发的成本。所以我们会把页面的不同部分拆分成独立的组件,然后在不同页面就可以共享这些组件,避免重复开发。
在vue里,所有的vue实例都是组件
Title
组件的data属性必须是函数!
组件时,它的data 并不是像之前直接提供一个对象:
Title
效果:
父组件使用子组件时,自定义属性(属性名任意,属性值为要传递的数据)
子组件通过props接收父组件数据,通过自定义属性的属性名
父组件使用子组件,并自定义了title属性:
Title
我们定义一个子组件,并接收复杂数据:
Title
这个是校验得小练习
来看这样的一个案例:
Title
效果:
使用vue-router和vue可以非常方便的实现 复杂单页应用的动态路由功能。
官网:https://router.vuejs.org/zh-cn/
使用npm安装:npm install vue-router --save
新建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
})
页面跳转控制:
登录
注册
通过
来指定一个锚点,当路由的路径匹配时,vue-router会自动把对应组件放到锚点位置进行渲染
通过
指定一个跳转链接,当点击时,会触发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:定义请求路径和组件的映射关系。相当于之前的
App.vue中也没有内容,而是定义了vue-router的锚点:
,我们之前讲过,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中的其它部分不会变化,这就实现了布局的共享。