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 日期处理之时区问题
Oct 08 Javascript
js 判断脚本加载完毕的代码
Jul 13 Javascript
JS倒计时代码汇总
Nov 25 Javascript
bootstrap datetimepicker2.3.11时间插件使用
Nov 19 Javascript
Node.js中多进程模块Cluster的介绍与使用
May 27 Javascript
详解用场景去理解函数柯里化(入门篇)
Apr 11 Javascript
读懂CommonJS的模块加载
Apr 19 Javascript
Layui多选只有最后一个值的解决方法
Sep 02 Javascript
微信小程序 搜索框组件代码实例
Sep 06 Javascript
ES6之Proxy的get方法详解
Oct 11 Javascript
Webpack5正式发布,有哪些新特性
Oct 12 Javascript
使用webpack5从0到1搭建一个react项目的实现步骤
Dec 16 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图片上传类带图片显示
2006/11/25 PHP
PHP数组交集的优化代码分析
2011/03/06 PHP
windows7下安装php的imagick和imagemagick扩展教程
2014/07/04 PHP
php图片合成方法(多张图片合成一张)
2017/11/25 PHP
laravel 查询数据库获取结果实现判断是否为空
2019/10/24 PHP
js option删除代码集合
2008/11/12 Javascript
ASP.NET中使用后端代码注册脚本 生成JQUERY-EASYUI的界面错位的解决方法
2010/06/12 Javascript
基于jQuery架构javascript基础体系
2011/01/01 Javascript
Jquery中val()表单取值赋值的实例代码
2013/08/15 Javascript
使用Jquery实现点击文字后变成文本框且可修改
2013/09/21 Javascript
jsPDF生成pdf后在网页展示实例
2014/01/16 Javascript
微信小程序开发之视频播放器 Video 弹幕 弹幕颜色自定义实例
2016/12/08 Javascript
JavaScript模块化之使用requireJS按需加载
2017/04/12 Javascript
AngularJS  ng-repeat遍历输出的用法
2017/06/19 Javascript
JavaScript实现的前端AES加密解密功能【基于CryptoJS】
2018/08/28 Javascript
解决betterScroll在vue中存在图片时,出现拉不动的问题
2018/09/27 Javascript
vue实现简单的星级评分组件源码
2018/11/16 Javascript
更优雅的微信小程序骨架屏实现详解
2019/08/07 Javascript
vue3 源码解读之 time slicing的使用方法
2019/10/31 Javascript
JS实现动态星空背景效果
2019/11/01 Javascript
微信小程序实现图片压缩
2019/12/03 Javascript
基于canvasJS在PHP中制作动态图表
2020/05/30 Javascript
python的Crypto模块实现AES加密实例代码
2018/01/22 Python
Python绘图Matplotlib之坐标轴及刻度总结
2019/06/28 Python
在django中实现页面倒数几秒后自动跳转的例子
2019/08/16 Python
Python高级编程之继承问题详解(super与mro)
2019/11/19 Python
python全局变量引用与修改过程解析
2020/01/07 Python
Python HTTP下载文件并显示下载进度条功能的实现
2020/04/02 Python
英国排名第一的宠物店:PetPlanet
2020/02/02 全球购物
运动会四百米广播稿
2014/01/19 职场文书
新手上路标语
2014/06/20 职场文书
体育运动会广播稿
2014/10/05 职场文书
杭白菊导游词
2015/02/10 职场文书
美术教师求职信范文
2015/03/20 职场文书
python 经纬度求两点距离、三点面积操作
2021/06/03 Python
vue el-table实现递归嵌套的示例代码
2022/08/14 Vue.js