Vue.js 2.x之组件的定义和注册图文详解


Posted in Javascript onJune 19, 2018

前言

什么是组件

组件: 组件的出现,就是为了拆分Vue实例的代码量的,能够让我们以不同的组件,来划分不同的功能模块,将来我们需要什么样的功能,就可以去调用对应的组件即可。

模块化和组件化的区别

  • 模块化:是从代码逻辑的角度进行划分的;方便代码分层开发,保证每个功能模块的职能单一
  • 组件化:是从UI界面的角度进行划分的;前端的组件化,方便UI组件的重用

全局组件的定义和注册

组件Component是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。

全局组件的定义和注册有三种方式,我们接下来讲一讲。

写法一

写法一:使用Vue.extend方法定义组件,使用 Vue.component方法注册组件。

代码举例:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>Document</title>
 <script src="vue2.5.16.js"></script>
</head>
<body>
 <div id="app">
  <!-- 如果要使用组件,直接把组件的名称,以 HTML 标签的形式,引入到页面中,即可 -->
  <account> </account>
 </div>
 <script>
  //第一步:使用 Vue.extend 定义组件
  var myAccount = Vue.extend({
   template: '<div><h2>登录页面</h2> <h3>注册页面</h3></div>' // 通过 template 属性,指定了组件要展示的HTML结构。template 是 Vue 中的关键字,不能改。
  });
  //第二步:使用 Vue.component 注册组件
  // Vue.component('组件的名称', 创建出来的组件模板对象)
  Vue.component('account', myAccount); //第一个参数是组件的名称(标签名),第二个参数是模板对象
  new Vue({
   el: '#app'
  });
 </script>
</body>
</html>

上方代码中,在注册组件时,第一个参数是标签名,第二个参数是组件的定义。

运行结果如下:

Vue.js 2.x之组件的定义和注册图文详解

代码截图如下:

Vue.js 2.x之组件的定义和注册图文详解

上图中,注意两点:

注意1、红框部分,要保证二者的名字是一致的。如果在注册时,组件的名称是驼峰命名,比如:

Vue.component('myComponent', myAccount); //第一个参数是组件的名称(标签名),第二个参数是模板对象
那么,在标签中使用组件时,需要把大写的驼峰改为小写的字母,同时两个单词之间使用-进行连接:

<my-component> </my-component>
Vue.component('my')

注意2、绿框部分,一定要用一个大的根元素(例如<div>)包裹起来。如果我写成下面这样,就没有预期的效果:

template: '<h2>登录页面</h2> <h3>注册页面</h3>'

结果如下:(并非预期的效果)

Vue.js 2.x之组件的定义和注册图文详解

写法二

写法二:Vue.component方法定义、注册组件(一步到位)。

代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>Document</title>
 <script src="vue2.5.16.js"></script>
</head>
<body>
 <div id="app">
  <account> </account>
 </div>
 <script>
  //定义、注册组件:第一个参数是组件的名称(标签名),第二个参数是组件的定义
  Vue.component('account', {
   template: '<div><h2>登录页面</h2> <h3>注册页面</h3></div>' // template 是 Vue 中的关键字,不能改。
  });
  new Vue({
   el: '#app'
  });
 </script>
</body>
</html>

代码截图如下:

Vue.js 2.x之组件的定义和注册图文详解

上图中,同样注意两点:

1、红框部分,要保证二者的名字是一致的。

2、绿框部分,一定要用一个大的根元素(例如<div>)包裹起来。如果我写成下面这样,就没有预期的效果:

template: '<h2>登录页面</h2> <h3>注册页面</h3>'

结果如下:(并非预期的效果)

Vue.js 2.x之组件的定义和注册图文详解

写法三

上面的写法一、写法二并不是很智能,因为在定义模板的时候,没有智能提示和高亮,容易出错。我们不妨来看看写法三。

写法三:将组件内容定义到template标签中去。

代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>Document</title>
 <script src="vue2.5.16.js"></script>
