来吧!一文彻底搞定Vue组件!

作者 | Jeskson

来源 | 达达前端小酒馆

Vue组件的概述

组件是什么呢,了解组件对象的分析,Vue组件中的data属性,props传递数据的原理到底是什么。

事件通信的那些事

如何了解父子组件事件通信,和遇到非父子组件事件通信如何处理。

组件类型又是什么鬼

自定义组件双向绑定v-model,动态组件,又是如何称为动态的,为啥是动态呢,递归组件,如何理解递归。

Vue组件的了解

Vue的理解,可以找我上一篇vue.js-详解三大流行框架VUE_快速进阶前端大咖-Vue基础,组件是什么,组件就是自己写好的一部分封装好的功能,自己写的叫组件,别人写的叫插件,组件的运用,是vue.js强大的功能之一,组件的出现是为了提高代码的可重用性,组件是一部分完整好的,如果要使用,你可以放到你自己任何的项目上去,减少代码的重复书写。

直接在你要用的地方引入即可,是不是减少了重复性开发,可以把组件的代码按照template,style,script的拆分形式,放到对应的文件中。

template是什么?它是模板(template),模板是声明了数据和最终展现给用户的dom之间的映射关系,初始化数据data是什么?一个组件的初始数据状态,对于可以重复使用的组件来说,通常是私有的状态,方法methods是对数据进行操作的方法,接收外部参数,组件之间通过参数来进行数据的传递和共享props,参数默认是单向绑定,也可以双向绑定。

回调函数,一个组件可以触发多个回调函数,created(),attached(),destroyed()。

Vue组件,全局注册与局部注册

全局注册文件,Vue.component(‘组件名‘, {组件参数})方式创建

<body>
 <div id="app">
  <my-component></my-component>
 </div>
 <script src="https://unpkg.com/vue"></script>
 <script>
 // 创建全局组件
 Vue.component('my-component",{
 // template: 组件的HTML代码结构
 template: '<div>this is dada</div>'
});
// Vue实例对象
var vm = new Vue({
 el: '#app'
});
</script>
</body>

局部注册组件,不是每个组件都是需要进行全局注册的,也可以直接在vue实例对象的构造函数中,使用compontent关键字进行注册自定义的组件。

<div id="app">
 <local-component></local-component>
</div>

<script src="https://unpkg.com/vue"></script>
<script>
// Vue实例UI小
var vm = new Vue({
 el: '#app',
 // 创建局部组件
 components: {
  'my-components': {
   template: '<div>this is my</div>'
   }
  }
 }
});

首先先创建局部组件对象,然后注册Vue构造器中注册局部组件对象,最后使用局部组件。

<div id="app">
 // 在默认情况,使用camel标记法将ui自动转换为短横线形式
 <local-component></local-component>
</div>

<script src="https://unpkg.com/vue"></script>

<script>
// 创建局部组件
const localComponent = {
 template: '<div>this is da</div>'
}

// vue实例对象
var vm = new Vue({
 el: '#app',
 // 创建只对当前vue实例对象有效的局部组件
 components: {
  // 注册组件
  localcomponent
 }
});
</script>
var vm = new Vue({
 el: '#app',
 // 创建局部组件
 components: {
  // 注册组件
  'my-component': localComponent
 }
});

组件对象的分析

vue组件就是一个vue实例:

// 自定义组件
var dada = Vue.component('my-component', {
 template: '<h1>dada</h1>'
});

组件只允许有唯一一个根元素,这样也行:

// 自定义
const dada = Vue.component('my-component', {
 template: `
  <div>
   <span>达达前端</span>
   <p> this is da</p>
  </div>
  `
});

在组件中使用template标签:

<div id='app'>
 <h1>my-component</h1>
 <my-component></my-component>
</div>

<template id="my">
 <div>this is dada</div>
 <p>this is dadadada</p>
</template>

<script..></script>

<script>
 // 自定义组件
 const my = Vue.component('my-component", {
  template: '#my'
 });
 // vue实例对象
 var vm = new Vue({
  el: '#app'
 });
</script>

// 会出现程序错误
因为vue组件只允许有一个根元素。

