vue.js---组件

作者: 学的会的前端 | 来源:发表于2019-08-09 09:37 被阅读6次

组件的作用

作用: 提高代码的可复用性。

组件的使用方法

  1. 全局注册:
  • 形式
Vue.component(tag,{
template:'<div></div>'
})
  • 代码示例:
<div id = "app">
  <!--可以把它当做HTML标签使用-->
  <my-component></my-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
  //注册组件名为my-component的组件
  Vue.component('my-component',{
    template:'<div>我是一个组件</div>'
  });
  var app = new Vue({
      el: "#app",
      data: {}
  })
</script>
  • 优点:所有的Vue示例都可以使用。
  • 缺点:权限太大,容错率降低。
  1. 局部注册:
  • 代码示例:
<script>
  var app = new Vue({
      el: '#app',
      components: {
        'app-component':{
          template:'<div>我是一个局部组件</div>'
        }
      }
  })
</script>
  1. html标签限制

vue组件的模板在某些情况下会受到html标签的限制,比如 <table> 中只能有 <tr> , <td> 这些元素,所以直接在table中使用组件是无效的,此时可以使用is属性来挂载组件。

  • 代码示例:
<div id = "app">
  <table>
      <!--<my-component></my-component>-->
      <tbody is = "my-component"></tbody>
  </table>
</div>

组件是使用技巧----奇淫技巧

  1. 推荐使用小写字母加-­进行命名(必须) 。child, my-­componnet命名组件

  2. template中的内容必须被一个DOM元素包括 ,也可以嵌套

  3. 在组件的定义中,除了template之外,还可以使用其他选项:data,computed,methods

  4. 在组件中使用data必须是一个方法。

  5. 代码示例:解决点击一个按钮,两个都进行加的操作

<body>
    <div id = "app">
        <button @click = "plus">点击加{{count}}</button>
        <button @click = "plus">点击加{{count}}</button>
        <hr/>
        <btn-component></btn-component>
        <btn-component></btn-component>

    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
    var app = new Vue({
        el: "#app",
        data: {
          count: 1
        },
        components: {
          'btn-component':{
            template:'<button @click = "count++">{{count}}</button>',
              data: function(){
              return {
                //每次返回的count是不一样的
                count: 0
              }
              }
          }
        },
        methods: {
          plus:function(){
            this.count ++;
          }
        }
    })
</script>
</body>

使用props传递数据 (父亲向儿子传递数据)

  1. 在组件中使用props来从父亲组件接收参数,注意,在props中定义的属性,都可以在组件中直接使用

  2. propps的数据来自父级,而组件中data 中return的数据就是组件自己的数据,两种情况作用域就是组件本身,因此这两种属性都可以在template,computed,methods中直接使用。

  3. props的值有两种,一种是字符串数组,一种是对象

  4. 可以使用v-­bind动态绑定父组件来的内容

  5. 代码示例:

<body>
在父组件向子组件传递消息:
<hr/>
<div id = "app" style = "border: 2px solid chartreuse;height: 360px;">
    <h5 style = "text-align:center">我是父组件</h5>
    <!--child-component就是app这个父组件的子组件,msg就是父组件传递给子组件的信息-->
    确定要传递的数据:(使用v-bind与否的区别)
    不使用:msg的时候,msg默认传入的是字符串
    <child-component msg = "[3,6,8]"></child-component> //msg.length = 7
    加了:msg,对传入的数据会进行自动识别
    <child-component :msg = "[3,6,8]"></child-component> //msg.length = 3
    <hr/>
    v-bind动态的传递数据---把input中parentmsg传递给子组件:
    <input type = "text" v-model = "parentmsg">
    <bind-component :msg = "parentmsg"></bind-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
    var app = new Vue({
        el: '#app',
        data: {
          parentmsg: '今天月亮真圆'
        },
        components: {
          'child-component':{
            props:['msg'],
            template: '<div style = "border: 1px solid red;height: 80px">{{msg.length}}</div>'
          },
            'bind-component':{
            props:['msg'],
        template: '<div style = "border: 1px solid red;height: 80px">{{msg}}</div>'
            }
        }
    })