</head>
<body>
 <!-- 定义模板 -->
 <template id="myAccount">
  <div>
   <h2>登录页面</h2>
   <h3>注册页面</h3>
  </div>
 </template>
 <div id="app">
  <!-- 使用组件 -->
  <account> </account>
 </div>
 <script>
  //定义、注册组件
  Vue.component('account', {
   template: '#myAccount' // template 是 Vue 中的关键字,不能改。
  });
  new Vue({
   el: '#app'
  });
 </script>
</body>
</html>

代码截图如下:

Vue.js 2.x之组件的定义和注册图文详解

写法三其实和方法二差不多,无非是把绿框部分的内容,单独放在了<template>标签中而已,这样有利于 html 标签的书写。

使用components定义私有组件

我们在上一段中定义的是全局组件,这样做的时候,多个Vue实例都可以使用这个组件。

我们可以在一个Vue实例的内部定义私有组件,这样做的时候,只有当前这个Vue实例才可以使用这个组件。

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>Document</title>
 <script src="vue2.5.16.js"></script>
</head>
<body>
 <div id="app">
  <!-- 使用Vue实例内部的私有组件 -->
  <my-login></my-login>
 </div>
 <script>
  new Vue({
   el: '#app',
   data: {},
   components: { // 定义、注册Vue实例内部的私有组件
    myLogin: {
     template: '<h3>这是私有的login组件</h3>'
    }
   }
  });
 </script>
</body>
</html>

运行效果:

Vue.js 2.x之组件的定义和注册图文详解

当然,我们还可以把模板的定义存放在<template>标签中,这样的话,模板里的html标签就可以出现智能提示和高亮,避免出错。如下:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>Document</title>
 <script src="vue2.5.16.js"></script>
</head>
<body>
 <!-- 定义模板 -->
 <template id="loginTmp">
  <h3>这是私有的login组件</h3>
 </template>
 <div id="app">
  <!-- 调用Vue实例内部的私有组件 -->
  <my-login></my-login>
 </div>
 <script>
  new Vue({
   el: '#app',
   data: {},
   components: { // 定义、注册Vue实例内部的私有组件
    myLogin: {
     template: '#loginTmp'
    }
   }
  });
 </script>
</body>
</html>

运行效果不变。

为组件添加 data 和 methods

既然组件是一个页面,那么,页面中可能会有一些功能要动态展示。因此,我们有必要为组件添加 data 和 methods。

代码举例如下:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>Document</title>
 <script src="vue2.5.16.js"></script>
</head>
<body>
 <!-- 定义组件的模板 -->
 <template id="myAccount">
  <div>
   <!-- 在组件的模板中,调用本组件中的data -->
   {{myData}}
   <a href="#" rel="external nofollow" v-on:click="login">登录1</a>
   <h2>登录页面</h2>
   <h3>注册页面</h3>
  </div>
 </template>
 <div id="app">
  <!-- 第一次调用组件 -->
  <account> </account>
  <!-- 第二次调用组件 -->
  <account> </account>
 </div>
 <script>
  //定义、注册组件
  Vue.component('account', {
   template: '#myAccount',
   //组件中的 data
   //【注意】组件中的data,不再是对象,而是一个方法(否则报错);而且这个方法内部,还必须返回一个对象才行
   // 组件中 的data 数据,使用方式,和实例中的 data 使用方式完全一样!!!
   data: function () {
    return {
     myData: 'smyhvae'
    }
   },
   //组件中的 method
   methods: {
    login: function () {
     alert('login操作');
    }
   }
  });
  new Vue({
   el: '#app'
  });
 </script>
</body>
</html>

上方代码所示,我们在account组件中添加的data 和 methods,其作用域只限于account组件里,保证独立性。

注意,在为组件添加数据时,data不再是对象了,而是function,而且要通过 return的形式进行返回;否则,页面上是无法看到效果的。通过 function返回对象的形式来定义data,作用是:

上方代码中,组件<account>被调用了两次(不像根组件那样只能调用一次),但是每个组件里的数据 myData是各自独立的,不产生冲突。

