Vue入门基础2

组件化

开发大型应用的时候,页面往往拆分成为多个部分,这些部件可能会被多个页面使用,所以有必要对这些部件进行组件化。

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

全局组件

通过Vue.component()来定义一个全局组件。

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

使用示例:

<body>
        <div id="app">
            <counter></counter>
            <counter></counter>
            <counter></counter>
        </div>
    </body>
    <script src="node_modules/vue/dist/vue.js"></script>
    <script>
        Vue.component("counter",{
            template:'<button @click="num++">点击次数:{{num}}</button>',
            data(){
                return{
                    num:0
                }
            }
        })
        var app = new Vue({
            el: "#app",
            data: {
                num:0
            },
        })
    </script>

组件复用

在上面的代码中,我们使用全局组件的时候,

        <div id="app">
            <counter></counter>
            <counter></counter>
            <counter></counter>
        </div>

我们点击按钮,发现它们的值相互之间不干涉,为什么呢?
在这里插入图片描述
在定义全局组件的时候,我们是用函数来定义data数据的,因此每个实例可以维护一份被返回对象的独立的拷贝:

 data(){
    return{
        num:0
    }
}

局部组件

一旦全局注册,就意味着即便以后你不再使用这个组件,它依然会随着Vue的加载而加载。因此,对于一些并不频繁使用的组件,我们会采用局部注册。

使用示例:

    <body>
        <div id="app">
            <hello1></hello1>
            <hello1></hello1>
            <hello1></hello1>
        </div>

    </body>
    <script src="node_modules/vue/dist/vue.js"></script>
    <script>
        const hello = {
            template: '<button @click="num++">点击次数:{{num}}</button>',
            data(){
                return{
                    num: 0
                }
            }
        }
        const app = new Vue({
            el: "#app",
            data: {
                num: 0
            },
            components:{
                hello1: hello
            }
        })
    </script>
  • components就是当前vue对象子组件集合。
    • 其key就是子组件名称
    • 其值就是组件对象名
    • hello1: hello如果属性名和值相同可以只写名
  • 效果与刚才的全局注册是类似的,不同的是,这个hello1组件只能在当前的Vue实例中使用。

组件通信

通常一个单页应用会以一棵嵌套的组件树的形式来组织:
在这里插入图片描述

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

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

父向子通信

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

使用示例:

    <body>
        <div id="app">
            <hello1 v-bind:num1="num" title="title"></hello1>
        </div>
    </body>
    <script src="node_modules/vue/dist/vue.js"></script>
    <script>
        const hello = {
            template: '<button @click="num1++">点击次数:{{num1}}</button>',
            props: ["num1"]
        }
        const app = new Vue({
            el: "#app",
            data: {
                num:0
            },
            components: {
                hello1: hello
            }
        })
    </script>

props验证

验证父组件传递的数据模型是否是子组件需要的:

 const hello = {
            template: '<button @click="num1++">点击次数:{{num1}}</button>',
            props: {
                num1: {
                    type: Number,
                    default: 0,
                    required: true
                }
            }
        }

定义一个复杂类型,例如数组,验证示例:

    <body>
        <div id="app">
            <hello :items="items"></hello>
        </div>

    </body>
    <script src="node_modules/vue/dist/vue.js"></script>
    <script>

        const hello = {
            template: '<ul><li v-for="(item,index) in items" >第{{index+1}}个按钮是:{{item}}</li><br></ul>',
            props: {
                num1: {
                    type: Number,
                    default: 0,
                    required: true
                },
                items:{
                    type: Array,
                    default: [],
                    required: true
                }
            }
        }

        const app = new Vue({
            el: "#app",
            data: {
                // num: "abc"
                num: "123",
                items:["变大","变小","变长"]
            },
            components: {
                // hello1: hello //组件名的key和value一样时,可只写一个
                hello
            }
        })
    </script>

PS1:v-for只能使用在<ul><li></li></ul><li>的类似结构里,不能直接作用与<li>里。
PS2:子组件的自定义属性,必须使用v-bind进行绑定

子向父通信

  • 在上面的案例中,通过父向子通信,可以将num的初始值传递到子模板,它的值可以修改,但是父模板的num并没有改变,下面案例将演示如何修改子模版的数据,同时修改父模板的数据。
  • 子组件调用这个$emit()方法,然后调用父模板的方法,间接修改数据。
<body>
        <div id="app">
            <hello :num1="num" @incres1="incres()"></hello>
        </div>
</body>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
const hello = {
        template: '<button @click="subIncre()">点击+1,现在是:{{num1}}</button>',
        props: {
            num1: {
                type: Number,
                default: 0,
                required: true
            },
        },
        methods: {
            subIncre(){
                this.$emit("incres1");
            }
        }
    }

    const app = new Vue({
        el: "#app",
        data: {
            // num: "abc"
            num: 0,
        },
        components: {
            // hello1: hello //组件名的key和value一样时,可只写一个
            hello
        },
        methods:{
            incres(){
                this.num++
            }
        }
    })
</script>

分析上面代码:数据的改变实际上是子组件调用父模板的方法间接修改的数据。

路由

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>

使用步骤

(1)创建router对象
(2)编写路由规则
(3)在父组件中引入router对象

需求

一个页面,包含登录和注册,点击不同按钮,实现登录和注册页切换,不能同时显示。

实现

(1)安装vue-router

(2)编写子组件

为了复用性,在开发中会将组件放入一个独立的JS文件,并将组件放进一个文件夹统一管理。

登录组件login.js

const loginForm = {
    //template内只能有一个根标签
    template: `
        <form id="loginForm">
            用&ensp;户&ensp;名:<input type="text"></br>
            密&emsp;&emsp;码:<input type="password"></br>
            <input type="button" value="登录">
        </form>
    `
}

注册组件register.js

const registerForm = {
    //template内只能有一个根标签
    template: `
        <form id="registerForm">
            用&ensp;户&ensp;名:<input type="text"></br>
            密&emsp;&emsp;码:<input type="password"></br>
            确认密码:<input type="password">            </br>
            <input type="button" value="注册">
        </form>
    `
}

(3)编写index.html主页面

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>组件路由</title>
    </head>
    <body>
        <div id="app">
            <span><router-link to="/login">登录</router-link></span>&emsp;
            <span><router-link to="/register">注册</router-link></span>
            <hr>
            <router-view></router-view>
        </div>
    </body>
    <script src="../node_modules/vue/dist/vue.min.js"></script>
    <script src="../node_modules/vue-router/dist/vue-router.js"></script>
    <script src="js/loginForm.js"></script>
    <script src="js/registerForm.js"></script>
    <script>
   		//创建router对象
        const router = new VueRouter({
            routes: [ //编写路由规则
                {
                    path:"/login", //请求路径,以“/”开头,不可省略
                    component:loginForm //组件名称
                }, {
                    path: "/register",
                    component: registerForm
                }
            ]
        })

        const app = new Vue({
            el: "#app",
            router //引入上面定义的router对象 ,可以省略在component中注册的路由组件
        })
    </script>
</html>

案例目录结构

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值