</script>
</body>

单向数据流

  • 单向数据流含义 : 通过props传递数据是单向的了, 也就是父组件数据变化时会传递给子组件,但是反过来不行。

  • 目的 :是尽可能将父子组件解稿,避免子组件无意中修改了父组件的状态。

  • 应用场景: 业务中会经常遇到两种需要改变 props 的情况

  1. 一种是父组件传递初始值进来,子组件将它作为初始值保存起来,在自己的作用域下可以随意使用和修改。这种情况可以在组件 data 内再声明一个数据,引用父组件的 prop
    步骤一:注册组件
    步骤二:将父组件的数据传递进来,并在子组件中用props接收
    步骤三:将传递进来的数据通过初始值保存起来
<body>
<div id = "app">
  <my-component msg = "我是父组件传递的数据"></my-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
  //注册组件
  Vue.component('my-component',{
    props: ['msg'],
    template: '<div>{{count}}</div>',
      //将传递进来的数据通过初始值保存起来
      data: function(){
      return {
        //props中的值可以通过this.xxx直接来进行获取
          count:this.msg
          //无论msg如何变化,都会传递给count,只需要维护count即可
      }
      }
  });
  var app = new Vue({
      el: '#app'
  })
</script>
</body>
  1. 另一种情况就是 prop 作为需要被转变的原始值传入。这种情况用计算属性就可以了
    步骤一:注册组件
    步骤二:将父组件的数据传递进来,并在子组件中用props接收
    步骤三:将传递进来的数据通过计算属性进行重新计算
<body>
<div id = "app">
  <!--需求:通过input中输入的书直接改变div的宽度-->
  传递的width仅仅是一个数据
  <input type = "text" v-model = "width">
  <width-component :width = "width"></width-component>

</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
  Vue.component('width-component',{
    props: ['width'],
      template: '<div :style = "style"></div>',
      //将传递进来的数据通过计算属性重新计算
      computed: {
        style: function(){
          //return的值就是style
          return {
            width:this.width + 'px',
              background: 'red',
                height: '30px'
          }
        }
      }
  });
  var app = new Vue({
      el: '#app',
      data: {
        width: 0
      }
  })
</script>
</body>

数据验证

vue组件中camelCased (驼峰式) 命名与 kebab­case(短横线命名)

  • 在html中, myMessagemymessage是一致的,在组件中的html中使用必须使用kebab-­case(短横线)命名方式。在html中不允许使用驼峰!!!

  • 在组件中, 父组件给子组件传递数据必须用短横线。在template中,必须使用驼峰命名方式,若为短横线的命名方式。则会直接保错。

  • 在组件的data中,用this.XXX引用时,只能是驼峰命名方式。若为短横线的命名方式,则会报错。

验证的 type 类型可以是:
• String
• Number
• Boolean
• Object
• Array
• Function

  • 相关代码示例:
    Vue.component('type-component',{
      //props中堆数据进行限定,必须使用对象
        props: {
          //限定a传入的数据必须是string
          a: String,
            //限定b传入的数据可以是string也可以是Number
            b: [String,Number],
            //c是布尔类型,默认值是true。既要指定默认值又要指定类型,就使用对象type--required--default
            c:{
            type:Boolean,
                default: true
            },
            //穿入的是数字,而且是必须传入
            d: {
            type: Number,
                required: true
            },
            //如果是数组或对象,默认值必须是一个函数来返回
            e: {
            type: Array,
                default: function(){
                  //如果不向子组件传递e,默认取值333
                  return [333];
                }
            },
            //自定义一个验证函数
            f: {
            validator: function(value){
              //value就是传入的值88,<10就会报错
              return value > 10
            }
            },
            //定义一个function
            g: {
            type:Function
            }
        },
        template:'<div>{{a}}---{{b}}--{{c}}--{{d}}--{{e}}--{{f}--{{g}}</div>'
    });

