vue学习-day04(路由)

一世执手 提交于 2019-12-30 14:18:28

目录

    1.组件传值-父组件向子组件传值和data与props的区别
    2.组件传值-子组件通过事件调用向父组件传值        
    3.案例:发表评论。使用ref获取DOM元素和组件引用
    4.路由-前端路由和后端路由的概念
    5.路由-vue-router的基本使用
    6.路由-路由redirect重定向的使用
    7.路由-设置选中路由高亮的两种方式
    8.路由-为路由切换启动动画
    9.路由传参-使用query方式传递参数
    10.路由传参-使用params方式传递路由参数
    11.路由-使用children属性实现路由嵌套
    12.路由-使用命名视图实现经典布局

 

1.组件传值-父组件向子组件传值和data与props的区别    <--返回目录

  父组件向子组件传值

<!DOCTYPE html>
<html>
<head>
    <title>标题</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <!-- 导入vue的包 -->
    <script type="text/javascript" src="vue2.js"></script>
    <style type="text/css">
        div {
            background-color: #ccc;
        }
        /*自定义样式,来控制元素动画样式*/
        .my-enter, .my-leave-to {
            opacity: 0;
            transform:translateX(150px);
        }
        .my-enter-active,  /*入场动画的时间段*/
        .my-leave-active {  /*离场动画的时间段*/
            transition: all 0.4s ease;
        }
    </style>
</head>
<body>
    <div id="app">
        <a href="" @click.prevent="comName='com1'">组件1</a>
        <a href="" @click.prevent="comName='com2'">组件2</a>
        <!-- 通过mode属性,设置组件切换时的模式,out-in表示上一个组件离场动画后,新组件才开始入场动画-->
        <transition name="my" mode="out-in">
            <!-- 父组件,可以在引用子组件的时候,通过属性绑定的形式,传递数据
            注意:定义属性名称全部小写 -->
            <!-- [Vue tip]: Prop "parentmsg" is passed to component <Anonymous>, 
            but the declared prop name is "parentMsg". Note that HTML attributes 
            are case-insensitive and camelCased props need to use their kebab-case 
            equivalents when using in-DOM templates. You should probably use 
            "parent-msg" instead of "parentMsg". -->
            <component :is="comName" :parentmsg="msg" @parentshow="show"></component>
        </transition>
    </div>

    <script type="text/javascript">  
        //创建一个vue实例
        var vm = new Vue({
            el: '#app',
            data: {
                comName: 'com1',
                msg: "父组件的msg"
            },
            methods: {
                show() {
                    console.log("调用了父组件的show方法");
                }
            },
            components: {
                com1: {
                    template: '<h1 @click="mymethod">这是子组件1----{{parentmsg}}</h1>',
                    //把父组件传递过来的parentMsg属性,在props数组中定义,这样才能使用该属性
                    props: ['parentmsg'],
                    methods: {
                        mymethod() {
                            this.$emit('parentshow');
                        }
                    }
                },
                com2: {
                    template: '<h1>这是子组件2</h1>'
                }
            }    
        });
    </script>
</body>
</html>

 

  data与props的区别:

    1)子组件中所有props中的数据,都是通过父组件传递给子组件的。数据只是可读
    2)子组件data中的数据是自身私有的,数据可读可写


2.组件传值-子组件通过事件调用向父组件传值    <--返回目录

<!DOCTYPE html>
<html>
<head>
    <title>标题</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <!-- 导入vue的包 -->
    <script type="text/javascript" src="vue2.js"></script>
    <style type="text/css">
        div {
            background-color: #ccc;
        }
        /*自定义样式,来控制元素动画样式*/
        .my-enter, .my-leave-to {
            opacity: 0;
            transform:translateX(150px);
        }
        .my-enter-active,  /*入场动画的时间段*/
        .my-leave-active {  /*离场动画的时间段*/
            transition: all 0.4s ease;
        }
    </style>
