乐优商城项目---day06-商品分类(vuetify-nginx-cors)

Vue-的基础使用

5.5.v-if和v-show

5.5.1.基本使用

v-if,顾名思义,条件判断。当获得结果为true时,所在的元素才会被渲染。javascript

语法:v-if="布尔表达式"html

v-if="布尔表达式"

示例:

<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>

效果:前端

5.5.2.与v-for结合

当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>

 

5.5.3.v-else

你可使用 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-elsev-else-if 也必须紧跟在带 v-if 或者 v-else-if 的元素以后。vue-router

演示:npm

5.5.4.v-show

另外一个用于根据条件展现元素的选项是 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>

 

5.6.v-bind

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 计算属性会当即返回以前的计算结果,而没必要再次执行函数。

5.8.watch

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>

6.组件化

在大型应用开发的时候,页面能够划分红不少部分。每每不一样的页面,也会有相同的部分。例如可能会有相同的头部导航。

可是若是每一个页面都独自开发,这无疑增长了咱们开发的成本。因此咱们会把页面的不一样部分拆分红独立的组件,而后在不一样页面就能够共享这些组件,避免重复开发。

在vue里,全部的vue实例都是组件

全局组件

咱们经过Vue的component方法来定义一个全局组件。

<!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>
  • 组件其实也是一个Vue实例,所以它在定义时也会接收:data、methods、生命周期函数等

  • 不一样的是组件不会与页面的元素绑定,不然就没法复用了,所以没有el属性。

  • 可是组件渲染须要html模板,因此增长了template属性,值就是HTML模板

  • 全局组件定义完毕,任何vue实例均可以直接在HTML中经过组件名称来使用组件了。

  • data必须是一个函数,再也不是一个对象。

效果:

 

 

你会发现每一个组件互不干扰,都有本身的count值。怎么实现的?

 

组件的data属性必须是函数

当咱们定义这个 <counter> 组件时,它的data 并非像以前直接提供一个对象:

取而代之的是,一个组件的 data 选项必须是一个函数,所以每一个实例能够维护一份被返回对象的独立的拷贝:

data: function () {
 return {
   count: 0
  }
}

若是 Vue 没有这条规则,点击一个按钮就会影响到其它全部实例!

 

局部组件:

一旦全局注册,就意味着即使之后你再也不使用这个组件,它依然会随着Vue的加载而加载。

所以,对于一些并不频繁使用的组件,咱们会采用局部注册。

咱们先在外部定义一个对象,结构与建立组件时传递的第二个参数一致:

<!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>
  • components就是当前vue对象子组件集合。

    • 其key就是子组件名称

    • 其值就是组件对象名

  • 效果与刚才的全局注册是相似的,不一样的是,这个counter组件只能在当前的Vue实例中使用

 

效果:

6.4.1.props(父向子传递)

  1. 父组件使用子组件时,自定义属性(属性名任意,属性值为要传递的数据)

  2. 子组件经过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>

 

6.4.2.props验证

咱们定义一个子组件,并接收复杂数据:

<!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>

这个是校验得小练习

 

6.4.4.子向父的通讯:$emit

来看这样的一个案例:

<!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>

效果:

7.2.vue-router简介和安装

使用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>

7.3.快速入门

新建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

Vue-总结:

 

1.搭建后台管理前端

1.1.导入已有资源

 

1.2.安装依赖

你应该注意到,这里并无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中)

2.Vuetify框架

2.1.为何要学习UI框架

Vue虽然会帮咱们进行视图的渲染,但样式仍是由咱们本身来完成。这显然不是咱们的强项,所以后端开发人员通常都喜欢使用一些现成的UI组件,拿来即用,常见的例如:

  • BootStrap

  • LayUI

  • EasyUI

  • ZUI

然而这些UI组件的基因天生与Vue不合,由于他们更多的是利用DOM操做,借助于jQuery实现,而不是MVVM的思想。

而目前与Vue吻合的UI框架也很是的多,国内比较知名的如:

  • element-ui:饿了么出品

  • i-view:某公司出品

然而咱们都不用,咱们今天推荐的是一款国外的框架:Vuetify

官方网站:https://vuetifyjs.com/zh-Hans/

2.2.为何是Vuetify

有中国的为何还要用外国的?缘由以下:

  • Vuetify几乎不须要任何CSS代码,而element-ui许多布局样式须要咱们来编写

  • Vuetify从底层构建起来的语义化组件。简单易学,容易记住。

  • Vuetify基于Material Design(谷歌推出的多平台设计规范),更加美观,动画效果酷炫,且风格统一

这是官网的说明:

缺陷:

  • 目前官网虽然有中文文档,但由于翻译问题,几乎不太能看。

2.3.怎么用?

基于官方网站的文档进行学习:

 

一个典型的三块布局。包含左,上,中三部分:

 

里面使用了Vuetify中的2个组件和一个布局元素:

  • v-navigation-drawer :导航抽屉,主要用于容纳应用程序中的页面的导航连接。

 

v-toolbar:工具栏一般是网站导航的主要途径。能够与导航抽屉一块儿很好地工做,动态选择是否打开导航抽屉,实现可伸缩的侧边栏。

  • v-content:并非一个组件,而是标记页面布局的元素。能够根据您指定的app组件的结构动态调整大小,使得您能够建立高度可定制的组件。

那么问题来了:v-content中的内容来自哪里?

 

  • Layout映射的路径是/

  • 除了Login之外的全部组件,都是定义在Layout的children属性,而且路径都是/的下面

  • 所以当路由到子组件时,会在Layout中定义的锚点中显示。

  • 而且Layout中的其它部分不会变化,这就实现了布局的共享。