Vue 入门

一、Vue 介绍

Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合

每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例开始的:

var vm = new Vue({
  // 选项
})

虽然没有完全遵循 MVVM 模型,但是 Vue 的设计也受到了它的启发。因此经常会使用 vm (ViewModel 的缩写) 这个变量名表示 Vue 实例。

 

 

当创建一个 Vue 实例时,可以传入一个选项对象

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue入门</title>
</head>
<body>
    <!--div就是Vue实例作用的范围-->
    <!--{{message}}就是View Model,其包含了Vue实例中的data选项内定义的message变量-->
    <div id="app">{{message}}</div>
</body>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
    let option = {//选项
        el: '#app', //指定Vue实例作用的元素,也就是View的范围
        data: {//数据模型,也就是Model
            //message变量的值一旦发生变化,就会更新与之相关的View Model,View Model一旦更新,
            //View呈现的内容也会随着更新
            message: '这是一条信息' 
        }
    }
    new Vue(option)
</script>
</html>

二、Vue 生命周期钩子函数

 

 

三、模板语法

Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层组件实例的数据。所有 Vue.js 的模板都是合法的 HTML,所以能被遵循规范的浏览器和 HTML 解析器解析。

在底层的实现上,Vue 将模板编译成虚拟 DOM 渲染函数。结合响应性系统,Vue 能够智能地计算出最少需要重新渲染多少组件,并把 DOM 操作次数减到最少。

1. 文本插值

<!-- {{msg}} 表示引用变量msg的值作为span标签的文本内容,变量msg的值发生变化时文本内容会发生变化-->
<span>{{ msg }}</span>
<!-- v-text="msg" 表示引用变量msg的值作为span标签的文本内容,变量msg的值发生变化时文本内容会发生变化-->
<span v-text="msg"></span>
<!-- v-once 表示引用变量msg的值作为span标签的文本内容,变量msg的值发生变化时文本内容不会发生变化,只生效一次-->
<span v-once>{{ msg }}</span>
​
<script type="text/javascript">
    new Vue({
        el: '#app',
        data: {
            content: '这是一条消息'
        }
    })
</script>

2. HTML 插值

<!-- v-html="content"表示引用变量content的值作为div标签的html内容,变量content的值发生变化时,div显示的html内容也跟随着发生变化 -->
<div v-html="content"></div>
​
<script type="text/javascript">
    new Vue({
        el: '#app',
        data: {
            content: '这是文本内容'
        }
    })
</script>

3. 属性绑定

<!-- v-bind:id="id" 表示引用变量id的值作为div标签的id属性值-->
<div v-bind:id="id"></div>
<!-- :id="id" 是 v-bind:id="id" 的缩写-->
<div :id="id"></div>
<!-- :[attr]="attrValue" 表示动态属性绑定, 引用变量attr的值作为属性名,引用attrValue的值作为属性值-->
​
<div :[attr]="attrValue"></div>
<script type="text/javascript">
    new Vue({
        el: '#app',
        data: {
            id: 'first',
            attr: 'name',
            attrValue: 'firstDiv'
        }
    })
</script>

4. 事件绑定

<!-- v-on:click="clickFun" 表示点击a标签时执行clickFun函数-->
<a v-on:click="clickFun">点击</a>
<!-- @click="clickFun" 是  v-on:click="clickFun" 的缩写-->
<a @click="clickFun">点击</a>
<!-- @click.prevent 表示点击时触发的事件调用event.preventDefault()-->
<a @click.prevent="clickFun">点击</a>
<script type="text/javascript">
    new Vue({
        el: '#app',
        data: {
            content: '这是文本内容'
        },
        methods: {
            clickFun: function(){
                console.log("你进行了点击操作")
            }
        }
    })
</script>

5. Class绑定

<!--div元素是否拥有类样式取决于data属性中isActive的值是否为true-->
<div :class="{ active: isActive }"></div>
<!--根据不同的条件控制类样式呈现-->
<div :class="{ active: isActive, 'error-msg':  isError }"></div>
<!--通过数组绑定类样式-->
<div :class="[activeClass, errorClass]"></div>
<!--通过三元一次运算符绑定-->
<div :class="[isActive ? 'active' : '']"></div>
​
<script type="text/javascript">
    new Vue({
        el: '#app',
        data: {
            isActive: false,
            isError: false,
            activeClass: 'active',
            errorClass: 'error'
        }
    })