组件template属性中包含div与P两个元素
<template id="my">
 // 组件只允许有一个根元素
 <div>
  <div>da</div>
  <p>da</p>
 </div>
</template>

// 成功

vue组件中的data属性

在组件中,可以使用任何有效的Vue实例对象属性。data属性是Vue组件可用的响应式数据,它是Vue实例的数据对象。在创建实例后,用户可以通过vm.$data访问原始数据对象,Vue实例也代理了data的所有属性。

即vm.a 等价于 vm.$data.a,以"_"或者是"$"开头的属性不会被Vue实例代理,因为它们可能和Vue内置的属性以及api方法产生冲突。

// 创建一个实例
var vm = new Vue({
 data: data
})
vm.a // => 1
vm.$data === data // => true

// Vue.extend()中的data
var Component = Vue.extend({
 data: function() {
  return { a: 1 }
 }
})

data属性必须声明为返回一个初始数据对象的函数。


<div id="app">
 <h1>my-component</h1>
 <my-component></my-component>
 <h2>my</h2>
 <my-component></my-component>
</div>

<template id="my">
 <div>
  <div>this is my</div>
  <p>this is da</p>
  <p>{{message}}</p>
  <button @click="message = 'update message'">
  修改
  </button>
 </div>
</template>

<script src="https://unpkg.com/vue"></script>

<script>
 var data={
  message: 'global'
 }
 // 全局组件
 const my = Vue.component('my-component', {
  template: '#my',
  // data属性表示当前组件使用的数据信息
  // data属性必须是回调函数形式,在回调函数中要返回对象
  data: function() {
   return data;
  }
});
 // Vue实例对象
 var vm = new Vue({
  el: '#app'
 });
</script>
// 全局组件
const my = Vue.component('my-component',{
 template: '#my',
 // data属性表示当前组件使用额数据信息
 // data属性必须是回调函数形式,在回调函数中要返回对象
 // data属性应该返回一个都有的对象
 data: function() {
  return {
   message: 'component-message'
  };
 }
});

props传递数据

父组件和子组件之间的通信使用props,是组件数据中的一个字段,子组件使用props来获取父组件的数据,props可以是字面量语法,动态语法,绑定修饰符等。

props字面量,子组件通过props声明待接收的父组件数据,父组件中使用子组件,通过HTML属性为子组件传递数据。

子组件:

const my = {
 // props:声明接收父组件数据
 props: ['message'],
 // data一样
 template: '<span>{{message}}</span>'
}

父组件:

<my-component message="message from parent by props">
<my-component>
const my = {
 props: ['myMessage'];
 template: '<span>{{message}}</span>'
}
<my-component my-message="hello"></my-component>
子组件props指明数据
Vue.component("my-component",{
 props: ['message'],
 template: '<span>{{message}}</span>'
});
<my-component alt="this is add"></my-component>

动态语法:

<div id="app">
 <my-component v-bind:message="message">
 </my-component>
 <my-component :message="message">
 </my-component>
</div>

v-bind指令将HTML属性绑定到一个表达式上,使用v-bind指令将动态props绑定到父组件的数据。

var vm = new Vue({
 el: '#app',
 data: {
  user: {
   name: 'test',
   age: '12'
  }
 }
});

<div id="app">
<my-component :user="user"></my-component>
<my-component user="user"></my-comoponent>
</div>

绑定修饰符

父组件的属性发生变化时,会传递给子组件

// 默认单向绑定
<child :message="parentMessage"></child>
// 双向绑定
<child :message.sync="parentMessage"></child>
// 单向绑定
<child :message.once="parentMessage"></child>
// 在子组件中修改props都会影响父组件的状态
<div id="example">
 <input type="text" v-model="info.name"/>
 <child v-bind:msg.once = "info"></child>
</div>
<script src="vue.js"></script>

