• Vue组件化开发


    组件化开发

    标准、分治、重用、组合

    1.组件注册

    命名:驼峰/短横线,驼峰命名的只能在字符串模板中使用驼峰式的组件,在普通的标签模板中需要转化为短横线使用。

    ①全局组件注册

    Vue.component('组件名称',{
        data:对象,组件数据[函数,闭包环境],
        template:组件模板内容[只包含一个根元素;可以是`模板字符串`]
    })
    
    Vue.component('button-counter',{
        data:function(){
            return{
                count:0
            }
        },
        template:'<button @click="handle">点击{{count}}次</button>',
        methods:{
            handle:function(){
                this.count++;
            }
        }
    })
    
    <button-counter></button-counter>
    

    ②局部组件注册

    局部组件只能在注册他的父组件中使用

    var ButtonCounter = {
        data:function(){
            return{
                count:0
            }
        },
        template:'<button @click="handle">点击{{count}}次</button>',
        methods:{
            handle:function(){
                this.count++;
            }
        }
    })
    
    
    components:{
        'button-counter':ButtonCounter
    }
    

    2.Vue调试工具vue-devtools

    3.组件间数据交互

    父--->子 方式 父组件 子组件 其他
    属性props,组件内部通过props接收传递过来的值 <menu-item :title='ptitle' content='hello'></menu-item> props:['title','content']
    引用refs(dom操作) <hello-word ref="hw"></hello-word>
    this.$refs.hw.foo ='bar'
    // data
    foo:'foo'
    子元素children this.$children[0].foo = 'dong' 子元素不保证顺序,也不是响应式。数组只读。
    子--->父 方式 父组件 子组件 其他
    $emit(自定义事件,携带参数) <menu-item title='来自父组件的值' @enlarge-text='handle($event)'></menu-item> <div @click='$emit("enlarge-text",5)'>扩大字体大小</div> 观察者模式
    非父子组件
    1 任意两个组件 事件中心(事件总线)或vuex
    2 兄弟组件 通过$parent共同的父组件进行传递
    祖先--->后代 祖先 后代
    provide/inject // 和data同级
    provide:{
    foo:'foo'
    }
    // 和data同级
    inject:['foo']
    用于高阶插件/组件库开发,不推荐直接用于应用程序代码。

    created->mounted:父组件先于子组件加载。

    ①父组件向子组件传值

    1️⃣属性props

    • 组件内部通过props接收传递过来的值

    props:使用驼峰形式,模板中使用短横线形式;字符串形式的模板中没有限制。

    props:['menuTitle']-------------menu-title

    • props属性
      • 字符串string:pstr
      • 数值number::pnum数值,pnum字符串
      • 布尔boolean::pboo布尔,pboo字符串
      • 数组array:parr
      • 对象object:pobject
    // 子组件
    Vue.component('menu-item',{
        props:['title','content'],
        data:function(){
            return{
                msg:'子组件数据'
            }
        },
        template:'<div>{{msg + "---" + title + content}}</div>',
    })
    
    • 父组件通过属性将值传递给子组件
    <!-- 父组件 -->
    <menu-item title='来自父组件的值'></menu-item>
    <menu-item :title='ptitle' content='hello'></menu-item>
    
    data:{
        ptitle:'动态绑定属性'
    }
    

    2️⃣引用refs

    应用场景:dom操作

    • 父组件
    <hello-word ref="hw"></hello-word>
    
    this.$refs.hw.foo ='bar'
    
    • 子组件
    // data
    foo:'foo'
    

    3️⃣子元素children

    • 父组件
    this.$children[0].foo = 'dong'
    

    注:子元素不保证顺序,也不是响应式。数组只读。

    ②子组件向父组件传值

    props传递数据原则:单向数据流,只允许父组件向子组件传递数据,不允许子组件直接操作数据

    观察者模式:子组件派发,父组件监听。事件真正的监听者是子组件(谁派发谁监听)。

    • 子组件通过自定义事件$emit(自定义事件,携带参数)向父组件传递信息
    // 子组件
    Vue.component('menu-item',{
        props:['title'],
        template:`
    		<div>
    			<div @click='$emit("enlarge-text",5)'>扩大字体大小</div>
    		</div>		`
    })
    
    • 父组件模板中监听子组件的事件,事件名称需要一致enlarge-text,获取参数$event
    <!-- 父组件 -->
    <div :style='{fontSize:fontSize+"px"}'>{{pmsg}}</div>
    <menu-item title='来自父组件的值' @enlarge-text='handle($event)'></menu-item>
    
    // 父组件中
    data:{
        pmsg:'hello',
        fontSize:10
    }
    // 子组件传递参数val=5
    methods:{
        handle:function(val){
            this.fontSize += val;
        }
    }
    

    ③非父子组件间传值(任意两个组件之间)

    1️⃣任意组件

    事件中心(事件总线)或vuex

    • 单独的事件中心(事件总线)管理组件间的通信
    image-20200831194931460
    var eventHub = new Vue();
    
    • 监听事件与销毁事件
    // 'add-todo'事件名称,addTodo事件函数
    mounted:function(){
        eventHub.$on('add-todo',addTodo)
    }
    
    eventHub.$off('add-todo')
    
     eventHub.$on('add-todo',(val)=>{
         this.num += val
     })
    
    • 触发事件
    handle:function(){
        eventHub.$emit('add-todo',id)
    }
    
    • 事件中心(事件总线),全局
    // main.js
    Vue.prototype.$bus = new Vue()
    
    // child1
    this.$bus.$on('foo',handle)
    // child2
    this.$bus.$emit('foo')
    

    2️⃣兄弟组件

    通过$parent共同的父组件进行传递

    ④祖先和后代

    由于嵌套层数过多,传递props不切实际,可以使用provide/inject

    单向传值:祖先->后代

    应用:用于高阶插件/组件库开发,不推荐直接用于应用程序代码。

    // 祖先
    provide(){
        return {foo:'foo'}
    }
    //后代
    inject:['foo']
    
    • 父组件
    // template
    <hello-word></hello-word>
    
    // 和data同级
    provide:{
        foo:'foo'
    }
    
    // 传动态的值
    provide(){
        return {foo:this.val}
    }
    
    data(){
        return {
            val:123
        }
    }
    
    • 子组件
    // 和data同级
    inject:['foo']
    

    4.组件插槽 模板内容

    分类 子组件 父组件(插槽内容)
    匿名插槽 <slot>默认内容</slot> <error-box>有bug发生</error-box>
    具名插槽 <slot name="header"></slot> <h1 v-slot:header>标题内容</h1>
    作用域插槽 <slot :item="item">{{item.name}}</slot> <template v-slot:default="scope">
    {{scope.item.name}}
    </template>

    父组件向子组件传递内容

    image-20200831195514415

    ①匿名插槽

    • 插槽位置,子组件模板做
    // 子组件预留一个插槽位置slot
    Vue.component('error-box',{
        template:`
    		<div>
    			<strong>ERROR:</strong>
    			<slot>默认内容</slot>
    		</div>		`
    })
    
    • 插槽内容
    <!-- 父组件传递插槽内容 -->
    <error-box>有bug发生</error-box>
    

    ②具名插槽

    根据名称匹配,没有匹配到的放到默认<slot>中。

    v-slot 2.6.0引入slot 被官方废弃。

    <!-- 子组件插槽定义 -->
    <div>
        <header>
            <slot name="header"></slot>
        </header>
        <main>
            <slot></slot>
        </main>
        <footer>
            <slot name="footer"></slot>
        </footer>
    </div>
    
    
    <!-- 父组件插槽内容 -->
    <!-- 一个标签 -->
    <base-layout>
        <h1 v-slot:header>标题内容</h1>
        <p>主要内容1</p>
        <p>主要内容2</p>
        <p v-slot:footer>底部内容</p>
    </base-layout>
    
    <!-- 父组件插槽内容 -->
    <!-- template多个标签 -->
    <base-layout>
        <template v-slot:header>
            <h1>标题内容1</h1>
            <h1>标题内容2</h1>
        </template>
        <p>主要内容1</p>
        <p>主要内容2</p>
        <template v-slot:footer>
            <p>底部内容1</p>
            <p>底部内容2</p>
        </template>
    </base-layout>
    

    ③作用域插槽

    应用场景:父组件获取子组件的内容并进行加工处理

    2.6.0以后 slot-scope 废弃,使用v-slot

    // 子组件插槽定义 提供slot位置,绑定属性item
    Vue.component('fruit-list',{
    	props:['list'],
    	template:`
            <div>
                <li v-for="item in list" :key="item.id">
                    <slot :item="item">{{item.name}}</slot>
                </li>
            </div>
    		`
    })
    
    <!-- 父组件 -->
    <!-- slot-scope(v-slot)可以得到子组件绑定的属性item -->
    <!-- 也可以解构直接写item,v-slot:default="item" -->
    <fruit-list :list="list">
    	<template v-slot:default="scope">
        	<strong v-if="scope.item.id==2" class="current">{{scope.item.name}}</strong>
            <span v-else>{{scope.item.name}}</span>
        </template>
    </fruit-list>
    
    date:{
        list:[{
            id:1,
            name:'apple'
        },{
            id:2,
            name='orange'
        }]
    }
    
  • 相关阅读:
    php环境搭建工具包推荐
    Android视频直播解决方案(rstp、udp)
    软件版本号命名
    附加数据库失败,无法升级数据库,因为它是只读的
    Web Api如何传递POST请求
    找回Reshaprer的Alt+Enter快捷键的方法
    asp.net 实现在线打印功能,jQuery打印插件PrintArea实现自动分页
    asp.net 回发或回调参数无效的各种情况分析及解决办法
    MQTT, XMPP, WebSockets还是AMQP?泛谈实时通信协议选型 good
    echarts 专题
  • 原文地址:https://www.cnblogs.com/wattmelon/p/13592266.html
Copyright © 2020-2023  润新知