</head>
<body>
    <div id="app">
        <a href="" @click.prevent="comName='com1'">组件1</a>
        <a href="" @click.prevent="comName='com2'">组件2</a>
        <!-- 通过mode属性,设置组件切换时的模式,out-in表示上一个组件离场动画后,新组件才开始入场动画-->
        <transition name="my" mode="out-in">
            <!-- 父组件,可以在引用子组件的时候,通过属性绑定的形式,传递数据
            注意:定义属性名称全部小写 -->
            <!-- [Vue tip]: Prop "parentmsg" is passed to component <Anonymous>, 
            but the declared prop name is "parentMsg". Note that HTML attributes 
            are case-insensitive and camelCased props need to use their kebab-case 
            equivalents when using in-DOM templates. You should probably use "parent-msg" instead of "parentMsg". -->
            <component :is="comName" :parentmsg="msg" @parentshow="show"></component>
        </transition>
        <br/>
        <h1>{{msg}}</h1>
    </div>

    <script type="text/javascript">  
        //创建一个vue实例
        var vm = new Vue({
            el: '#app',
            data: {
                comName: 'com1',
                msg: "父组件的msg"
            },
            methods: {
                show(data) {
                    console.log("调用了父组件的show方法---" + data );
                    this.msg = data;
                }
            },
            components: {
                com1: {
                    template: '<h1 @click="mymethod">这是子组件1----{{parentmsg}}</h1>',
                    data: function(){
                        return {
                            sonmsg: '子组件的msg'
                        }
                    },
                    //把父组件传递过来的parentMsg属性,在props数组中定义,这样才能使用该属性
                    props: ['parentmsg'],
                    methods: {
                        mymethod() {
                            this.$emit('parentshow', this.sonmsg);//调用父组件传递过来的方法
                        }
                    }
                },
                com2: {
                    template: '<h1>这是子组件2</h1>'
                }
            }    
        });
    </script>
</body>
</html>


3.案例:发表评论。使用ref获取DOM元素和组件引用    <--返回目录

  案例:添加评论部分是子组件;父组件对所有评论进行列表展示。评论保存在本地存储localStorage

<!DOCTYPE html>
<html>
<head>
    <title>标题</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <!-- 导入vue的包 -->
    <script type="text/javascript" src="vue2.js"></script>    <link rel="stylesheet" type="text/css" href="bootstrap.min.css">
</head>
<body>
    <div id="app">
        <com1></com1>
        <div class="container">
            <ul class="list-group">
                <li class="list-group-item" v-for="item in list" :key="item.id">
                    <span class="badge">{{item.user}}</span>
                    {{item.comments}}
                </li>
            </ul>
        </div>
    </div>

    <template id="temp1">
        <div class="container">
            <div class="row">
                <div class="col-md-3"></div>
                <div class="col-md-6">
                    <form>
                        <div class="form-group">
                            <label for="user">用户名</label>
                            <input type="text" name="user" placeholder="输入用户名" class="form-control" v-model="user">
                        </div>
                        <div class="form-group">
                            <label for="comments">评论</label>
                            <input type="text" name="comments" placeholder="输入评论" class="form-control" v-model="comments">
                        </div>
                        <button class="btn btn-primary" @click="postCommets">发表评论</button>
                    </form>
                </div><!-- /.col-md-6 -->
            </div><!-- /.row -->
        </div><!-- /.container -->
    </template>

    <script type="text/javascript">  
        //创建一个vue实例
        var vm = new Vue({
            el: '#app',
            data: {
                list: []
            },
            methods: {
                loadComments() {
                    var list = JSON.parse(localStorage.getItem("cmts") || '[]');
                    this.list = list;
                }
            },
            created() {
                this.loadComments();
            },
            components: {
                com1: {
                    template: '#temp1',
                    data(){
                        return {
                            user: '',
                            comments: ''
                        }
                    },
                    methods: {
                        postCommets() {
                            var obj = {id:Date.now(), user: this.user, comments: this.comments};
                            var list = JSON.parse(localStorage.getItem("cmts") || '[]');
                            list.unshift(obj);
                            localStorage.setItem("cmts", JSON.stringify(list));
                            this.user = '';
                            this.comments = '';
                        }
                    }
                }
            }    
        });
    </script>