换而言之,通过函数返回对象的目的,是为了让每个组件都有自己独立的数据存储,而不应该共享一套数据。

为什么组件的data必须是一个function

我们先来看下面这样的例子:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>Document</title>
 <script src="vue2.5.16.js"></script>
</head>
<body>
 <div id="app">
  <!-- 第一次调用组件 -->
  <counter></counter>
  <hr>
  <!-- 第二次调用组件 -->
  <counter></counter>
 </div>
 <!-- 定义模板 -->
 <template id="tmpl">
  <div>
   <input type="button" value="让count加1" @click="increment">
   <h3>{{count}}</h3>
  </div>
 </template>
 <script>
  var dataObj = { count: 0 }
  // 这是一个计数器的组件, 身上有个按钮,每当点击按钮,让 data 中的 count 值 +1
  Vue.component('counter', {
   template: '#tmpl',
   data: function () {
    return dataObj //当我们return全局的dataObj的时候,子组件们会共享这个dataObj
   },
   methods: {
    increment() {
     this.count++
    }
   }
  })
  // 创建 Vue 实例,得到 ViewModel
  var vm = new Vue({
   el: '#app',
   data: {},
   methods: {}
  });
 </script>
</body>
</html>

运行效果如下:

Vue.js 2.x之组件的定义和注册图文详解

上面的例子中,将组件<counter>调用了两次,由于dataObj是全局对象,导致两个组件实例都可以共享这个dataObj数据。于是,我们点击任何一个组件实例的按钮,都可以让count数据加1。

现在问题来了,如果我们想让组件<counter>的两个实例去单独操作count数据,应该怎么做呢?我们应该修改 data中 return出去的内容:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>Document</title>
 <script src="vue2.5.16.js"></script>
</head>
<body>
 <div id="app">
  <counter></counter>
  <hr>
  <counter></counter>
  <hr>
  <counter></counter>
 </div>
 <template id="tmpl">
  <div>
   <input type="button" value="让count加1" @click="increment">
   <h3>{{count}}</h3>
  </div>
 </template>
 <script>
  var dataObj = { count: 0 }
  // 这是一个计数器的组件, 身上有个按钮,每当点击按钮,让 data 中的 count 值 +1
  Vue.component('counter', {
   template: '#tmpl',
   data: function () {
    // return dataObj //当我们return全局的dataObj的时候,这个dataObj是共享的
    return { count: 0 } // 【重要】return一个**新开辟**的对象数据
   },
   methods: {
    increment() {
     this.count++
    }
   }
  })
  // 创建 Vue 实例,得到 ViewModel
  var vm = new Vue({
   el: '#app',
   data: {},
   methods: {}
  });
 </script>
</body>
</html>

运行效果:

Vue.js 2.x之组件的定义和注册图文详解

如上图所示,每当我们创建一个新的组件实例时,就会调用data函数,data函数里会return一个新开辟的对象数据。这样做,就可以保证每个组件实例有独立的数据存储。

组件的切换

使用v-if和v-else结合flag进行切换

代码举例:(登录组件/注册组件,二选一)

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>Document</title>
 <script src="vue2.5.16.js"></script>
</head>
<body>
 <div id="app">
  <!-- 温馨提示:`.prevent`可以阻止超链接的默认事件 -->
  <a href="" @click.prevent=" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" flag=true">登录</a>
  <a href="" @click.prevent=" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" flag=false">注册</a>
  <!-- 登录组件/注册组件,同时只显示一个 -->
  <login v-if="flag"></login>
  <register v-else="flag"></register>
 </div>
 <script>
  Vue.component('login', {
   template: '<h3>登录组件</h3>'
  })
  Vue.component('register', {
   template: '<h3>注册组件</h3>'
  })
  // 创建 Vue 实例,得到 ViewModel
  var vm = new Vue({
   el: '#app',
   data: {
    flag: false
   },
   methods: {}
  });
 </script>
</body>
</html>

运行效果如下:

Vue.js 2.x之组件的定义和注册图文详解

使用Vue提供的<component>标签实现组件切换

