来吧!一文彻底搞定Vue组件!_一文彻底搞定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 // => 1vm.$data === data // => true
// Vue.extend()中的datavar 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'); }}});

 

  •  
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>

> 【作者】:Jeskson

> 【转载说明】:转载请说明出处,谢谢合作!~

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

意见反馈

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

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