Vue的组件是可复用的 Vue 实例,且带有一个名字 。我们可以在一个通过 new Vue 创建的 Vue 根实例中,把这个组件作为自定义元素来使用。因为组件是可复用的 Vue 实例,所以它们与 new Vue 接收相同的选项,例如 datacomputedwatchmethods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项。

一  创建组件

  Vue提供了三种不同的方式来定义组件,分别是:全局组件,私有组件,单文件组件。接下来就让我一一道来。

  1,全局组件

  注册全局组件非常简单,也是很常用的一种方式。

  1. Vue.component('myCom',{
  2. template:'<div><p>我是一个全局<span>组件</span></p></div>'
  3. });

  Vue.component()方法需要两个参数:

    第一个,组件名称;

    第二个,实例(初始化)对象,可以包含所有使用new方式创建Vue实例时提供的所有属性,除了el。

  注意:组件的实例对象必须提供一个template属性,用作该组件的HTML代码模板,且在该模板中有且只能有一个根元素。全局组件的注册必须在创建Vue实例之前。

  小技巧:由于在编写JS时,一般没有HTML代码提示,创建组件模板代码会很不方便,所有可以在HTML文件中使用<template>元素创建模板,然后在组件的template属性中使用id选择器引用该模板。

  注意:<template>元素必须在new Vue实例接管的根元素外部。

  1. <template id="tem">
  2. <div>
  3. <p>我是组件内的p</p>
  4. <span>我是组件中的span</span>
  5. </div>
  6. </template>
  7. <!-- 在HTML中 -->
  1. Vue.component('myCom',{
  2. template:'#tem'
  3. });
    //在组件中

  

  2,私有组件

  全局创建的组件在所有Vue实例中均可以使用,有时候这并不符合我们的需求。你可以通过以下方式定义Vue实例的私有组件,这些组件只能在该Vue实例根元素内部使用。

  1. var vm = new Vue({
  2. el:'#app',
  3. components:{
  4. mycom:{
  5. template:'#tem'
  6. }
  7. }
  8. });

  通过Vue实例的components属性可以定义私有组件,该属性绑定一个对象,对象的属性名是组件名,属性值是组件实例对象。

  

  3,单文件组件

  Vue的单文件组件是一个以.vue为后缀名的文件。由于HTML和JavaScrip不能识别.vue文件,所以不能直接使用这种方式的组件,必须配合webpack或vue-cli工具才能正确解析.vue文件。这里的重点是Vue单文件组件,所以有兴趣的同学请移步webpack中文网

  1. <tempalte>
  2. //HTML模板
  3. </template>
  4. <script>
  5. //JS代码
  6. </script>
  7. <style>
  8. //CSS代码
  9. </style>

  .vue文件的名称就是组件的名称,其结构非常简单、清晰:

    <template>标签是组件的HTML模板;

    <script>标签是逻辑代码;

    <style>标签中是样式代码。

二  组件的使用

  不管以哪种方式创建Vue组件,我们最终的目的是在HTML页面中展示出来。本节将详细介绍Vue组件使用方式。

  1,组件标签

  要把我们创建的Vue组件添加到页面中去,只需要把组件名当做标签来使用即可。

  1. Vue.component('myCom',{
  2. template:"#tem"
  3. });
  4. var vm = new Vue({
  5. el:"#app"
  6. });
  7. //JS部分
  1. <div id="app">
  2. <my-com></my-com>
  3. </div>
  4. <!-- HTML部分 -->

  小技巧:注册组件时,建议使用全小写形式命名,因为HTML标签要求使用小写字母。如果你一定要遵守小驼峰命名规则,那么你应该在使用组件时用“-”短横线把单词分隔开。

  

  2,组件复用

  Vue的组件可以重复使用。

  1. <div id="app">
  2. <my-com></my-com>
  3. <my-com></my-com>
  4. <my-com></my-com>
  5. </div>

  当然,全局组件可以在任何地方使用,而私有组件只能在实例接管元素内部使用。

  组件不仅可以简单的重复使用,还可以嵌套。

  1. var vm = new Vue({
  2. el:'#app',
  3. compontents:{
  4. mycom1:{
  5. template:'<div>组件一 <mycom2></mycom2></div>'
  6. },
  7. mycom2:{
  8. template:'<div>组件二</div>'
  9. }
  10. }
  11. });

  

  3,另一种使用方式

  1. var mycom = {
  2. tempalte:'<div id="app2">hello</div>'
  3. };
  4. var vm = new Vue({
  5. el:'#app',
  6. render:function(createEl){
  7. return createEl(mycom);
  8. }
  9. });

  使用render方式渲染组件:给Vue实例添加render属性,该属性值是一个接收一个方法作为参数的函数。参数用于创建Vue组件,return该组件将替代Vue实例接管的#app元素。最终的表现是:页面上将不再出现#app的div,取而代之的是#app2的div。

  这种方式一般配合单文件组件使用,如果要渲染多个组件,只需要创建多个Vue实例即可。

