Veujs从入门到应用(三)之vue组件及vue路由

一、组件

在大型应用开发的时候,页面可以划分成很多部分。往往不同的页面,也会有相同的部分。例如可能会有相同的头部导航。

但是如果每个页面都独自开发,这无疑增加了我们开发的成本。所以我们会把页面的不同部分拆分成独立的组件,然后在不同页面就可以共享这些组件,避免重复开发。

在vue里,所有的vue实例都是组件

全局组件

Vue.component("",{
template:"",
data:""
});

我们用Vue.component();,来定义一个全局组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
<loltoulan></loltoulan><br><br>
<loltoulan></loltoulan><br><br>
<loltoulan></loltoulan><br><br>
<loltoulan></loltoulan><br><br>

</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
    Vue.component("loltoulan",{
        template:"<button v-on:click='add' @click.right.prevent='num--'>你点了我 {{ num }} 次,我记住了.</button>",
        data(){
            return{
                num:0
            }
        },
        methods:{
            add:function () {
                this.num++;
            }
        }
    });
   const model=new Vue({
        el: "#app"
    });
</script>
</body>
</html>

效果:
在这里插入图片描述

  • 组件其实也是一个Vue实例,因此它在定义时也会接收:data、methods、生命周期函数等
  • 不同的是组件不会与页面的元素绑定,否则就无法复用了,因此没有el属性。
  • 但是组件渲染需要html模板,所以增加了template属性,值就是HTML模板
  • 全局组件定义完毕,任何vue实例都可以直接在HTML中通过组件名称来使用组件了。
  • data必须是一个函数,不再是一个对象。
  • 必须有根,也就是必须有 const model= new Vue({el: “#app”})

在上面的案例中我们发现:虽然公用的是同一个num,但是各个组件之中的值却没有发生关联,这就是因为,在Vue.component();中data属性的值是一个函数,而不是一个对象,因为如果是一个对象的话,因为我们操作的都是同一个对象,就像v-model中双向绑定那样,具有同样的值,而函数则不一样,函数会再执行结束后立即释放,不会存在引用的问题。

局部组件

//定义我们的局部组件
const hello={};
const model=new Vue({ components:{ key: value}});
其key就是子组件名称
其value就是组件对象名
效果与刚才的全局注册是类似的,不同的是,这个counter组件只能在当前的Vue实例中使用

局部组件和全局组件不同的是,局部组件需要在Vue实例中进行注册,而且与全局组件不同的是,局部组件的创建方法,业务和全局组件不同

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <loltoulan></loltoulan><br><br>
    <loltoulan></loltoulan><br><br>
    <loltoulan></loltoulan><br><br>
    <loltoulan></loltoulan><br><br>

</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
    //定义我们的局部组件  
   const hello={
        template:"<button v-on:click='add' @click.right.prevent='num--'>你点了我 {{ num }} 次,我记住了.</button>",
        data(){
            return{
                num:0
            }
        },
        methods:{
            add:function () {
                this.num++;
            }
        }
    };
    const model=new Vue({
        el: "#app",
        components:{
            //在component中注册我们测局部组件
            loltoulan : hello
        }
    });
</script>
</body>
</html>

在这里插入图片描述

组件通信

在这里插入图片描述

  • 页面首先分成了顶部导航、左侧内容区、右侧边栏三部分
  • 左侧内容区又分为上下两个组件
  • 右侧边栏中又包含了3个子组件

各个组件之间以嵌套的关系组合在一起,那么这个时候不可避免的会有组件间通信的需求。

父向子通讯

就比如说我们在csdn的写作业面中,我们需要发布文章,我们点击发布文章之后会弹出
在这里插入图片描述
这样一张图,他有可能就会有一些向弹窗传递值的情况,这就是组件通讯。
在vue中组件通讯的方式如下:
局部组件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <toulan v-bind:name1="name" v-bind:num="num"></toulan>

</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
    //定义我们的局部组件
    const hello={
        template:"<button v-on:click='num++' @click.right.prevent='num--' >" +
            "你点了{{name1}}共{{ num }} 次,我记住你了.</button>",

        props:{
            name1:{
                type:String,

                required:true
            },
            num: {
                type:Number,
                default:0,
                required: true
            }
        }
    };
    const model=new Vue({
        el: "#app",
        data :{
            name:"Jacobshash",
            num:0
        },
        components:{
            //在component中注册我们测局部组件
            toulan : hello
        }
    });
</script>
</body>
</html>

在这里插入图片描述
全局组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
<!--    此处的num仅仅只是为了父向子赋值所用-->
<loltoulan v-bind:number="num"></loltoulan>

</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
    Vue.component("loltoulan",{
        template:"<button v-on:click='add' @click.right.prevent='number--'>你点了我 {{ number }} 次,我记住了.</button>",

        methods:{
            add:function () {
                this.number++;
            }
        },
        props:["number"]
    });
   const model=new Vue({
        el: "#app",
       data:{
            num:10
       }
    });
</script>
</body>
</html>

在这里插入图片描述

子向父通讯:

子组件接收到父组件属性后,默认是不允许修改的。怎么办?
既然只有父组件能修改,那么加和减的操作一定是放在父组件:
但是,点击按钮是在子组件中,那就是说需要子组件来调用父组件的函数,怎么做?
我们可以通过v-on指令将父组件的函数绑定到子组件上:
在子组件中定义函数,函数的具体实现调用父组件的实现,并在子组件中调用这些函数。当子组件中按钮被点击时,调用绑定的函数:vue提供了一个内置的this.$emit()函数,用来调用父组件绑定的函数

子组件中的事件只能调用子里面的方法,父里面的事件只能调用父里面的方法

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <h2>num: {{num}}</h2>
    <!--自定义事件-->
    <counter :count="num" @inc="increment" @dec="decrement"></counter>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript">
    Vue.component("counter", {
    //调用方法
        template: '\
                <div>\
                    <button @click="plus">加</button>  \
                    <button @click="reduce">减</button>  \
                </div>',
        props: ['count'],
        methods: {
       
            plus() {
            //通过调用特定方法,来进行父子组件的联系
                this.$emit("inc");
            },
            reduce() {
            
                this.$emit("dec");
            }
        }
    });
    var app = new Vue({
        el:"#app",
        data:{
        //初始化num
            num:0
        },
        // 父组件中定义操作num的方法,因为字中做出改变,默认是不能传递给父的
        methods:{ 
            increment(){
                this.num++;
            },
            decrement(){
                this.num--;
            }
        }
    })
</script>
</body>
</html>

在这里插入图片描述

二、路由

可以通过不同的按钮实现不同的页面,而不刷新页面和地址栏

示例如下:
在这里插入图片描述
接下来,我们要做出相似的案例:

Veujs从入门到应用(一)中的npm安装方法一样

首先,我们需要安装路由插件,如果我们是通过npm安装的,那么,我们就直接在
在这里插入图片描述
或者在创建工程的文件夹下,打开cmd窗口,输入命令

npm install vue-router --save

在这里插入图片描述
我们的文件夹下多了一个文件夹,如下:
在这里插入图片描述
安装成功之后,我们就开始

当然,我们这部分也是基于组件开发的,所以,我们可以通过,组件来进行创建

代码如下:

//因为我们这个组件的复用性不是很高,所以我们建议使用局部组件
//因为考虑到我们的登陆注册页面是比较宽广的,所以我们使用这种方式来编写模板页面
//值得注意的是,一个template中只能有一个根标签,也就是,一个同一级的标签
const loginForm = {
    template: `
  <div>
    <h1>登录页面</h1>
    用户名:<input  type="text" /><br>
    密&emsp;码:<input type="text" /><br>
    <input type="submit" value="登录">
    <input type="reset" value="重置">
</div>   
  `
};
//因为我们这个组件的复用性不是很高,所以我们建议使用局部组件
//因为考虑到我们的登陆注册页面是比较宽广的,所以我们使用这种方式来编写模板页面
//值得注意的是,一个template中只能有一个根标签,也就是,一个同一级的标签
const registerForm = {
    template: `
  <div>
    <h1>注册页面</h1>
    用&ensp;户&ensp;名:<input  type="text" /><br>
    密&emsp;&emsp;码:<input type="text" /><br>
    确认密码:<input type="text" /><br>
    <input type="submit" value="登录">
    <input type="reset" value="重置">
</div>   
  `
};

然后我们编写index中的代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <span>登录</span>
    <span>注册</span>
    <hr/>
    <div>
        <!--<loginForm></loginForm>-->
        <!--
            疑问:为什么不采用上面的写法?
            由于html是大小写不敏感的,如果采用上面的写法,则被认为是<loginform></loginform>
            所以,如果是驼峰形式的组件,需要把驼峰转化为“-”的形式
         -->
        
        <!--显示组件-->
        <login-form></login-form>
        <register-form></register-form>
    </div>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<!--引入login.js-->
<script src="src/js/login.js"></script>
<!--引入register.js-->
<script src="src/js/register.js"></script>
<script type="text/javascript">
    const vm = new Vue({
        //绑定vue作用域
        el: "#app",
        //注册组件
        components: {
            loginForm:loginForm,
            registerForm:registerForm
        }
    })
</script>
</body>
</html>

这时我们还没有引入路由组件的js文件
效果如下
在这里插入图片描述

我们期待的是,当点击登录或注册按钮,分别显示登录页或注册页,而不是一起显示。
但是,如何才能动态加载组件,实现组件切换呢?
虽然使用原生的Html5和JS也能实现,但是官方推荐我们使用vue-router模块。

让我们引入路由组件之后

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

</head>
<body>
<div id="app">
<!--router-link来指定跳转的路径-->
    <h1><span><router-link to="/login">登录</router-link></span></h1>
    <h1><span><router-link to="/register">注册</router-link></span></h1>
    <hr/>
    <div>
        <!--vue-router的锚点-->
        <router-view></router-view>
    </div>

    <!--<loginForm></loginForm>-->
    <!--
        疑问:为什么不采用上面的写法?
        由于html是大小写不敏感的,如果采用上面的写法,则被认为是<loginform></loginform>
        所以,如果是驼峰形式的组件,需要把驼峰转化为“-”的形式

       npm install vue-router --save
     -->
    <!--<login-form></login-form>
    <register-form></register-form>-->
</div>
<script src="node_modules/vue/dist/vue.min.js"></script>
<script src="node_modules/vue-router/dist/vue-router.js"></script>
<script src="src/js/login.js"></script>
<script src="src/js/register.js"></script>
<script>

    const router = new VueRouter({
        routes: [
            {
                path: "/login",
                component: loginForm
            },{
                path: "/register",
                component: registerForm
            }
        ]
    });

    const app = new Vue({
        el:"#app",
        components:{
            registerForm: registerForm,
            loginForm:loginForm
        },
        router
    })

</script>

</body>
</html>

效果:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值