Vue学习总结-组件化

在大型应用开发的时候,页面可以划分成很多部分。往往不同的页面,也会有相同的部分。例如可能会有相同的头部导航。但是如果每个页面都独自开发,这无疑增加了我们开发的成本。所以我们会把页面的不同部分拆分成独立的组件,然后在不同页面就可以共享这些组件,避免重复开发。在vue里,所有的vue实例都是组件

全局组件

组件其实也是一个Vue实例,它在定义时需要接收:data、methods、生命周期函数等,但是不同的组件不会与页面的元素绑定,否则就无法复用了,因此没有el属性。接下来我们通过Vue的component方法来定义一个全局组件。

// 定义全局组件,两个参数:1,组件名称。2,组件参数
Vue.component("counter",{
    template: "<button @click='num++'>Button{{num}}</button>",
    data(){
        return {
            num: 1
        }
    }
})

样例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="app">
        <!--全局组件定义完毕后,任何vue实例都可以直接在HTML中通过组件名称来使用组件-->
        <counter></counter>
    </div>
</body>
<script src="node_modules/vue/dist/vue.js"></script>
<script>

    // 定义全局组件,两个参数:1,组件名称。2,组件参数
    Vue.component("counter",{
        // template属性用来渲染组件,其值就是html模板
        template: "<button @click='num++'>点我呀,点我加1。{{num}}</button>",
        //data必须是一个函数,不再是一个对象
        data(){
            return {
                num: 0
            }
        }
    })

    const app= new Vue({
        el:"#app"
    })
</script>
</html>

运行结果:
在这里插入图片描述

组件的复用:

定义好的组件,可以任意复用多次:

<div id="app">
    <!--使用定义好的全局组件-->
    <counter></counter>
    <counter></counter>
    <counter></counter>
</div>

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

组件的data属性必须是一个函数而不是一个对象,因此每个实例可以维护一份被返回对象的独立的拷贝,每个组件之间互不干扰,都有自己的count值。

局部组件

全局注册会随着Vue的加载而加载,造成不必要的浪费。因此,对于一些并不频繁使用的组件,我们会采用局部注册。(局部组件只能在当前的Vue实例中使用)

const hello={
template: "<div>打个招呼,我是{{name}}</div>",
	data(){
	    return {
	        name: "小明"
	    }
	}
}

然后在Vue中使用它:

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

......

var app = new Vue({
    el:"#app",
    //components:当前vue对象子组件集合, key: value(子组件名称: 组件对象名)当名称和对象名一样时可以只写一个
        components:{
        hello: hello // 将定义的对象注册为组件
    }
})

运行结果:
在这里插入图片描述

组件通信

通常一个单页应用会以一棵嵌套的组件树的形式来组织:

在这里插入图片描述

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

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

props(父向子传递)

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

父组件使用子组件,并给子主键传递属性:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="app">
        <!--自定义属性num1-->
        <counter :num1="num"></counter>
    </div>
</body>
<script src="node_modules/vue/dist/vue.js"></script>
<script>

    Vue.component("counter",{
        //使用props接收到的属性来渲染页面
        template: "<button @click='num1++'>点我呀,点我加1。{{num1}}</button>",
        // 通过props来接收一个父组件传递的属性
        props: ["num1"]
    })

    const app= new Vue({
        el:"#app",
        data: {
            num: 0
        }
    })
</script>
</html>

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

props验证

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

<!--自定义属性num1-->
<counter :num1="num1" :num2="num2"></counter>
......
Vue.component("counter",{
    //子组件模板有且只有一个根标签
    template: "<button @click='num1++,num2++'>{{num1}}+{{num2}}={{num1+num2}}</button>",
    props: {
        num1: {
            type: Number,
            default: 0
        },
        num2: {
            type: Number,
            default: 0
        }
    }
})

const app= new Vue({
    el:"#app",
    data: {
        num1: 1,
        num2: 2
    }
})

子组件可以对 items 进行迭代,并输出到页面。 props:定义需要从父组件中接收的属性

  • items:是要接收的属性名称
    • type:限定父组件传递来的必须是数组
    • default:默认值
    • required:是否必须

当 prop 验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的警告,但还是会执行

运行效果:

在这里插入图片描述

type类型,可以有:
在这里插入图片描述

子向父的通信:$emit

子组件接收到父组件属性后,默认是不允许修改的。既然只有父组件能修改,那么加和减的操作一定是放在父组件:

const app= new Vue({
    el:"#app",
    data: {
        num: 0
    },
    methods:{
        incr(){
            this.num++;
        }
    }
})

但是,点击按钮是在子组件中,那就是说需要子组件来调用父组件的函数,怎么做?

我们可以通过v-on指令将父组件的函数绑定到子组件上:

<div id="app">
    <counter :num1="num" @incr1="incr()"></counter>
    <counter :num1="num" @incr1="incr()"></counter>
    <counter :num1="num" @incr1="incr()"></counter>
</div>

在子组件中定义函数,函数的具体实现调用父组件的实现,并在子组件中调用这些函数。当子组件中按钮被点击时,调用绑定的函数:

Vue.component("counter",{
    template: "<button @click='subIncr'>点我呀,点我加1。{{num1}}</button>",
    props: {
        num1: {
            type: Number,
            default: 0
        }
    },
    methods:{
        subIncr(){
            this.$emit("incr1")
        }
    }
})

vue提供了一个内置的 this.$emit() 函数,用来调用父组件绑定的函数

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

路由vue-router

实现功能:一个页面,包含登录和注册,点击不同按钮,实现登录和注册页切换

在这里插入图片描述

编写登录及注册组件

新建一个user目录以及login.js及register.js,编写组件,这里我们只写模板,不写功能。

login.js内容如下:

const loginForm = {
    template:'\
    <div>\
    <h2>登录页</h2> \
    用户名:<input type="text"><br/>\
    密码:<input type="password"><br/>\
    </div>\
    '
}

register.js内容:

const registerForm = {
    template:'\
    <div>\
    <h2>注册页</h2> \
    用&ensp;户&ensp;名:<input type="text"><br/>\
    密&emsp;&emsp;码:<input type="password"><br/>\
    确认密码:<input type="password"><br/>\
    </div>\
    '
}

编写父组件并引用子组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="app">
        <span>登录</span>
        <span>注册</span>
        <hr>
        注册页/登录页
        <!--html是大小写不敏感的,对于大写字母如F用-f表示-->
        <login-form></login-form>
        <register-form></register-form>
    </div>

</body>
<script src="../node_modules/vue/dist/vue.js"></script>
<script src="js/login.js"></script>
<script src="js/register.js"></script>
<script>
    const app= new Vue({
        el: "#app",
        components: {
            loginForm,
            registerForm
        }
    })
</script>
</html>

样式:
在这里插入图片描述

使用vue-router模块实现路由功能

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>

快速入门:

新建vue-router对象,并且指定路由规则:

// 创建VueRouter对象,并指定路由参数
const router = new VueRouter({
    routes:[ // 编写路由规则
        {
            path:"/login", // 请求路径,以“/”开头
            component:loginForm // 组件名称
        },
        {
            path:"/register",
            component:registerForm
        }
    ]
})
  • routes:路由规则的数组,可以指定多个对象,每个对象是一条路由规则,包含以下属性:
    • path:路由的路径
    • component:组件名称

在父组件中引入router对象:

var vm = new Vue({
    el:"#app",
    components:{// 引用登录和注册组件
        loginForm,
        registerForm
    },
    router // 引用上面定义的router对象
})

页面跳转控制:

<div id="app">
    <!--router-link来指定跳转的路径-->
    <span><router-link to="/login">登录</router-link></span>
    <span><router-link to="/register">注册</router-link></span>
    <hr/>
    <div>
        <!--vue-router的锚点-->
        <router-view></router-view>
    </div>
</div>
  • 通过<router-view>来指定一个锚点,当路由的路径匹配时,vue-router会自动把对应组件放到锚点位置进行渲染
  • 通过<router-link>指定一个跳转链接,当点击时,会触发vue-router的路由功能,路径中的hash值会随之改变

完整代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="app">
        <!--router-link来指定跳转的路径-->
        <span><router-link to="/login">登录</router-link></span>
        <span><router-link to="/register">注册</router-link></span>
        <hr>
        <!--vue-router的锚点-->
        <router-view></router-view>
    </div>

</body>
<script src="../node_modules/vue/dist/vue.js"></script>
<script src="../node_modules/vue-router/dist/vue-router.js"></script>
<script src="js/login.js"></script>
<script 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: { // 引用登录和注册组件
            loginForm,
            registerForm
        },
        router // 引用上面定义的router对象
    })
</script>
</html>

运行效果:

在这里插入图片描述

注意:单页应用中,页面的切换并不是页面的跳转,仅仅是地址最后的hash值变化。事实上,我们总共就一个HTML:index.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙源lll

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值