</script>

6. 条件渲染

<!--根据flag的值控制div及其子元素是否显示-->
<div v-if="flag === 1">flag = 1</div>
<div v-else-if="flag === 2">flag = 2</div>
<div v-else>flag = 3</div>
<!--根据errorMsg的值控制div是否显示-->
<div v-show="errorMsg !=='' " v-text="errorMsg"></div>
​
<!--v-if 和 v-show的区别: v-if切换时的开销高,v-show渲染时的开销高-->
​
<script type="text/javascript">
    new Vue({
        el: '#app',
        data: {
            flag: 1,
            errorMsg: ''
        }
    })
</script>

7. 列表渲染

<select>
    <!--v-for表示循环遍历,(s,index)中的s表示每次遍历时使用的变量名,index表示元素所在的下标,
:key表示option元素是唯一的,需要每次都重新渲染,:value表示每次选中该option选项时使用的值,
{{s}}位于option标签对之间,其值作为option选项的内容呈现-->
    <option v-for="(s,index) in sexList" :key="index" :value="s">{{s}}</option>
</select>
<script type="text/javascript">
    new Vue({
        el: '#app',
        data: {
            sexList: ['男','女','其他']
        }
    })
</script>

8. 表单输入绑定

<!--将文本框中内容与user对象中的username属性绑定在一起,这是一种双向绑定,文本框中的内容变化时,
            username属性值也会发生变化,username属性值发生变化时,文本框显示内容也会发生变化-->
<input type="text" v-model="user.username">
<input type="password" v-model="user.password">
<!--绑定的数据必须是数字-->
<input type="number" v-model.number="user.age">
<!--复选框组绑定时,必须进行分组,且绑定的数据是一个数组-->
<input type="checkbox" name="hobby" v-model="user.hobbies" value="0">打游戏
<input type="checkbox" name="hobby" v-model="user.hobbies" value="1">撸代码
<input type="checkbox" name="hobby" v-model="user.hobbies" value="2">处对象
<!--单选框组绑定时,必须进行分组-->
<input type="radio" name="sex" v-model="user.sex" value="0">男
<input type="radio" name="sex" v-model="user.sex" value="1">女
<input type="radio" name="sex" v-model="user.sex" value="2">其他
<input type="button" value="打印user对象" @click="showUser">
​
<script type="text/javascript">
    new Vue({
        el: '#app',
        data: {
            user: {
                username: '',
                password: '',
                age: '',
                hobbies: [],
                sex: ''
            }
        },
        methods: {
            showUser: function () {
                //在方法中访问data属性中定义的变量时,必须要加this
                console.log(this.user)
            }
        }
    })
</script>

四、Vue组件

1. Vue组件定义

  • 新建 template.js

    //component函数就是用来定义组件的
    //第一个参数就是组件的名称
    //第二个参数就是组件的详细信息,包括使用的模板template和该组件使用的数
    //据data,与普通页面不同的是,组件中的数据定义的方式使用的是一个data方法
    //来获取,因此,需要返回一个定义好的数据对象
    Vue.component("qf-pagination",{
        //template模板只允许存在一个根标签
        template: '<div>' +
            '<button v-for="page in totalPage" v-text="page" @click="gotoPage(page)"></button>' +
            '</div>',
        data(){
            return {
                totalPage: 10
            }
        },
        methods: {
            gotoPage: function (page) {
                console.log(page)
            }
        }
    });
  • 页面中引入 template.js

    <body>
        <div id="app"></div>
    </body>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript" src="js/templates.js"></script>
    <script type="text/javascript">
        new Vue({
            el: '#app',
            data: {
    ​
            }
        })
    </script>
  • 页面中使用组件

<body>
    <div id="app">
        <!--引用定义的组件-->
        <qf-pagination></qf-pagination>
    </div>
</body>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript" src="js/templates.js"></script>
<script type="text/javascript">
    new Vue({
        el: '#app',
        data: {
​
        }
    })
</script>

2. 组件传值

组件的主要作用就是进行重复利用。在重复利用的过程中就会涉及到数据的传递,那么,组件是怎么接收传递的过来的数据的呢?

