• Vue-组件


    一、组件的两种使用方法

    二、使用props传递数据

    三、单向数据流

    四、组件中的命名方式

    五、数据验证

    六、组件通信

    七、slot(插槽)

    八、动态组件

    Vue中的组件

    • 组件是可复用的Vue实例
    • 命名组件推荐使用小写字母,用-连接
    • 在组件定义中,除了template,其它选项还有:data,methods,computed
    • 组件定义中的data必须是一个方法

    一、组件的两种使用方法

    全局注册

    <my-component></my-component>
    Vue.component('my-component',{
       template: '<div>组件内容</div>'
    })

    局部注册

    var app = new Vue({
       el:'#app',
       components:{
           ''my-components:{
                template:'<div>组件内容</div>'
            }
         }  
    })

    二、使用props传递数据

    这边的props采用数组方式

    父组件向子组件传递数据

    v-bin动态绑定父组件传的内容

    <div id="app" style="300px;height:200px;border:2px solid skyblue">
      <child-component msg="我是父组件的内容"></child-component>
      <hr>
     <!--  v-bind进行动态数据动态绑定 将input中的sth传给子组件 -->
      <input type="text" v-model="dadmsg">
      <bind-component :sth="dadmsg"></bind-component>
    </div>
    var app = new Vue({
      el: '#app',
      data: {
        dadmsg: 'happy'
      },
      components: {
        'child-component': {
          props: ['msg'],
          template: '<div>{{msg}}</div>'
        },
        'bind-component': {
          props: ['sth'],
          template: '<div>{{sth}}</div>'
        }
      }
    })

    在组件中使用props来从父组件接收参数,在props中的属性,都可以在组件中直接使用。

    三、单向数据流

    概念理解:通过props传递数据是单向的,父组件变化时数据会传给子组件,但是反过来不行。

    目的:是将父子组件解稿,避免子组件修改无意间修改了父组件的状态。

    两种改变prop的情况的应用场景

    • 父组件传递初始值,子组件可以将它作为初始值保存起来,在自己的作用域下可以随意进行修改;
    • 将传递进来的数据作为初始值进行保存
    1. 注册组件
    2. 将父组件的数据传递进来,并在子组件中props接收
    3. 将传递进来的数据通过初始值保存起来
    <div id='app'>
      <child-component msg='今天也要努力啊'></child-component>
    </div>
    let app = new Vue({
      el: '#app',
      components: {
        'child-component': {
          props: ['msg'],
          template: '<div>{{count}}</div>',
          data() {
            return {
              count: this.msg
            }
          }
        }
      }
    })

    prop作为需要被转变的原始值传入,用计算属性对其再次进行计算

    1. 注册组件
    2. 将父组件的数据传递进来,并在子组件中使用props接收
    3. 将传递进来的数据通过计算属性进行重新计算并渲染到页面
    <div id="app">
      <input type="text" v-model="width">
      <width-component :width='width'></width-component>
    </div>
    let app = new Vue({
      el: "#app",
      data: {
         0
      },
      components: {
        'width-component': {
          props: ['width'],
          template: '<div :style="style"></div>',
          computed: {
            style() {
              return {
                 this.width + 'px',
                background: 'red',
                height: '30px'
              }
            }
          }
        }
      }
    })

    四、组件中的命名方式

    camelCased (驼峰式)

    kebab­case(短横线命名)

    • 组件中的html中、父组件给子组件传递数据,必须使用短横线命名。  (a-bc √    aBc ×)
    • 在props中,短横线命名驼峰命名都可以。
    • 在template中,必须使用驼峰命名,短横线会报错。
    • 在data中,使用this.xxx时,必须使用驼峰命名,短横线会报错。
    • 组件的命名,短横线命名驼峰命名都可以。

    五、数据验证

    这边的props采用对象方式

    可验证的类型:Number  String  Boolean  Array  Object  Function  自定义

    <div id="app">
      <style-component :a='a' :b='b' :c='c' :d='d' :e='e' :g='g'></style-component>
    </div>
    let app = new Vue({
      el: '#app',
      data: {
        a: 1,
        b: '2',
        c: '', //空字符串,就取默认的true
        d: [111, 222, 333],
        e: console.log(),
        g: 3
      },
      components: {
        'styleComponent': {
          props: {
            //数字类型
            a: {
              type: Number,
              required: true //必传
            },
            //字符串类型
            b: {
              type: [String, Number]
            },
            //布尔类型
            c: {
              type: Boolean,
              default: true //默认值
            },
            //数组或对象  默认值是函数形式返回
            d: {
              type: Array,
              default: function() {
                return []
              }
            },
            //函数类型
            e: {
              type: Function
            },
            //自定义一个函数
            g: {
              validator: function(value) {
                return value < 10
              }
            }
    
          },
          template: '<div>{{a}}--{{b}}--{{c}}--{{d}}--{{g}}</div>'
        }
      }
    })

    六 、组件通信

    子组件向父组件传递数据

    ——给父组件添加自定义事件

    ——子组件通过$emit触发事件

    1. 给父组件添加自定义事件
    2. 子组件$emit传出数据
    3. 自定义事件函数接收数据参数并赋值,渲染
    <div id="app">
      <p>您的账户余额为{{num}}</p>
      <btn-component @change='change'></btn-component>
    </div>
    new Vue({
      el: '#app',
      data: {
        num: 3000
      },
      methods: {
        change(value) {
          this.num = value
        }
      },
      components: {
        'btn-component': {
          template: '<div>
                        <button @click="hangle_ad">+1000</button> 
                        <button @click="hangle_re">-1000</button> 
                    </div>',
          data() {
            return {
              count: 3000
            }
          },
          methods: {
            hangle_ad() {
              this.count += 1000
              this.$emit('change', this.count)
            },
            hangle_re() {
              this.count -= 1000
              this.$emit('change', this.count)
            }
          }
        }
      }
    })

    ——v-model代替自定义事件

    v-model实质背后做了两个操作

    1. v-bind绑定一个value属性  (父组件要接收一个value值)
    2. v-on指令给当前元素绑定input事件  (子组件在有新的value值得时候要触发一个input事件)

    所以上面那个银行存款的demo可以改为

    <div id="app">
      <p>您的账户余额为{{num}}</p>
      <btn-component v-model='num'></btn-component>  这边改啦!!
    </div>
    new Vue({
      el: '#app',
      data: {
        num: 3000
      },                               //父组件没有自定义函数啦!!
      components: {
        'btn-component': {
          template: '<div>
                        <button @click="hangle_ad">+1000</button> 
                        <button @click="hangle_re">-1000</button> 
                    </div>',
          data() {
            return {
              count: 3000
            }
          },
          methods: {
            hangle_ad() {
              this.count += 1000
              this.$emit('input', this.count)  //这边改啦!!
            },
            hangle_re() {
              this.count -= 1000
              this.$emit('input', this.count)   //这边改啦!!
            }
          }
        }
      }
    })        

    非父组件之间的通信

    两个非父子关系的组件进行通信,可以使用一个空的Vue实例作为中央事件总线(中介)

    <div id="app">
      <ahandle></ahandle>
      <bhandle></bhandle>
    </div>
    var app = new Vue({
      el: '#app',
      data: {
        bus: new Vue() //bus中介
      },
      components: {
        'ahandle': {
          template: '<div><button @click="aclick">点击向b组件传递数据</button></div>',
          data() {
            return {
              aaa: '我是来自a组件的内容'
            }
          },
          methods: {
            aclick() { //a组件创建事件,供b组件监听   由bus中介$emit提交
              this.$root.bus.$emit('givetob', this.aaa)
            }
          }
        },
        'bhandle': {
          template: '<div>我是b组件</div>',
          created() { //b组件监听a组件创建的事件   由bus中介$on监听
            this.$root.bus.$on('givetob', function(value) { //这里的value就是a组件传进来的this.aaa
              alert(value)
            })
          }
        }
      }
    })

    父链  $.parent

    <div id="app">
    <btn-component></btn-component>--{{msg}}
    </div>
    let app = new Vue({
      el: '#app',
      data: {
        msg: '我是父组件,我现在没有内容'
      },
      components: {
        'btn-component': {
          template: '<button @click="changeFather">点击修改父组件中的内容</button>',
          methods: {
            changeFather() {
              this.$parent.msg = '我现在有内容啦'
            }
          }
        }
      }
    })

    子链 $children

    vue提供索引:$ref

    <div id="app">
      <button @click='getchild'>点击父组件按钮获取a组件内容</button>
      <a-component ref='a'></a-component>   添加索引ref
      <b-component ref='b'></b-component>
      {{msg}}
    </div>
    let app = new Vue({
      el: '#app',
      data: {
        msg: '子组件数据未获得'
      },
      methods: {
        getchild() {
          this.msg = this.$refs.a.msg  //获取a组件的内容 ---refs
        }
      },
      components: {
        'a-component': {
          template: '<span></span>',
          data() {
            return {
              msg: '我是a组件中的内容'
            }
          }
        },
        'b-component': {
          template: '<span></span>',
          data() {
            return {
              msg: '我是b组件中的内容'
            }
          }
        }
      }
    })

    七、slot(插槽)

    使用slot进行分发内容

    编译的作用域

    父组件模板的内容在父组件作用域中编译;

    子组件模板的内容在子组件作用域内编译。

    插槽的用法

    混合父组件的内容与子组件自己的模板

    • 单个插槽
    <div id="app">
      <slotcomponent>
        <p>父组件插入到子组件的内容——我把子组件的slot替换掉啦</p>
      </slotcomponent>
    </div>
    new Vue({
      el: '#app',
      components: {
        'slotcomponent': {
          template: '<slot>父组件没有插入内容没有内容就显示这个</slot>'
        }
      }
    })
    • 具名插槽
        <div id="app">
            <name-component>
                <h2 slot="header">标题</h2>
                <p>内容1</p>
                <p>内容2</p>
                <p slot="footer">底部</p>
            </name-component>
        </div>
     let app = new Vue({
                el: '#app',
                components: {
                    'name-component': {
                        template: '<div> 
                            <div class="header"> 
                                <slot name="header"></slot> 
                            </div> 
                            <div class="container"> 
                                <slot></slot> 
                            </div> 
                            <div class="footer"> 
                                <slot name="footer"></slot> 
                            </div> 
                        </div>'
                    }
                }
            })
    • 作用域插槽
    <div id="app">
      <mycomponent>
        <p slot='aaa' slot-scope='child'>
          {{child.text}} name拿不到
        </p>
      </mycomponent>
    </div>
    let app = new Vue({
      el: '#app',
      components: {
        'mycomponent': {
          template: '<div>
          <slot text="我是子组件插槽的内容" name="aaa"></slot>
          </div>'
        }
      }
    })

    *2.5.0之前都是用template中写,渲染的是template中的内容

    <div id="app">
      <mycomponent>
        <template slot='aaa' slot-scope='child'>
          {{child.text}} name拿不到
        </template>
      </mycomponent>
    </div>

    访问slot

    this.$slot.插槽名称

    在具名插槽的例子前提下添加代码

    ......
    components:{
    ......
    mounted(){
         var header = this.$slots.header
         console.log(header) //此处拿到的是虚拟节点
         var headerin = this.$slots.header[0].elm.innerText
         console.log(headerin)
         }
    }

    八、动态组件

    使用Vue提供的component元素,动态挂载不同的组件

    使用is特性来实现

    代码

    待补充待补充待补充......

  • 相关阅读:
    golang 实现生产者消费者模式(转)
    ssh设置免密登录后登录仍需密码可能的原因,以及 ssh 出问题或的调试方法
    http 请求 Cros 跨域问题记录(转)
    问题解决——SSH时出现WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!(转)
    Git撤销本地commit(转)
    golang project 不显示文件夹 或者某个包明明能 import 但就是 import 不进来,提示Unresolved reference
    Qt6.2.4 qml 实现登录注册及显示详情demo
    Qt6.2.4 qml 实现文件选择与内容读取
    【转载】Qt6.2.4 qml ChartView 实现饼状图与问题解决
    【转载】AntvX6 流程图 demo 基于原生 js 支持导入与导出数据
  • 原文地址:https://www.cnblogs.com/BUBU-Sourire/p/11429016.html
Copyright © 2020-2023  润新知