zoukankan      html  css  js  c++  java
  • 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特性来实现

    代码

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

  • 相关阅读:
    [学习笔记]基于值域预处理的快速 GCD
    [学习笔记]整除偏序与zeta变换、Möbius变换、lcm卷积、gcd卷积
    [学习笔记]MinMax容斥
    [学习笔记]Pollard Rho算法
    [学习笔记]Miller Rabin测试
    [学习笔记]万能欧几里得
    用C#写程序安装包 Joe
    linux 命令
    几个有用的php字符串过滤,转换函数
    linux挂载 Windows分区
  • 原文地址:https://www.cnblogs.com/BUBU-Sourire/p/11429016.html
Copyright © 2011-2022 走看看