上面的例子中,我们是通过flag的值来进行组件的切换。但是,flag的值只可能有两种情况,也就是说,v-if和v-else只能进行两个组件之间的切换。

那如何实现三个甚至三个以上的组件切换呢?这里,我们可以用到Vue提供的<component>标签。

我们先来看一下<component>标签的用法。

基于上面的代码,如果我想让login组件显示出来,借助<component>标签可以这样做:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>Document</title>
 <script src="Vue2.5.16.js"></script>
</head>
<body>
 <div id="app">
  <!-- Vue提供了 component ,来展示对应名称的组件 -->
  <!-- 【重要】component 是一个占位符, `:is` 属性,可以用来指定要展示的组件名称。这里,我们让 login 组件显示出来 -->
  <component :is="'login'"></component>
 </div>
 <script>
  // 组件名称是 字符串
  Vue.component('login', {
   template: '<h3>登录组件</h3>'
  })
  Vue.component('register', {
   template: '<h3>注册组件</h3>'
  })
  // 创建 Vue 实例,得到 ViewModel
  var vm = new Vue({
   el: '#app',
   data: {
    comName: 'login' // 当前 component 中的 :is 绑定的组件的名称
   },
   methods: {}
  });
 </script>
</body>
</html>

上方代码中,提取关键代码如下:     

<component :is="'login'"></component>

如果我想让register组件显示出来,借助<component>标签可以这样做:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>Document</title>
 <script src="Vue2.5.16.js"></script>
</head>
<body>
 <div id="app">
  <!-- Vue提供了 component ,来展示对应名称的组件 -->
  <!-- 【重要】component 是一个占位符, `:is` 属性,可以用来指定要展示的组件名称 -->
  <component :is="'register'"></component>
 </div>
 <script>
  // 组件名称是 字符串
  Vue.component('login', {
   template: '<h3>登录组件</h3>'
  })
  Vue.component('register', {
   template: '<h3>注册组件</h3>'
  })
  // 创建 Vue 实例,得到 ViewModel
  var vm = new Vue({
   el: '#app',
   data: {
    comName: 'login' // 当前 component 中的 :is 绑定的组件的名称
   },
   methods: {}
  });
 </script>
</body>
</html>

上方代码中,提取关键代码如下:    

<component :is="'register'"></component>

因此,如果要实现组件之间的切换,我们可以给<component>标签里的is属性值设置为变量即可,来看看代码实现。

实现组件切换的完整代码:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>Document</title>
 <script src="vue2.5.16.js"></script>
</head>
<body>
 <div id="app">
  <!-- 点击按钮后,设置变量`comName`为不同的值,代表着后面的component里显示不同的组件 -->
  <a href="" @click.prevent=" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" comName='login'">登录</a>
  <a href="" @click.prevent=" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" comName='register'">注册</a>
  <!-- Vue提供了 component ,来展示对应名称的组件 -->
  <!-- component 是一个占位符, :is 属性,可以用来指定要展示的组件的名称 -->
  <!-- 此处的`comName`是变量,变量值为组件名称 -->
  <component :is="comName"></component>
 </div>
 <script>
  // 组件名称是 字符串
  Vue.component('login', {
   template: '<h3>登录组件</h3>'
  })
  Vue.component('register', {
   template: '<h3>注册组件</h3>'
  })
  // 创建 Vue 实例,得到 ViewModel
  var vm = new Vue({
   el: '#app',
   data: {
    comName: 'login' // 当前 component 中的 :is 绑定的组件的名称
   },
   methods: {}
  });
 </script>
</body>
</html>

效果:

Vue.js 2.x之组件的定义和注册图文详解

总结