在定义组件时,通过 props 属性定义组件接收的数据,在使用组件时,需要传递 props 中定义的属性值。

  • 定义组件

    Vue.component("user-info", {
        template: '<ul>' +
                      '<li v-for="prop in Object.keys(user)">{{prop +"=>" + user[prop]}}</li>' +
                  '</ul>',
        props: ['user']
    })
  • 调用组件

    <body>
        <div id="app">
            <!--引用定义的组件-->
            <user-info :user="user"></user-info>
        </div>
    </body>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript" src="js/templates.js"></script>
    <script type="text/javascript">
        new Vue({
            el: '#app',
            data: {
                user: {
                    username: 'admin',
                    password: '123456',
                    name: '管理员'
                }
            }
        })
    </script>

五、自定义指令

1. 语法

Vue.directive('指令名称', {
  //钩子函数
})

2. 自定义指令的钩子函数

  • bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。

  • inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。

  • update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。

  • componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。

  • unbind:只调用一次,指令与元素解绑时调用。

    指令钩子函数会被传入以下参数:

    //el:指令所绑定的元素,可以用来直接操作 DOM。
    //binding:一个对象,包含以下属性:
        //name:指令名,不包括 v- 前缀。
        //value:指令的绑定值,例如:`v-test="1+1"中,绑定值为 2。
        //oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。
        //expression:字符串形式的指令表达式。例如 v-test="1 + 1" 中,表达式为 "1 + 1"。
        //arg:传给指令的参数,可选。例如 v-test:foo 中,参数为 `"foo"`。
        //modifiers:一个包含修饰符的对象。
    //vnode:Vue 编译生成的虚拟节点。可以用于值的绑定
    //oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。

3. 案例

  • 新建 directive.js

    Vue.directive('file', {
        //el就是指令所绑定的元素,可以用来直接操作 DOM。
        //
        bind: function (el, binding, vnode) {
            el.innerHTML = '<input type="text">' +
                '            <i>' +
                '                <input type="button" value="浏览...">' +
                '                <input type="file">' +
                '            </i>';
            let i = el.children[1];
            i.style.position = 'relative';
            i.children[1].style.position = 'absolute';
            i.children[1].style.left = '0';
            i.children[1].style.top = '0';
            i.children[1].style.width = '53px';
            i.children[1].style.opacity = '0';
            i.children[1].onchange = function () {
                if(i.children[1].files != null && i.children[1].files.length > 0){
                    //vnode.context记录当前的上下文,也就是实例对象
                    //binding.expression就是取到v-file="image"中的image
                    //整条语句就是给image变量赋值
                    vnode.context[binding.expression] = i.children[1].files[0]
                    el.children[0].value = i.children[1].files[0].name
                } else {
                    vnode.context[binding.expression] = ''
                    el.children[0].value = ''
                }
            }
        }
    });
  • 引入 directive.js,然后在页面上使用

    <body>
        <div id="app">
            <div v-file="file"></div>
            <input type="button" value="显示选择的文件" @click="showFile">
        </div>
    </body>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript" src="js/directive.js"></script>
    <script type="text/javascript">
        new Vue({
            el: '#app',
            data: {
                file: ''
            },
            methods: {
                showFile: function () {
                    console.log(this.file)
                }
            }
        })
    </script>

六、导出与导入

1. 导出函数

common.js

/**
 * 日期转换为字符串
 * @param date
 * @returns {string}
 */
export function date2Str(date){
    let year = date.getFullYear();
    let month = date.getMonth();
    let day = date.getDate();
    let hour = date.getHours();
    let minute = date.getMinutes();
    let seconds = date.getSeconds();
    return year + "-" + zerofill(month + 1, 2) + "-" + zerofill(day, 2) + " " + zerofill(hour, 2) + ":" + zerofill(minute, 2) + ":" + zerofill(seconds, 2);
}
​
/**
 *  零填充
 * @param value
 * @param length
 * @returns {string}
 */