<script>
// 创建根实例
var vm = new Vue({
 el: '#example',
 data: function() {
  return {
   info: {
   name: 'hello'
   }
  }
 },
 components: {
  'child': {
   //声明props
   props: ['msg'],
   template: '<div>{{msg.name}}</div>'
  }
 }
});
</script>
Vue.component('example', {
 props: {
  propsA: 'null',
  // 多种类型
  propM: [String, Number],
  // 必须是字符串
  propB: {
   type: String,
   required: true
  },
  propc: {
   type:Number,
   default: 100
  },
  propD: {
   type: Object,
   default: function() {
    return {msg: 'hello'}
   }
  },
  // 指定props为双向绑定
  propE: {
   twoWay: true
  },
  propF: {
   validator: function() {
    return value > 10
   }
  }
 });

type类型:string,number,boolean,object,function,array.

type可以是一个自定义的构造器。

为props定义一个coerce()函数

Vue.component('example', {
props: {
 // 转换函数
 propG: {
  coerce: function(val) {
   return val+''
  }
 },
 propH: {
  coerce: function(val){
   return JSON.parse(val)
  }
 }
}
})

事件通信

父子组件事件通信,会在HTML中使用元素会有的一些属性,父组件通过props向子组件传递数据,子组件通过events向父组件发送消息。

子组件需要某个数据,可以在内部定义一个props,父组件将data属性传递给子组件的data属性。

// 父组件向子组件传递数据
<my-component :item="users"></my-component

Vue.component('example',{
 template: `<div><button @click="myclick"></button></div>`,
 methods: {
  myclick: function() {
  }
 }
});

父组件向子组件传递数据

子组件向父组件发送消息可以使用vue自定义事件机制。

子组件主要通过使用$emit向父组件触发事件。

父组件使用$on或v-on指令监听子组件触发的事件,并接收子组件发送的消息。

<div id="app">
 <my-component @childevent="handleEvent"></my-component>
</div>
Vue.component('my-component',{
template: '#my-component',
props: ['value'],
methods: {
 emitEvent: function() {
  console.log('child component click event');
  this.$emit('childevent');
 }
}
});
Vue.component('my-component',{
template: '#my-component',
props: ['value'],
methods: {
 emitEvent: function() {
  console.log('child component click event');
  this.$emit('childevent');
 }
}
});
emitEvent: function() {
 this.$emit('childevent','附加数据')
}
handleEvent:function(){
 console.log(arguments[0]);
}

子组件向父组件发送消息。父组件$on或v-on监听子组件触发的事件,接收子组件发送的消息。

<div id="app">
// 使用组件
<my-component :message="message" @my-component-event="handleMyComponentEvent">
</my-component>
<p>message==={{message}}</p>
</div>

<template id="my">
<div>
<p>{{message}}</p>
<p>
 <button @click="handleClick"></button>
</p>
</div>
</template>

<script>
const myComponent={
template: '#my',
props:['message'],
methods:{
handleClick: function(){
this.$emit('my-component-event','updata');
}
}
};
// Vue实例对象
var vm = new Vue({
el: '#app',
data: {
message: 'from parent'
},
// 注册组件
components: {
 myComponent
},
// 方法
methods: {
 // 接收子组件定义事件处理
 handleMyComponentEvent: function(param){
 this.message=arguments[0];
 }
}
});

非父子组件进行事件通信

父组件通过props向子组件传递数据,子组件通过自定义事件向父组件触发动态修改事件。

非父子组件之间的通讯方式

子组件中,通过使用$parent或者$root访问当前组件的父组件或根组件实例对象。

this.$parent父组件
this.$root根组件


var vm = new Vue({
 el: '#app',
 data: {
  message: 'message'
 },
 components: {
  childComponent
 }
});

const childComponent={
 template:'',
 methods:{
 updateRootMessage: function(){
  this.$root.message='message from child';
 }
}
};

父组件访问子组件,使用ref属性,通过this.$refs进行访问子组件

<div id="app">
 <child-component ref="childComponent">
 </child-component>
</div>

var vm = new Vue({
 el: '#app',
 components: {
  childComponent
 },
 methods: {
  updateChild: function(){
   this.$refs.childComponent.message="from parent";
  }
 }
});

事件总线机制

监听订阅on,触发emit。用on方法去监听某个事件,用emit方法去触发这个事件,同时调用这个on方法回调函数,这样就完成了一次事件触发。

var dada = new Vue()
// 触发组件a中的事件
dada.$emit('id-selected',1)
// 触发b创建的函数中监听事件
dada.$on('id-selected', function(id){
})

创建事件总线对象

var dada = new Vue()

监听事件总线所触发的事件

dada.$on

触发自定义事件

dada.$emit

<div id="app">
<child1-component></child1-component>
<child2-component :message="message" ref="child2">
</child2-component>
</div>

<template id="child1">
<div>
<button @click="updateChild2">da</button>
</div>
</template>

<template id="child2">
<div>
message={{message}}
<p>{{name}}</p>
</div>
</template>

<script src="https://unpkg.com/vue">更新2的内容</script>

<script>
const dada = new Vue();
// 创建组件
const child1Component={
 template: '#child1',
 methods: {
  updaeChild2: function(){
   // 使用事件总线触发自定义事件
   dada.$emit('child1-event','update name from child1');
  }
 }
};

const child2Component = {
 template: '#child2',
 props: ['message'],
 data: function() {
  return {
   name: 'child2'
  };
 },
 created: function() {
 // 保留当前vue组件对象
 const app = this;
 // 监听事件总线触发的事件
 bus.$on('child1-event', function(param){
  console.log('捕获');
  app.name = param;
 });
}
};
</script>

?? 不要忘记留下你学习的脚印 [点赞 + 收藏 + 评论]

作者Info:

【作者】:Jeskson
【原创公众号】:达达前端小酒馆。
【福利】:公众号回复 “资料” 送自学资料大礼包(进群分享,想要啥就说哈,看我有没有)!
【转载说明】:转载请说明出处,谢谢合作!~

大前端开发,定位前端开发技术栈博客,PHP后台知识点,web全栈技术领域,数据结构与算法、网络原理等通俗易懂的呈现给小伙伴。谢谢支持,承蒙厚爱!!!



若本号内容有做得不到位的地方(比如:涉及版权或其他问题),请及时联系我们进行整改即可,会在第一时间进行处理。


请点赞!因为你们的赞同/鼓励是我写作的最大动力!

欢迎关注达达的CSDN!

这是一个有质量,有态度的博客

原文地址:https://www.cnblogs.com/dashucoding/p/12026297.html

时间: 2024-10-08 03:27:06

来吧!一文彻底搞定Vue组件!的相关文章

一篇搞定vue请求和跨域

vue本身不支持发送AJAX请求,需要使用vue-resource.axios等插件实现 axios是一个基本Promise的HTTP请求客户端,用来发送请求,也是vue2.0官方推荐的,同时不再对vue-resource进行更新和维护 axios发送AJAX请求 安装axios npm install axios -S 基本用法 axios([options]) axios.get(url[,options])  传参方式:1.通过url 传参   2.通过params选项传参 axios.p

来吧!一文彻底搞定哈希表!

哈希表是个啥? 小白: 庆哥,什么是哈希表?这个哈希好熟悉,记得好像有HashMap和HashTable之类的吧,这是一样的嘛??? 庆哥: 这个哈希确实经常见??,足以说明它是个使用非常频繁的玩意儿,而且像你说的HashMap和HashTable之类的与哈希这个词肯定是有关系的,那哈希是个啥玩意啊,这个咱们还是得先来搞明白啥是个哈希表.?? 我们看看百科解释吧: 散列表(Hash table,也叫哈希表),是根据键(Key)而直接访问在内存存储位置的数据结构.也就是说,它通过计算一个关于键值的

程序收藏不看系列:一文轻松搞定系统限流

1. 我们为什么需要限流 为了"反脆弱",在微服务复杂拓扑的情况下,限流是保障服务弹性和拓扑健壮的重中之重. 想一想,如果业务推出了一个秒杀活动,而你没有任何的限流措施:当你搭建了一个账号平台,而完全没有对十几个业务方设定流量配额--这些很有可能在特定场合下给你的产品带来大量的业务损失和口碑影响. 我们通常重点关注产品业务层面正向和逆向功能的完成,而对于逆向技术保障,这一点则是企业发展过程中很容易忽视的,所以一旦业务快速增长,这将给你的产品带来很大的隐患. 当然,也不是所有的系统都需要

用ORM的思想操作XML文档,一个对象就搞定不要太简单。滚蛋吧!XmlDocument、XmlNode、Xml***……

大家有没有这样的感受,一涉及XML文档操作就得百度一遍.是不是非!常!烦!.各种类型,各种方法,更别提为了找到一个节点多费劲.本来想写个XML操作的工具方法,写了两行一想既然XML文档是有规律的,如果抽象成一个树形结构的类,查找节点是不是就可以用lambda了,创建修改都是操作类,那不是好用得飞起!说干就干,经过两天打磨,终于是大功告成.系统默认的XML文件相关操作我就不吐槽了,来看看怎么飞起的吧. 设计思路: 写着好多啊,简单来说就是把XML标签分为两类:XmlChildTag子标签和XmlB

如何翻译PPT文档?PPT文档翻译一招搞定

PPT文档怎么翻译?PPT文件中有需要翻译的内容的时候,你还在一个个的复制进网页中搜索然后进行翻译吗?这个方法已经淘汰了,不仅麻烦,还拉低你的工作效率,今天小编来为大家介绍一个翻译PPT文档的方法,教你摆脱死板的翻译方法,翻译PPT也可以轻松搞定!准备工具:文档翻译器还需要提前准备好需要翻译的PPT文件,当然电脑也少不了,这是一个基本的辅助工具哦.好啦,上面的工作就绪后,开始翻译啦:1:打开文档翻译器后,点击左侧功能栏中的文档翻译功能,之后点击页面内的[点击上传文档]按钮添加要进行翻译的PPT文

在vue中使用基于d3为基础的dagre-d3.js搞定一个流程图组件

项目中想搞定一个流程图,开始使用了阿里的G6,但是G6目前不支持手势,这样就很郁闷了,因为公司的领导都是使用iPad看的,你不支持手势是不行的,后来又想到了百度的echarts,试了试,感觉还不错,手机端也是没问题的,但是用起来不是很好用,每个节点的位置还要自己去设置计算有点麻烦,所以想找个在支持pc和wap并且使用方便的,结果找到了dagre-d3.js,完全满足我的需求啊,就是文档不全,还大多数都是英文.搞完之后觉得有必要记录一下,哈哈哈. 首先避免不了的就是下载,既然是基于d3的肯定是要连

只需一句话就能搞定NVelocity模板引擎,源码+解析+文档+资料+注释

好长时间不发技术方面的动态了,今天无聊就发篇关于NVelocity的技术文章吧,这门技术来源于java开源项目Velocity,比较好用,其他的我也不过多介绍了,没听过的在文章末尾会有介绍,下面我们就实战吧~ 咱们直接上最简单的方法,一句话搞定: DNTNvelocityHelper.NvelocityTemplate(context.Request.MapPath("~/NVelocity/templates/"), context, "Templater_index.dn

【RabbitMQ】一文带你搞定RabbitMQ延迟队列

本文口味:鱼香肉丝? ?预计阅读:10分钟 一.说明 在上一篇中,介绍了RabbitMQ中的死信队列是什么,何时使用以及如何使用RabbitMQ的死信队列.相信通过上一篇的学习,对于死信队列已经有了更多的了解,这一篇的内容也跟死信队列息息相关,如果你还不了解死信队列,那么建议你先进行上一篇文章的阅读. 这一篇里,我们将继续介绍RabbitMQ的高级特性,通过本篇的学习,你将收获: 什么是延时队列 延时队列使用场景 RabbitMQ中的TTL 如何利用RabbitMQ来实现延时队列 二.本文大纲

一步一步搞定Python3.6编码问题

Python中的编码问题很蛋疼,我们遇到这类问题有时候会使用下面几个步骤处理该问题: 1:这么低级问题,别问同事了太丢人,赶紧百度: 2:卧槽,出了一堆广告,骂个娘,赶紧找相关解决问题方式: 3:尼玛,终于搞定,原来这么简单,赶紧搞定其它工作,晚上回头在查原因: 4:傻B单位每天加班,到家都11点了,赶紧洗洗睡了:等会,先来局王者农药...... 5:编码问题早就忘了: 6:过了几天又出现编码错误,,从第1步开始重新来过. 今天我们就花一局王者农药时间搞定Python3.6的编码问题. 搞清楚编