三  数据传递(通信)

  1,props传递数据(父组件 --> 子组件)

  通过在子组件绑定props属性,实现父组件向子组件传递数据。props属性值是一个数组,数组元素被定义用来接收父组件传递来的数据,然后通过v-bind指令指定数组元素接收哪些数据。子组件通过访问props数组元素就可以访问到父组件传递过来的数据了,就如同访问data里面的值。

  1. <div id="app">
  2. <mycom :fromFatherMsg="toSonMsg"></mycom>
  3. </div>
  4. <!-- HTML部分 -->
  1. Vue.component({
  2. template:"<div>{{fromFatherMsg}}</div>",
  3. props:["fromFatherMsg"]
  4. });
  5. var vm = new Vue({
  6. el:'#app',
  7. data:{
  8. toSonMsg:'这是给子组件的数据'
  9. }
  10. });
  11. //JS部分

  通过上面的例子,我们可以将这个过程简单的分为三步:

    第一步,在子组件上添加一个数组属性props,在数组中定义用来接收数据的变量(以字符串形式存储);

    第二步,使用子组件时通过v-bind指令,绑定预先定义的接收变量和父组件将要传递过来的值;

    第三步,在子组件中,如同访问data中的数据一样,访问props数组元素接收到的数据。

  

  2,$emit传递方法(父组件 --> 子组件)

  父组件向子组件传递方法,是通过自定义事件来实现的。

  监听(同时注册)自定义事件有两种方式:组件上使用v-on指令、实例的$on()方法。这里我们将使用第一种方式来做演示。

  子组件通过实例的$emit()方法触发自定义事件,这里的事件名将成为$emit()方法的第一个参数。

  1. <div id="app">
  2. <mycom @fromFatherFun="toSonFun"></mycom>
  3. </div>
  4. <!-- HTML部分 -->
  1. Vue.component({
  2. template:"<div><button @click="myFun">点击执行来自父组件的方法</button></div>",
  3. methods:{
  4. myFun:function(){
  5. this.$emit('fromFatherFun');
  6. }
  7. }
  8. });
  9. var vm = new Vue({
  10. el:'#app',
  11. methods:{
  12. toSonFun(){
  13. console.log( "这是给子组件的方法");
  14. }
  15. });
  16. //JS部分

  注意:和传递数据一样,子组件不能直接使用父组件的方法。子组件需要通过实例的$emit()方法间接执行来自父组件的方法。

  这一过程也可以分为三步:

    第一步,使用子组件时,通过v-on指令自定义一个事件;

    第二步,绑定自定义事件和父组件需要传递的方法(指定回调函数);

    第三步,通过子组件的$emit()方法(通过实参指定需要触发的自定义事件)触发父组件的方法执行;

  

  3,子组件抛出值(子组件 --> 父组件)

  子组件在通过$emit()触发自定义事件时,可以同时利用方法的第二个参数,向外抛出一个值。回调函数(上面父组件传递下来的方法)需要定义一个形参来接收这个子组件抛出的值。

  1. //接上面的例子
  2. Vue.component({
  3. template:"<div><button @click="myFun">点击执行来自父组件的方法</button></div>",
  4. data(){
  5. return {name:'ren'};
  6. },
  7. methods:{
  8. myFun:function(){
  9. this.$emit('fromFatherFun',this.name);
  10. }
  11. }
  12. });
  13. var vm = new Vue({
  14. el:'#app',
  15. data:{
  16. nameFromSon:null
  17. }
  18. methods:{
  19. toSonFun(data){
  20. this.nameFromSon = data;
  21. },
  22. });

  子组件抛出一个值的原理和父组件给子组件传递方法原理是一样的,只不过是不同的用法而已。虽然有点绕,但有用哦。

  

  4,获取子组件的引用

  在使用子组件时,通过绑定ref属性,父组件可以通过Vue实例的$refs属性拿到子组件的引用,然后就可以直接访问子组件的属性或方法了。

  1. <div id="app">
  2.  <mycom ref="sonCom"></mycom>
  3. <button @click="printMsgFromSon">点击打印子组件的信息</button>
  4. </div>
  5. <!-- HTML部分 -->
  1. Vue.component('mycom',{
  2. data:function(){return {name:'ren'}}
  3. });
  4.  
  5. var vm = new Vue({
  6. el:'#app',
  7. methods:{
  8. printMsgFromSon:function(){
  9. console.log(this.$refs.sonCom.name);
  10. }
  11. }
  12. });
  13. //JS部分

  小技巧:ref属性不仅可以用在组件上,也可以用在其他标准HTML标签上,这样Vue实例就可以获取到原生的DOM对象了。

  注意:即使子组件是Vue实例的私有组件,实例也不能直接使用组件的相关数据,还是需要通过$refs等属性来间接访问。

  5,兄弟组件间传值

  兄弟组件间实现通信也是采用自定义事件的形式。不过,这一般需要一个空的Vue实例作为中介,配合使用$on()和$emit()实现兄弟组件间的传值。

  1. <div id="app">
  2. <com1></com1>
  3. <com2></com2>
  4. </div>
  5. <template id="com1">
  6. <div>
  7. <p>com1组件:{{name}}</p>
  8. <button @click="send">将数据发送给com2</button>
  9. </div>
  10. </template>
  11. <template id="com2">
  12. <div>
  13. <p>com2组件:{{name}}</p>
  14. </div>
  15. </template>
  16. <!-- HTML部分 -->
  1. var event = new Vue();
  2. var vm = new Vue({
  3. el:'#app',
  4. components:{
  5. com1:{
  6. template:'#com1',
  7. data(){
  8. return{name:'ren'};
  9. },
  10. methods:{
  11. send(){
  12. event.$emit('sendMsg',this.name);
  13. }
  14. }
  15. },
  16. com2:{
  17. template:'#com2',
  18. data(){
  19. return {name:null};
  20. },
  21. created(){//因为不知道什么时候会被触发,所以一般选择在生命周期钩子中监听
  22. event.$on('sendMsg',name => {this.name = name;})
  23. //这里需要使用箭头函数,使其内部的this指向com2
  24. }
  25. }
  26. }
  27. });
    //JS部分

四  其他事项

  1,单独的data

  经过上面的学习,你可能已经发现了一个问题:组件中的data属性是一个函数返回的对象。

  1. Vue.component("mycom",{
  2. template:"",
  3. data(){
  4. return { //some code };
  5. }
  6. });
  7. //这是ES6的写法,等同于data:function(){return {some code};}

  由于data属性绑定的是一个对象,而对象是一个引用类型,为了保证为每个组件维护一份独立的数据,组件的data属性必须是一个函数。

  

  2,插槽<slot>

  当你读到这里时,你可能会有一个疑问:既然我们可以用标签形式使用Vue组件,那么是否可以在开始标签和结束标签之间填些内容呢?如果可以的话,该如何做呢?Vue的答案是肯定的。

  首先请看下面的例子:

  1. <div id="app">
  2. <com>我是插槽内容</com>
  3. </div>
  4. <!-- HTML部分 -->
  1. Vue.compenent('com',{
  2. template:'<div><p>我是组件</p><slot>我是默认值<slot></div>'
  3. });
  4. var vm = new Vue({
  5. el:'#app'
  6. });
  7. //JS部分

  "我是插槽内容"将替换com组件中<slot>元素。

  注意:如果在使用子组件时没有提供插槽值,那么<slot>元素中的默认值将会生效,前提是你已经定义了这些值。

  上面的例子中,组件最终渲染的HTML结构如下:

  1. <div>
  2. <p>我是组件</p>
  3. 我是插槽内容
  4. </div>

  注意:插槽的内容不仅可以是文本内容,还可以是HTML代码,甚至另一个组件。

  如果你需要在一个组件中定义多个插槽,那么你应该需要用到<slot>元素的name属性,来指定每个插槽应该拥有怎么样的模板。

  1. <div>
  2. <com>
  3. <template v-slot:"header">
  4. <!-- 单独的HTML模板 -->
  5. </template>
  6. <div><p>我是默认的模板</p></div>
  7. <template v-slot:"footer">
  8. <!-- 单独的HTML模板 -->
  9. </template>
  10. </com>
  11. </div>
  12. <!-- HTML部分 -->
  1. Vue.component('com',{
  2. tempalte:'<div><slot name="header"></slot><slot></slot><slot name="footer"></slot></div>'
  3. });
  4. var vm = new Vue({
  5. el:'#app'
  6. });

  具名的插槽需要在使用组件时,用<template>元素单独定义模板,并通过v-slot指令以参数的形式指定:“我是xxx插槽的模板”。

  其他所有没有包裹在<template>元素内的模板,将自动归为匿名的<slot>元素下面。

  

  3,特殊的嵌套元素

  有些 HTML 元素,诸如 <ul><ol><table> 和 <select>,对于哪些元素可以出现在其内部是有严格限制的。而有些元素,诸如 <li><tr> 和 <option>,只能出现在其它某些特定的元素内部。要怎样才能在这些元素中正确的渲染组件呢?幸好,Vue提供了is特性:

  1. <table>
  2. <tr is="mycom"></tr>
  3. </table>

  注意:如果你使用字符串定义组件模板(例如:template: '...')、或者单文件组件(.vue)、或者<script>标签(<script type="text/x-template">),那么你完全可以忽略掉这个限制。

Vue组件应用的更多相关文章

  1. vue组件

    分享出来让思路更成熟. 首先组件是 Vue.js 最强大的功能之一. 可以减少很多的工作量,提高工作效率. 编写一个可复用性的组件,虽然官网上也有.... 编写可复用性的vue组件 具备一下的几个要求 ...

  2. vue组件的配置属性

    vue组件的声明语法: Vue.component('component-name',{ template:'<p>段落{{prop1}} {{prop2}}</p>', da ...

  3. vue组件,撸第一个

    实现此例您可以学到: vue-cli的基本应用 父组件如何向子组件传递值 单文件组件如何引入scss v-on和v-for的基础应用 源码下载 一.搭建vue开发环境 更换镜像到cnpmnpm ins ...

  4. vue组件最佳实践

    看了老外的一篇关于组件开发的建议(强烈建议阅读英文原版),感觉不错翻译一下加深理解. 这篇文章制定一个统一的规则来开发你的vue程序,以至于达到一下目的. 1.让开发者和开发团队更容易发现一些事情. ...

  5. JS组件系列——又一款MVVM组件:Vue(二:构建自己的Vue组件)

    前言:转眼距离上篇 JS组件系列——又一款MVVM组件:Vue(一:30分钟搞定前端增删改查) 已有好几个月了,今天打算将它捡起来,发现好久不用,Vue相关技术点都生疏不少.经过这几个月的时间,Vue ...

  6. vue组件大集合 component

    vue组件分为全局组件.局部组件和父子组件,其中局部组件只能在el定义的范围内使用, 全局组件可以在随意地方使用,父子组件之间的传值问题等. Vue.extend 创建一个组件构造器 template ...

  7. 【Vue】详解Vue组件系统

    Vue渲染的两大基础方式 new 一个Vue的实例 这个我们一般会使用在挂载根节点这一初始化操作上: new Vue({ el: '#app' }) 注册组件并使用—— 全局注册 通过Vue.comp ...

  8. 关于vue组件的一个小结

    用vue进行开发到目前为止也有将近一年的时间了,在项目技术选型的时候隔壁组选 react的时候我们坚持使用vue作为前端的开发框架.虽然两者思想上的差异不大,但是vue的语法在代码的可读性以及后期的维 ...

  9. Vue组件基础用法

    前面的话 组件(Component)是Vue.js最强大的功能之一.组件可以扩展HTML元素,封装可重用的代码.根据项目需求,抽象出一些组件,每个组件里包含了展现.功能和样式.每个页面,根据自己所需, ...

  10. Vue组件模板形式实现对象数组数据循环为树形结构

    数据结构为数组中包含对象--树形结构,用Vue组件的写法实现以下的效果: 树形列表,缩进显示层级,第5级数据加底色,数据样式显色,点击展开折叠数据.本文为用Vue实现方式,另有一篇为用knockout ...

随机推荐

  1. Birt报表

    研究了两天终于发现开始学会了BIRT报表的开发流程. 第一步:到http://www.eclipse.org/downloads/下载  Eclipse IDE for Java and Report ...

  2. 吉利WA数

  3. python购物车练习题

    # 购物车练习# 1.启动程序后,让用户输入工资,打印商品列表# 2.允许用户根据商品编号购买商品# 3.用户选择商品后,检测余额是否够,够就直接扣款,不够就提醒# 4.可随时退出,退出时,打印已购买 ...

  4. 大数据之路week01--自学之面向对象java(static,this指针(初稿))

    函数的重载 返回值不一样会报错 java中,如果自己定义了构造函数的话,它就不会给你默认一个无参函数 如果一个属性,只进行定义,不初始化,自动补0,如果是一个布尔属性,默认是false但是如果一个局部 ...

  5. 最适合Java开发者的一本书和一软件

    一书-<Java编程思想> 一软件-IntelliJ IDEA Java自学是否可以成功,答案显而易见,可以. 自学Java关键看自己是否有毅力.是否有恒心. 自学Java 自学Java不 ...

  6. Centos 6/7 常用命令总结 (基础)

    Centos 6/7 常用命令总结 (基础): 参考链接:https://www.cnblogs.com/linhaifeng/p/6045600.html 目录介绍: a) bin目录:用来存放常用 ...

  7. 利用GitHub Pages + jekyll快速搭建个人博客

    前言 想搭建自己博客很久了(虽然搭了也不见得能产出多频繁). 最初萌生想写自己博客的想法,想象中,是自己一行一行码出来的成品,对众多快速构建+模板式搭建不屑一顾,也是那段时间给闲的,从前后端选型.数据 ...

  8. Java基础:8种基本数据类型,取值范围和储存字节说明。

    Java中,一共有8种基本数据类型: 4种整数型:int,short,long,byte. 2种浮点型:float,double. 1种字符类型:char. 1种表示真值的类型:boolean. [S ...

  9. 微信web协议,群成员唯一uin,获取群成员唯一标识

    群成员唯一标识获取接口 全网最新,支持调试测试.觉得OK再付款! 800元出售源码 不讲价 联系QQ:2052404477

  10. Secure CRT注册码

    secure CRT 把记忆的东西放在这就行了,:)   SecureCRT 5.2.2的注册码 Name:          Apollo InteractiveCompany:    Apollo ...