export function zerofill(value, length) {
    if(value === undefined || value === null || value === ''){
        throw new Error(value + "不能为空")
    } else if(length < 0){
        throw new Error("填充长度length不能小于0:" + length)
    } else if(value.length > length){
        throw new Error(value + "长度大于" + length)
    } else {
        let data = value + "";
        while (data.length < length){
            data = '0' + data
        }
        return data;
    }
}
​
/**
 * 拷贝对象
 * @param o
 * @returns {{}}
 */
export function copyObject(o) {
    if(typeof o === 'object'){
        let data = {};
        Object.keys(o).forEach(key => data[key] = o[key])
        return data;
    } else {
        throw new Error(o + "不是对象");
    }
}

2. 导入函数

<body>
    <div id="app">
        <input type="button" value="显示日期" @click="showDate">
    </div>
</body>
<script type="text/javascript" src="js/vue.js"></script>
<!--注意:这里的type属性的值必须是module,只有在module中才可以进行导入-->
<script type="module">
    //import导入的时候需要使用{}来指定导入的函数名,导入多个函数时函数名之间使用逗号隔开
    //from表示函数的来源,后面接一个字符串地址,必须使用相对路径
    import {date2Str } from './js/common.js'
    new Vue({
        el: '#app',
        methods: {
            showDate: function () {
                console.log(date2Str(new Date()))
            }
        }
    })
</script>

3. 插件导出

file-plugin.js

//export default {} 就是用来定义插件的 {}中定义的是插件的内容,Vue规定,插件必须提供一个install方法
export default {
    //插件安装方法,可以带一个Vue类型参数,还可以带一个option选项参数
    install(Vue) {
        //这里定制的是一个指令插件
        Vue.directive('file', {
            //el就是指令所绑定的元素,可以用来直接操作 DOM。
            //
            bind: function (el, binding, vnode) {
                el.innerHTML = '<input type="text">' +
                    '            <i>' +
                    '                <input type="button" value="浏览...">' +
                    '                <input type="file">' +
                    '            </i>';
                let i = el.children[1];
                i.style.position = 'relative';
                i.children[1].style.position = 'absolute';
                i.children[1].style.left = '0';
                i.children[1].style.top = '0';
                i.children[1].style.width = '53px';
                i.children[1].style.opacity = '0';
                i.children[1].onchange = function () {
                    if(i.children[1].files != null && i.children[1].files.length > 0){
                        //vnode.context记录当前的上下文,也就是实例对象
                        //binding.expression就是取到v-file="image"中的image
                        //整条语句就是给image变量赋值
                        vnode.context[binding.expression] = i.children[1].files[0]
                        el.children[0].value = i.children[1].files[0].name
                    } else {
                        vnode.context[binding.expression] = ''
                        el.children[0].value = ''
                    }
                }
            }
        });
    }
}

4. 插件导入

<body>
    <div id="app">
        <div v-file="file"></div>
        <input type="button" value="显示选择的文件" @click="showFile">
    </div>
</body>
<script type="text/javascript" src="js/vue.js"></script>
<script type="module">
    //由于定义的插件是没有名称的,因此导入的时候可以给该插件命名
    import filePlugin from './js/file-plugin.js'
    //use方法就是用来安装插件的,会调用插件中的install方法
    Vue.use(filePlugin)
    new Vue({
        el: '#app',
        data: {
            file: ''
        },
        methods: {
            showFile: function () {
                console.log(this.file)
            }
        }
    })
</script>

5. 组件的导出

Navigation.js

export  default {
    template: '<ul>' +
        '        <li v-for="title in titles" v-text="title" @click="showTitle(title)"></li>' +
        '    </ul>',
    data(){
        return {
            titles: ["文章","评论","交友"]
        }
    },
    methods: {
        showTitle: function (title) {
            console.log(title)
        }
    }
}

6. 组件的导入

<body>
    <div id="app">
        <!--引用调用的组件-->
        <navigation></navigation>
    </div>
</body>
<script type="text/javascript" src="js/vue.js"></script>
<script type="module">
    //导入定义的组件
    import Navigation from "./component/Navigation.js";
    //组件注册
    Vue.component('Navigation', Navigation)
    new Vue({
        el: '#app'
    })
</script>

七、Vue 路由

路由的整合需要使用到第三方库 vue-router.js

1. 路由导航

<!-- vue-router使用 router-link 组件来导航. 通过传入 to 属性指定链接. <router-link> 默认会被渲染成一个 <a>标签 -->
<router-link to="/">首页</router-link>
<router-link to="/nav">导航</router-link>