组件通信

组件关系可分为父子组件通信、兄弟组件通信、跨级组件通信

自定义事件—子组件给父组件传递数据

使用v­-on 除了监昕 DOM 事件外,还可以用于组件之间的自定义事件。

  • JavaScript 的设计模式 一一观察者模式, dispatchEventaddEventListener这两个方法。 Vue 组件也有与之类似的一套模式,子组件用$emit()来 触发事件 ,父组件用
    $on()来 监昕子组件的事件 。

  • 代码示例:
    第一步:自定义事件
    第二步: 在子组件中用$emit触发事件,第一个参数是事件名,后边的参数是要传递的数据
    第三步:在自定义事件中用一个参数来接受

<div id = "app">
    您现在的银行卡余额是:{{total}}
    //在父组件的作用域中定义一个自定义事件
    <son-component @change = "handleTotal"></son-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
    //需求,通过加号按钮和减号按钮来给父组件传递数据
    //子组件的count值随时随地的赋值给父组件的total
    Vue.component('son-component',{
      template: '<div> <button @click = "handleincrease">+1000</button>\<button @click = "handlereduce">-1000</button></div>',
        data: function(){
        return {
          count:1000
        }
        },
        methods: {
      handleincrease:function(){
        this.count = this.count + 1000;
            //触发自定义事件
          this.$emit('change',this.count)
      },
      handlereduce:function(){
        this.count = this.count - 1000;
        this.$emit('change',this.count)
      }
        }

    });
    var app = new Vue({
        el: '#app',
        data: {
          total: 2000
        },
        //自定义事件要接受一个参数
        methods: {
          handleTotal: function(value){
            //此处的形参value就是传递过来的数据,就是this.count
              this.total = value;
          }
        }
    })
</script>

在组件中使用v-model

  • $emit的代码,这行代码实际上会触发一个input事件, input后的参数就是传递给v­model绑定的属性的值.
  • v­-model 其实是一个语法糖,这背后其实做了两个操作
    1. v-­bind 绑定一个 value属性
    2. v-­on 指令给当前元素绑定 input 事件
  • 要使用v­-model,要做到:

    1. 接收一个 value 属性。
    2. 在有新的 value 时触发input 事件
  • 具体代码示例

<div id = "app">
    您现在的银行卡余额是:{{total}}
    <son-component v-model = "total"></son-component>
    v-model其实就是绑定了input事件,当触发input时候,input事件就会自动接收传递过来的参数,并赋值给已经绑定的total。
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
  //需求,通过加号按钮和减号按钮来给父组件传递数据
  Vue.component('son-component',{
    template: '<div> <button @click = "handleincrease">+1000</button>\</div>',
    data: function(){
      return {
        count:1000
      }
    },
    methods: {
      handleincrease:function(){
        this.count = this.count + 1000;
        //触发自定义事件(注意此处)
        this.$emit('input',this.count)
      }
    }

  });
  var app = new Vue({
    el: '#app',
    data: {
      total: 2000
    }
  })
</script>

非父组件之间的通信

image.png
  • 代码示例:
<body>
<div id = "app">
    <my-acomponent></my-acomponent>
    <my-bcomponent></my-bcomponent>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
    Vue.component('my-acomponent',{
      template: '<div><button @click = "handle">点击我向b组件传递数据</button></div>',
        data: function(){
        return {
          aaa: '我是来自a组件的内容'
        }
        },
        methods: {
          handle: function(){
                //在子组件中访问根组件this.$root
              this.$root.bus.$emit('lala',this.aaa);
          }
        }
    });
  Vue.component('my-bcomponent',{
    template: '<div></div>',
      created: function(){
      //a组件在实例创建的时候就监听事件---lala事件
          //function中的参数传多少就有多少
          this.$root.bus.$on('lala',function(value){
            alert(value)
          })
      }
  });
    var app = new Vue({
        el: '#app',
        data: {
          //bus中介
            bus: new Vue()
        }
    })
