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


    file

    作者 | 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!

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

    前端技术栈

  • 相关阅读:
    vue使用Highcharts图表
    Laya 骨骼动画播放
    unity3d学习笔记
    unity学习笔记
    Laya本地存储对象,读取上来之后没有类方法了
    Laya2学习笔记
    Laya vscode f5断点调试开启
    fairyGUI学习笔记
    使用docker安装swoole环境
    docker学习笔记
  • 原文地址:https://www.cnblogs.com/dashucoding/p/12026297.html
Copyright © 2020-2023  润新知