2. 路由出口

<!--  vue-router使用 router-view 来表示路由出口,路由匹配到的组件将渲染在这里 -->
<router-view />

3. 路由组件定义

//Navigation.js
export  default {
    name: 'Navigation',
    template: '<ul>' +
    '        <li v-for="title in titles" v-text="title" @click="showTitle(title)"></li>' +
    '    </ul>',
    data(){
        return {
            titles: ["文章","评论","交友"]
        }
    },
    methods: {
        showTitle: function (title) {
            console.log(title)
        }
    }
}
​
//Home.js
export  default {
    name: 'Home',
    template: '<div>' +
    '        这是首页' +
    '    </div>',
    data(){
        return {
​
        }
    },
    methods: {
​
    }
}

4. 路由配置

<body>
    <div id="app">
        <!-- vue-router使用 router-link 组件来导航. 通过传入 to 属性指定链接. <router-link> 默认会被渲染成一个 <a>标签 -->
        <router-link to="/">首页</router-link>
        <router-link to="/nav">导航</router-link>
        <!-- 路由出口,路由匹配到的组件将渲染在这里 -->
        <router-view />
    </div>
</body>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript" src="js/vue-router.js"></script>
<script type="module">
    import Home from './component/Home.js'
    import Navigation from './component/Navigation.js'
​
    //创建 router 实例,里面包含一个 routes 配置数组
    let router = new VueRouter({
        //定义路由,每个路由应该映射一个组件
        routes: [{
            path: '/',
            component: Home
        },{
            path: '/nav',
            component: Navigation
        }]
    });
​
    //Vue实例的选项中配置路由
    new Vue({
        router: router
    }).$mount("#app") //Vue实例挂载在#app的元素上
</script>

5. 命名路由

//创建 router 实例,里面包含一个 routes 配置数组
let router = new VueRouter({
    //定义路由,每个路由应该映射一个组件
    routes: [{
        path: '/',
        name: 'Home', //路由的名称
        component: Home
    },{
        path: '/nav',
        name: 'Navigation', //路由的名称
        component: Navigation
    }]
});
<!-- 使用v-bind:[属性] 绑定当前使用的路由,绑定时根据路由的名称进行绑定 -->
<router-link :to="{name: 'Home'}">首页</router-link>
<router-link :to="{name: 'Navigation'}">导航</router-link>

6. 路由重定向

Login.js

export default {
    name: 'Login',
    template: '<div>\n' +
    '            <div>\n' +
    '                <input type="text" v-model="user.username">\n' +
    '            </div>\n' +
    '            <div>\n' +
    '                <input type="text" v-model="user.password">\n' +
    '            </div>\n' +
    '            <div>\n' +
    '                <input type="button" value="登录" @click="login">\n' +
    '            </div>\n' +
    '        </div>',
    data(){
        return {
            user: {
                username: '',
                password: ''
            }
        }
    },
    methods: {
        login: function () {
            console.log(this.user)
        }
    }
}
import Home from './component/Home.js'
import Login from './component/Login.js'
import Navigation from './component/Navigation.js'
​
//创建 router 实例,里面包含一个 routes 配置数组
let router = new VueRouter({
    //定义路由,每个路由应该映射一个组件
    routes: [{
        path: '/',
        redirect: '/login',//重定向,只要使用当前路由,就会重定向到/login
        name: 'Home', //路由的名称
        component: Home
    },{
        path: '/login',
        name: 'Login', //路由的名称
        component: Login
    },{
        path: '/nav',
        name: 'Navigation', //路由的名称
        component: Navigation
    }]
});

7. 路由守卫

  • 全局前置守卫

    //创建 router 实例,里面包含一个 routes 配置数组
    let router = new VueRouter({
        //定义路由,每个路由应该映射一个组件
        routes: [{
            path: '/',
            redirect: '/login',
            name: 'Home', //路由的名称
            component: Home
        },{
            path: '/login',
            name: 'Login', //路由的名称
            component: Login
        },{
            path: '/nav',
            name: 'Navigation', //路由的名称
            component: Navigation
        }]
    });
    //全局前置守卫
    //to: 即将要进入的目标路由对象
    //from: 当前导航正要离开的路由对象
    //next: 一定要调用该方法,否则,路由将不会跳转。执行效果依赖 next 方法的调用参数。
    //next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
    //next(false): 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL //地址会重置到 `from` 路由对应的地址。
    //next('/') 或者 next({path: '/'}): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。
    //next(error): 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递
    //给router.onError() 注册过的回调。
    router.beforeEach((to, from, next) => {
        console.log("路由准备从" + from.path + "跳转到" + to.path)
        next()
    })

