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 instanceof,typeof的区别
Mar 24 Javascript
jquery插件制作教程 txtHover
Aug 17 Javascript
jquery $.each 和for怎么跳出循环终止本次循环
Sep 27 Javascript
原生JavaScript生成GUID的实现示例
Sep 05 Javascript
JS实现的数组全排列输出算法
Mar 19 Javascript
jquery左右全屏大尺寸多图滑动效果代码分享
Aug 28 Javascript
详解JS中定时器setInterval和setTImeout的this指向问题
Jan 06 Javascript
Angularjs实现搜索关键字高亮显示效果
Jan 17 Javascript
解决使用vue.js路由后失效的问题
Mar 17 Javascript
微信开发之企业付款到银行卡接口开发的示例代码
Sep 18 Javascript
jQuery实现全选、反选和不选功能的方法详解
Dec 04 jQuery
Layer UI表格列日期格式化及取消自动填充日期的实现方法
May 10 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+mysql扎实个人基本功
2008/03/27 PHP
php创建sprite
2014/02/11 PHP
PHP下通过QRCode类库创建中间带网站LOGO的二维码
2014/07/12 PHP
smarty自定义函数htmlcheckboxes用法实例
2015/01/22 PHP
php用户注册信息验证正则表达式
2015/11/12 PHP
symfony2.4的twig中date用法分析
2016/03/18 PHP
Zend Framework缓存Cache用法简单实例
2016/03/19 PHP
URL编码转换,escape() encodeURI() encodeURIComponent()
2006/12/27 Javascript
JavaScript日期时间格式化函数分享
2014/05/05 Javascript
JS实现文字链接感应鼠标淡入淡出改变颜色的方法
2015/02/26 Javascript
jQuery实现平滑滚动的标签分栏切换效果
2015/08/28 Javascript
JS封装cookie操作函数实例(设置、读取、删除)
2015/11/17 Javascript
基于javascript实现最简单选项卡切换
2017/02/01 Javascript
JavaScript实现定时页面跳转功能示例
2017/02/14 Javascript
Vue2.0 实现歌手列表滚动及右侧快速入口功能
2018/08/08 Javascript
[44:21]Ti4 循环赛第四日 附加赛NEWBEE vs LGD
2014/07/13 DOTA
python目录与文件名操作例子
2016/08/28 Python
Python实现的选择排序算法示例
2017/11/29 Python
浅谈python爬虫使用Selenium模拟浏览器行为
2018/02/23 Python
Python3处理HTTP请求的实例
2018/05/10 Python
python定时复制远程文件夹中所有文件
2019/04/30 Python
详解pandas如何去掉、过滤数据集中的某些值或者某些行?
2019/05/15 Python
python编程进阶之异常处理用法实例分析
2020/02/21 Python
Python实现爬取并分析电商评论
2020/06/19 Python
详解numpy1.19.4与python3.9版本冲突解决
2020/12/15 Python
CSS3中Transition动画属性用法详解
2016/07/04 HTML / CSS
HTML5 Canvas鼠标与键盘事件demo示例
2013/07/04 HTML / CSS
使用HTML5拍照示例代码
2013/08/06 HTML / CSS
瑞典时尚服装购物网站:Miinto.se
2017/10/30 全球购物
白兰氏健康Mall:BRAND’S
2017/11/13 全球购物
夜大毕业生自我评价分享
2013/11/10 职场文书
班组长安全生产职责
2013/12/16 职场文书
九年级物理教学反思
2014/01/29 职场文书
社区健康教育实施方案
2014/03/18 职场文书
生活委员竞选稿
2015/11/21 职场文书
CSS使用伪类控制边框长度的方法
2022/01/18 HTML / CSS