</script>
</body>
  • 父链:this.$parent
Vue.component('child-component',{
    template: '<button @click = "setFatherData">通过点击我修改父亲的数据</button>',
      methods: {
      setFatherData:function(){
        this.$parent.msg = '数据已经修改了'
      }
      }
  });
  • 子链:this.$refs

提供了为子组件提供索引的方法,用特殊的属性ref为其增加一个索引

    <my-acomponent ref = "a"></my-acomponent>
    <my-bcomponent ref = "b"></my-bcomponent>
    <child-component ref = "c"></child-component>  
    var app = new Vue({
        el: '#app',
        data: {
          //bus中介
            bus: new Vue(),
            msg: '数据还未修改',
            formchild: '还未拿到'
        },
        methods: {
          getChildData: function(){
            //用来拿子组件中的内容
              this.formchild = this.$refs.a.msg;
          }
        }

    })

什么是slot(插槽)

为了让组件可以组合,我们需要一种方式来混合父组件的内容与子组件自己的模板。这个过程被称为内容分发。Vue.js 实现了一个内容分发 API,使用特殊的 slot 元素作为原始内容的插槽。

编译的作用域

在深入内容分发 API 之前,我们先明确内容在哪个作用域里编译。假定模板为:\

<child-component>
{{ message }}
</child-component>

message 应该绑定到父组件的数据,还是绑定到子组件的数据?答案是父组件。

组件作用域简单地说是:

  1. 父组件模板的内容在父组件作用域内编译;<div id = "app"></div>内的是父组件的作用域。

  2. 子组件模板的内容在子组件作用域内编译,template中的是子组件的作用域。

插槽的用法

父组件的内容与子组件相混合,从而弥补了视图的不足

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

  • 单个插槽:
<body>
<div id = "app">
    <my-component>
        //在子组件中渲染出父组件的内容,sort中的内容会替换成p中的内容
        <p>我是父组件插入的内容</p>
    </my-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
    Vue.component('my-component',{
      template: '<div> <slot>如果父组件没有内容,我就自动出现 </slot></div>'
    });
    var app = new Vue({
        el: '#app'
    })
</script>
</body>
  • 具名插槽:
    根据不同的视图和div使用不同的插槽
<body>
<div id = "app">
    <name-component>
        <h3 slot = "header">我是标题</h3>
        <p>我是正文内容</p>
        <p>我是正文内容有两段</p>
        <p slot = "footer">我是底部信息</p>
    </name-component>

</div>
<!--视图不变,数据变-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
  Vue.component('name-component',{
    template: '<div> <div class = "header">\n' +
    '\t<slot name = "header">\n' +
    '\t\t\n' +
    '\t</slot>\n' +
    '</div>\n' +
    '<div class = "container">\n' +
    '\t<slot>\n' +
    '\t\t\n' +
    '\t</slot>\n' +
    '</div>\n' +
    '<div class = "footer">\n' +
    '\t<slot name = "footer">\n' +
    '\t\t\n' +
    '\t</slot>\n' +
    '</div>\n</div>'
  });

  var app = new Vue({
    el: '#app'
  })
</script>
</body>

作用域插槽

主要作用: 从子组件中获取数据。

作用域插槽是一种特殊的slot,使用一个可以复用的模板来替换已经渲染的元素
-------slot-scope
====template模板是不会被渲染的。sort替换的是template里面的内容。
——从子组件获取数据