8.路由元信息

//创建 router 实例,里面包含一个 routes 配置数组
let router = new VueRouter({
    //定义路由,每个路由应该映射一个组件
    routes: [{
        path: '/',
        redirect: '/login',
        name: 'Home', //路由的名称
        component: Home,
        meta: {//路由元信息
            name: '首页',
            keepAlive: true
        }
    },{
        path: '/login',
        name: 'Login', //路由的名称
        component: Login,
        meta: {//路由元信息
            name: '登录',
            keepAlive: true
        }
    },{
        path: '/nav',
        name: 'Navigation', //路由的名称
        component: Navigation,
        meta: {//路由元信息
            name: '导航',
            keepAlive: true
        }
    }]
});

9. 路由懒加载

//创建 router 实例,里面包含一个 routes 配置数组
    let router = new VueRouter({
        //定义路由,每个路由应该映射一个组件
        routes: [{
            path: '/',
            redirect: '/login',
            name: 'Home', //路由的名称
            component: function () {//组件用到时,调用函数获取组件,这种方式称为懒加载
                return import('./component/Home.js')
            },
            meta: {//路由元信息
                name: '首页',
                keepAlive: true
            }
        },{
            path: '/login',
            name: 'Login', //路由的名称
            component: function () {//组件用到时,调用函数获取组件,这种方式称为懒加载
                return import('./component/Login.js')
            },
            meta: {//路由元信息
                name: '登录',
                keepAlive: true
            }
        },{
            path: '/nav',
            name: 'Navigation', //路由的名称
            component: function () {//组件用到时,调用函数获取组件,这种方式称为懒加载
                return import('./component/Login.js')
            },
            meta: {//路由元信息
                name: '导航',
                keepAlive: true
            }
        }]
    });
//创建 router 实例,里面包含一个 routes 配置数组
let router = new VueRouter({
    //定义路由,每个路由应该映射一个组件
    routes: [{
        path: '/',
        redirect: '/login',
        name: 'Home', //路由的名称
        component: () => import('./component/Home.js'), //箭头函数,相当于Java中lambda表达式
        meta: {//路由元信息
            name: '首页',
            keepAlive: true
        }
    },{
        path: '/login',
        name: 'Login', //路由的名称
        component: () => import('./component/Login.js'),//箭头函数,相当于Java中lambda表达式
        meta: {//路由元信息
            name: '登录',
            keepAlive: true
        }
    },{
        path: '/nav',
        name: 'Navigation', //路由的名称
        component: () => import('./component/Navigation.js'),//箭头函数,相当于Java中lambda表达式
        meta: {//路由元信息
            name: '导航',
            keepAlive: true
        }
    }]
});