以上所述是小编给大家介绍的Vue.js 2.x之组件的定义和注册图文详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
Javascript代码混淆综合解决方案-Javascript在线混淆器
Dec 18 Javascript
JavaScript入门教程(5) js Screen屏幕对象
Jan 31 Javascript
JavaScript DOM学习第一章 W3C DOM简介
Feb 19 Javascript
JavaScript中为元素加上name属性的方法
May 09 Javascript
基于jQuery的投票系统显示结果插件
Aug 12 Javascript
JavaScript中数组对象的那些自带方法介绍
Mar 12 Javascript
基于JavaScript 声明全局变量的三种方式详解
May 07 Javascript
js获取当月最后一天实例代码
Nov 19 Javascript
数据结构中的各种排序方法小结(JS实现)
Jul 23 Javascript
Vue.js每天必学之数据双向绑定
Sep 05 Javascript
jQuery实现左右滑动的toggle方法
Mar 03 jQuery
AngularJS与后端php的数据交互方法
Aug 13 Javascript
Vue中使用webpack别名的方法实例详解
Jun 19 #Javascript
vue mounted组件的使用
Jun 18 #Javascript
基于rollup的组件库打包体积优化小结
Jun 18 #Javascript
详解组件库的webpack构建速度优化
Jun 18 #Javascript
Javascript实现异步编程的过程
Jun 18 #Javascript
详解JS函数stack size计算方法
Jun 18 #Javascript
jQuery使用动画队列自定义动画操作示例
Jun 16 #jQuery
You might like
php遍历数组的4种方法总结
2014/07/05 PHP
php计划任务之ignore_user_abort函数实现方法
2015/01/08 PHP
PHP实现微信网页授权开发教程
2016/01/19 PHP
PhpStorm terminal无法输入命令的解决方法
2016/10/09 PHP
Mac版PhpStorm之XAMPP整合apache服务器配置的图文教程详解
2016/10/13 PHP
超棒的javascript页面顶部卷动广告效果
2007/12/01 Javascript
javascript实现tabs选项卡切换效果(自写原生js)
2013/03/19 Javascript
js跑马灯代码(自写)
2013/04/17 Javascript
JavaScript创建类/对象的几种方式概述及实例
2013/05/06 Javascript
jquery 鼠标滑动显示详情应用示例
2014/01/24 Javascript
javascript页面加载完执行事件代码
2014/02/11 Javascript
JavaScript ES6中const、let与var的对比详解
2017/06/18 Javascript
微信小程序实现验证码获取倒计时效果
2018/02/08 Javascript
JavaScript同源策略和跨域访问实例详解
2018/04/03 Javascript
详解vue中的computed的this指向问题
2018/12/05 Javascript
jQuery实现的卷帘门滑入滑出效果【案例】
2019/02/18 jQuery
Vuejs中的watch实例详解(监听者)
2020/01/05 Javascript
Vue全局使用less样式,组件使用全局样式文件中定义的变量操作
2020/10/21 Javascript
Ant Design Vue table中列超长显示...并加提示语的实例
2020/10/31 Javascript
[51:29]Alliance vs TNC 2019国际邀请赛小组赛 BO2 第二场 8.16
2019/08/18 DOTA
Python程序设计入门(4)模块和包
2014/06/16 Python
Python 实现使用dict 创建二维数据、DataFrame
2018/04/13 Python
Python 普通最小二乘法(OLS)进行多项式拟合的方法
2018/12/29 Python
python调用外部程序的实操步骤
2019/03/04 Python
Html5移动端获奖无缝滚动动画实现示例
2018/06/25 HTML / CSS
阿玛尼美妆英国官网:Giorgio Armani Beauty英国
2019/03/28 全球购物
Ego Shoes官网:英国时髦鞋类品牌
2020/10/19 全球购物
对象的序列化(serialization)类是面向流的,应如何将对象写入到随机存取文件中
2015/06/22 面试题
毕业生自荐书模版
2014/01/04 职场文书
公交公司毕业生求职信
2014/02/15 职场文书
秋天的怀念教学反思
2014/04/28 职场文书
学校爱国卫生月活动总结
2014/06/25 职场文书
大学生党性分析材料
2014/12/19 职场文书
信用卡工作证明范本
2015/06/19 职场文书
遗嘱范文
2015/08/07 职场文书
如果用一句诗总结你的上半年,你会用哪句呢?
2019/07/16 职场文书