<body>
<div id = "app">
    <my-component>
        <!--一定要在template模板中使用,prop是临时变量名,任意取-->
            <template slot = "abc" slot-scope = "prop">
                {{prop.text}}
                {{prop.name}} //拿不到,只能拿除了name以外的数据
                {{prop.ss}} //可以拿到
            </template>
    </my-component>

</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
  Vue.component('my-component',{
    template: '<div> <slot text = "我是来自子组件的数据" ss = "nihao" name = "abc"></slot></div>'
  });
  var app = new Vue({
    el: '#app'
  })
</script>
</body>

------vue2.5.0之后的写法:

<p slot = "abc" slot-scope = "prop">
    {{prop.text}}
    {{prop.ss}}
</P>

访问slot

通过this.$slots.(NAME)

Vue.component('my-component',{
template:'<div></div>',
 mounted:function(){
      //访问插槽,拿到的是虚拟节点VNde
          var header = this.$slots.header;
          var text = header[0].elm.innerText;
          var html = header[0].elm.innerHTML;
          console.log(header);
          console.log(text);
          console.log(html)
      }
})

组件高级用法---动态组件

  1. VUE给我们提供 了一个元素叫component

  2. 作用: 用来动态的挂载不同的组件

  3. 实现:使用is特性来进行实现的

  4. 具体代码实现:

<body>
<div id = "app">
    <component :is = "thisView"></component>
    <button @click = "handleView('A')">第一句</button>
    <button @click = "handleView('B')">第二句</button>
    <button @click = "handleView('C')">第三句</button>
    <button @click = "handleView('D')">第四句</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
    //需求:通过点击不同的按钮切换不同的视图
    Vue.component('compA',{
      template: '<div>离离原上草</div>'
    });
  Vue.component('compB',{
    template: '<div>一岁一枯荣</div>'
  });
  Vue.component('compC',{
    template: '<div>野火烧不尽</div>'
  });
  Vue.component('compD',{
    template: '<div>春飞吹又生</div>'
  });
    var app = new Vue({
        el: '#app',
        data: {
          thisView:'compA'
        },
        methods: {
          //点击按钮实现对不同组件的切换
          handleView: function(tag){
            this.thisView = 'comp' + tag;
          }
        }
    })
</script>
</body>

相关文章

  • vue.js---组件

    组件的作用 作用: 提高代码的可复用性。 组件的使用方法 全局注册: 形式 代码示例: 优点:所有的Vue示例都可...

  • vue.js---计算属性

    利用例子引入计算属性 以上代码缺点:逻辑过程就会变得臃肿,难以维护,所以遇到复杂的逻辑时,应当使用计算属性。 定义...

  • vue.js---前端状态管理

    Vuex之store 作用: 用来管理状态,共享数据,在各个组件之间管理外部状态 如何使用?安装 第一步:引入vu...

  • vue.js---表单与v-model

    基本用法 VUE提供了v-­model指令, 用于在表单类元素上双向绑定事件 input和textarea 可以用...

  • vue组件之间的通信

    一、父子组件,父组件=》子组件 父组件中的子组件: 子组件:props 二、父子组件,子组件=》父组件 子组件: ...

  • Angular5 父子组件之间的通信

    一、父组件向子组件通信 父组件: 子组件: 二、子组件向父组件通信 父组件: 子组件:

  • react中调用子组件的方法

    class组件 父组件 子组件 react hook 父组件调用子组件方法 父组件 子组件

  • ReactNative组件间的通信

    父组件向子组件通信 父组件向子组件传值 父组件向子组件传递方法 子组件向父组件通信 子组件向父组件传值 子组件向父...

  • (17.06.21)Vue组件、组件的定义和使用、组件之间的数据

    Vue组件组件        Component     定义组件        公共的组件     使用组件  ...

  • ReactNative组件介绍

    ReactNative组件介绍 View组件Text组件TouchableOpacity组件TextInput组件...

网友评论

    本文标题:vue.js---组件

    本文链接:https://www.haomeiwen.com/subject/czqcjctx.html