10. 嵌套路由

  • 创建管理页面组件Manage.js

    export default {
        name: 'Manage',
        template: '<div class="main-container">\n' +
        '            <aside>\n' +
        '                <router-link v-for="m in menus" :to="{path: m.routePath}">\n' +
        '                    <div v-text="m.name"></div>\n' +
        '                </router-link>\n' +
        '            </aside>\n' +
        '            <main>\n' +
        '                <header>头部信息</header>\n' +
        '                <section>\n' +
        '                    <nav>导航条</nav>\n' +
        '                    <article>\n' +
        '                        <router-view />\n' +
        '                    </article>\n' +
        '                    <footer>页脚</footer>\n' +
        '                </section>\n' +
        '            </main>\n' +
        '        </div>',
        data(){
            return {
                menus: [{
                    id: 1,
                    name: '用户管理',
                    routePath: '/user'
                },{
                    id: 2,
                    name: '角色管理',
                    routePath: '/role'
                }]
            }
        },
        methods: {
    ​
        }
    }
  • 创建二级路由组件 User.js

    export default {
        name: 'User',
        template: '<div>用户界面</div>'
    }
  • 创建二级路由组件 Role.js

    export default {
        name: 'Role',
        template: '<div>角色界面</div>'
    }
  • 二级路由配置

    //创建 router 实例,里面包含一个 routes 配置数组
    let router = new VueRouter({
        //定义路由,每个路由应该映射一个组件
        routes: [{
            path: '/',
            redirect: '/login',
            name: 'Home'//路由的名称
        },{
            path: '/login',
            name: 'Login', //路由的名称
            component: () => import('./component/Login.js'),//箭头函数,相当于Java中lambda表达式
            meta: {//路由元信息
                name: '登录',
                keepAlive: true
            }
        },{
            path: '/manage',
            name: 'Manage', //路由的名称
            component: () => import('./component/Manage.js'),//箭头函数,相当于Java中lambda表达式
            meta: {//路由元信息
                name: '导航',
                keepAlive: true
            },
            children: [{//子路由
                path: '/user',
                name: 'User',
                component: () => import('./component/User.js'),
                meta: {//路由元信息
                    name: '用户管理',
                    keepAlive: true
                },
            },{
                path: '/role',
                name: 'Role',
                component: () => import('./component/Role.js'),
                meta: {//路由元信息
                    name: '角色管理',
                    keepAlive: true
                },
            }]
        }]
    });
  • 创建页面 css 样式 index.css

    html,body, #app, .main-container{
        width: 100%;
        height: 100%;
        margin: 0;
        padding: 0;
        overflow: hidden;
    }
    ​
    .main-container{
        display: flex;
        flex-direction: row;
    }
    ​
    aside{
        width: 200px;
        border-right: 1px solid #ddd;
    }
    main{
        flex-grow: 1.5;
        flex-shrink: 0.5;
        display: flex;
        flex-direction: column;
    }
    ​
    header, nav{
        height: 40px;
        border-bottom: 1px solid #ddd;
    }
    footer{
        height: 40px;
        border-top: 1px solid #ddd;
    }
    ​
    section{
        flex-grow: 1.5;
        flex-shrink: 0.5;
        display: flex;
        flex-direction: column;
    }
    ​
    article{
        flex-grow: 1.5;
        flex-shrink: 0.5;
    }
  • 整体引入

    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title>Vue入门</title>
            <link rel="stylesheet" type="text/css" href="css/index.css">
        </head>
        <body>
            <div id="app">
                <router-view />
            </div>
        </body>
        <script type="text/javascript" src="js/vue.js"></script>
        <script type="text/javascript" src="js/vue-router.js"></script>
        <script type="module">
            //创建 router 实例,里面包含一个 routes 配置数组
            let router = new VueRouter({
                //定义路由,每个路由应该映射一个组件
                routes: [{
                    path: '/',
                    redirect: '/login',
                    name: 'Home'//路由的名称
                },{
                    path: '/login',
                    name: 'Login', //路由的名称
                    component: () => import('./component/Login.js'),//箭头函数,相当于Java中lambda表达式
                    meta: {//路由元信息
                        name: '登录',
                        keepAlive: true
                    }
                },{
                    path: '/manage',
                    name: 'Manage', //路由的名称
                    component: () => import('./component/Manage.js'),//箭头函数,相当于Java中lambda表达式
                    meta: {//路由元信息
                        name: '导航',
                        keepAlive: true
                    },
                    children: [{
                        path: '/user',
                        name: 'User',
                        component: () => import('./component/User.js'),
                        meta: {//路由元信息
                            name: '用户管理',
                            keepAlive: true
                        },
                    },{
                        path: '/role',
                        name: 'Role',
                        component: () => import('./component/Role.js'),
                        meta: {//路由元信息
                            name: '角色管理',
                            keepAlive: true
                        },
                    }]
                }]
            });
            //全局前置守卫
            router.beforeEach((to, from, next) => {
                console.log("路由准备从" + from.path + "跳转到" + to.path)
                next()
            })
            //Vue实例的选项中配置路由
            new Vue({
                router: router
            }).$mount("#app")//Vue实例挂载在#app的元素上
        </script>
    </html>

八、脚手架搭建

九、Element UI

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值