开发大型应用的时候,页面往往拆分成为多个部分,这些部件可能会被多个页面使用,所以有必要对这些部件进行组件化。
在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个子组件各个组件之间以嵌套的关系组合在一起,那么这个时候不可避免的会有组件间通信的需求。
使用示例:
<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>验证父组件传递的数据模型是否是子组件需要的:
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进行绑定
分析上面代码:数据的改变实际上是子组件调用父模板的方法间接修改的数据。
使用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"> 用 户 名:<input type="text"></br> 密 码:<input type="password"></br> <input type="button" value="登录"> </form> ` }注册组件register.js
const registerForm = { //template内只能有一个根标签 template: ` <form id="registerForm"> 用 户 名:<input type="text"></br> 密 码:<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> <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>案例目录结构