</body>
</html>

  

  // 问题1:我这个案例里面不需要将父组件的loadComments()方法传递给子组件;点击发表按钮后,评论列表自动更新。
  // 问题2:我没有手动给输入框注册enter键盘事件,但是也有这个功能,猜测是bootstrap本身自带的。

 

  使用ref获取DOM元素和组件引用

// vue获取dom元素
<!DOCTYPE html>
<html>
<head>
    <title>vue获取dom元素</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <!-- 导入vue的包 -->
    <script type="text/javascript" src="vue2.js"></script>
</head>
<body>
    <div id="app">
        <input type="button" value="获取h3标签里面的文本" @click="getEle">
        <h3 ref="h3Ele">这是一个h3标签</h3>
    </div>

    <script type="text/javascript">  
        //创建一个vue实例
        var vm = new Vue({
            el: '#app',
            data: {
            },
            methods: {
                getEle() {
                    // this.$refs.h3Ele:得到一个原生DOM对象
                    alert(this.$refs.h3Ele.innerText);
                }
            }
        });
    </script>
</body>
</html>

// vue获取子组件
<!DOCTYPE html>
<html>
<head>
    <title>vue获取dom元素</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <!-- 导入vue的包 -->
    <script type="text/javascript" src="vue2.js"></script>
    <!-- <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> -->
</head>
<body>
    <div id="app">
        <input type="button" value="获取h3标签里面的文本" @click="getEle">
        <com1 ref="com1ref"></com1>
    </div>

    <script type="text/javascript">  
        //创建一个vue实例
        var vm = new Vue({
            el: '#app',
            data: {
            },
            methods: {
                getEle() {
                    console.log(this.$refs.com1ref.sonmsg);
                    this.$refs.com1ref.show();
                }
            },
            components: {
                com1: {
                    template: '<div></div>',
                    data() {
                        return {
                            sonmsg: '子组件的msg'
                        }
                    },
                    methods: {
                        show() {
                            console.log("调用子组件的show方法:" + this.sonmsg);
                        }
                    }
                }
            }
        });
    </script>
</body>
</html>


4.路由-前端路由和后端路由的概念    <--返回目录

    * 后端路由:对于普通的网站,所有的超链接都是URL地址,所有的URL地址都对应服务器上的资源
    * 前端路由:对应单页面应用程序来说,主要通过URL中的hash(#号)来实现不同页面之间的切换,
      同时,hash有一个特点:HTTP请求中不会包含hash相关的内容。所以,单页面程序中页面跳转主要用hash实现
    * 在单页面应用程序中,这种通过hash改变类切换页面的方式,称做前端路由
    * 路由:在URL中采用#号来作为当前视图的地址,改变#号后的参数,页面并不会重载。
    * 单页Web应用(single page web application,SPA),就是只有一张Web页面的应用,
      是加载单个HTML 页面并在用户与应用程序交互时动态更新该页面的Web应用程序。


5.路由-vue-router的基本使用    <--返回目录

<!DOCTYPE html>
<html>
<head>
    <title>vue获取dom元素</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <!-- 导入vue.js -->
    <script type="text/javascript" src="vue2.js"></script>
    <!-- 安装 vue-router 路由模块 -->
    <script type="text/javascript" src="vue-router.js"></script>
</head>
<body>
    <div id="app">
        <h1>Hello App!</h1>
        <p>
        <!-- 使用 router-link 组件来导航. -->
        <!-- 通过传入 `to` 属性指定链接. -->
        <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
        <router-link to="/login">Go to login</router-link>
        <router-link to="/register">Go to register</router-link>
        <!-- 下面的方式也可以,但是不推荐注意使用 -->
        <a href="#/login">登录</a>
        <a href="#/register">注册</a>
        </p>
        <!-- 路由出口 -->
        <!-- 路由匹配到的组件将渲染在这里 -->
        <router-view></router-view>
    </div>

    <script type="text/javascript"> 
        // 组件的模板对象
        var login = {
            template: '<h1>登录组件</h1>'
        };
        var register = {
            template: '<h1>注册组件</h1>'
        };

        // 创建一个路由对象
        var routerObj = new VueRouter({
            routes: [  // 路由匹配规则
                {path: '/login', component: login},
                {path: '/register', component: register}
            ]
        });

        // 创建一个vue实例
        var vm = new Vue({
            el: '#app',
            data: {      
            },
            methods: { 
            },
            //将路由规则对象,注册到vm实例上,用来监听URL地址的变化,然后展示对应的组件
            router: routerObj  
        });
    </script>
</body>
</html>    


6.路由-路由redirect重定向的使用    <--返回目录

routes: [  // 路由匹配规则
            {path: '/', redirect: '/login'},
            {path: '/login', component: login},
            {path: '/register', component: register}
        ]


7.路由-设置选中路由高亮的两种方式    <--返回目录

  // 第一种方式

<style type="text/css">
    .router-link-active { // vue-router默认的
        color: red;
        background-color: #ccc;
    }
</style>

  // 设置链接激活时使用的CSS类名。默认值可以通过路由的构造选项linkActiveClass来全局配置。

var routerObj = new VueRouter({
    routes: [  // 路由匹配规则
        {path: '/', redirect: '/login'},
        {path: '/login', component: login},
        {path: '/register', component: register}
    ],
    linkActiveClass: 'myActive'
});

/*修改链接激活使用的CSS类名:myActive*/
.myActive {
    color: #fff;
    background-color: #ff3300;
}


8.路由-为路由切换启动动画    <--返回目录

/*自定义样式,来控制元素动画样式*/
.my-enter, .my-leave-to {
    opacity: 0;
    transform:translateX(150px);
}
.my-enter-active,  /*入场动画的时间段*/
.my-leave-active {  /*离场动画的时间段*/
    transition: all 0.4s ease;
}

<!-- 路由匹配到的组件将渲染在这里 -->
<transition mode="out-in" name="my">
    <router-view></router-view>
</transition>    


9.路由传参-使用query方式传递参数    <--返回目录

<router-link to="/login?id=10">Go to login</router-link>

var login = {
    template: '<h1>登录组件---{{$route.query.id}}</h1>'
};


10.路由传参-使用params方式传递路由参数    <--返回目录

<router-link to="/register/20">Go to register</router-link>

var register = {
    template: '<h1>注册组件---{{$route.params.id}}</h1>'
};

// 创建一个路由对象
var routerObj = new VueRouter({
    routes: [  // 路由匹配规则
        {path: '/', redirect: '/login'},
        {path: '/login', component: login},
        {path: '/register/:id', component: register}
    ],
    linkActiveClass: 'myActive'
});


11.路由-使用children属性实现路由嵌套    <--返回目录

<!DOCTYPE html>
<html>
<head>
    <title>使用children属性实现路由嵌套</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <!-- 导入vue.js -->
    <script type="text/javascript" src="vue2.js"></script>
    <!-- 安装 vue-router 路由模块 -->
    <script type="text/javascript" src="vue-router.js"></script>
    <style type="text/css">
        /*链接激活默认使用的CSS类名:router-link-active*/
        .router-link-active {
            color: red;
            background-color: #ccc;
        }
        /*修改链接激活使用的CSS类名:myActive*/
        .myActive {
            color: #fff;
            background-color: #ff3300;
        }
        /*自定义样式,来控制元素动画样式*/
        .my-enter, .my-leave-to {
            opacity: 0;
            transform:translateX(150px);
        }
        .my-enter-active,  /*入场动画的时间段*/
        .my-leave-active {  /*离场动画的时间段*/
            transition: all 0.4s ease;
        }

        .parent {
            border:1px dashed #000;
            width: 300px;
            height: 500px;
        }
    </style>
</head>
<body>
    <div id="app">
        <h1>Hello App!</h1>
        <p>
        <!-- 使用 router-link 组件来导航. -->
        <!-- 通过传入 `to` 属性指定链接. -->
        <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
        <router-link to="/account">go to account</router-link>
        </p>
        
        <!-- 路由出口,路由匹配到的组件将渲染在这里 -->
        <transition mode="out-in" name="my">
            <router-view class="parent"></router-view><!-- 给父组件留的坑 -->
        </transition>
    </div>

    <template id="temp">
        <div>
            <h2>account--父组件</h2>
            <router-link to="/account/login">登陆</router-link>
            <router-link to="/account/register">注册</router-link>
            <router-view></router-view><!-- 给子组件留的坑 -->
        </div>
    </template>

    <script type="text/javascript"> 
        // 组件的模板对象
        var account = {
            template: '#temp'
        };
        var login = {
            template: '<h1>login组件</h1>'
        };
        var register = {
            template: '<h1>register组件</h1>'
        };

        // 创建一个路由对象
        var routerObj = new VueRouter({
            routes: [  // 路由匹配规则
                //{path: '/', redirect: '/account'},
                {path: '/account', component: account, children: [
                    {path: 'login', component: login},
                    {path: 'register', component: register}
                ]}
            ],
            linkActiveClass: 'myActive',        
        });

        // 创建一个vue实例
        var vm = new Vue({
            el: '#app',
            data: {    
            },
            methods: {
            },
            //将路由规则对象,注册到vm实例上,用来监听URL地址的变化,然后展示对应的组件
            router: routerObj  
        });
    </script>
</body>
</html>


12.路由-使用命名视图实现经典布局    <--返回目录

<!DOCTYPE html>
<html>
<head>
    <title>使用命名视图实现经典布局</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <!-- 导入vue.js -->
    <script type="text/javascript" src="vue2.js"></script>
    <!-- 安装 vue-router 路由模块 -->
    <script type="text/javascript" src="vue-router.js"></script>
    <style type="text/css">
        .header {
            background-color: #abc;
            height: 80px;
        }
        .container {
            display: flex;
            height: 600px;
        }
        .left {
            flex: 2;
            background-color: #ccc;
        }
        .main {
            flex: 8;
            background-color: blue;
        }
        body {
            margin: 0;
            padding: 0;
        }
        h1 {
            margin: 0;
            padding: 0;
            font-size: 16px;
        }
    </style>
</head>
<body>
    <div id="app">
        <!-- 路由出口,路由匹配到的组件将渲染在这里 -->
        <router-view class="header"></router-view>
        <div class="container">
            <router-view name="left" class="left"></router-view>
            <router-view name="main" class="main"></router-view>
        </div>
    </div>

    <script type="text/javascript"> 
        // 组件的模板对象
        var header = {
            template: '<h1>header组件</h1>'
        };
        var left = {
            template: '<h1>left组件</h1>'
        };
        var main = {
            template: '<h1>main组件</h1>'
        };

        // 创建一个路由对象
        var routerObj = new VueRouter({
            routes: [  // 路由匹配规则
                {path: '/', components: {
                    'default': header,
                    'left': left,
                    'main': main
                }}
            ]        
        });

        // 创建一个vue实例
        var vm = new Vue({
            el: '#app',
            data: {    
            },
            methods: {
            },
            //将路由规则对象,注册到vm实例上,用来监听URL地址的变化,然后展示对应的组件
            router: routerObj  
        });
    </script>
</body>
</html>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!