最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 可复用性的组件详解

    正文概述 掘金(TheWorld)   2021-02-04   310

    可复用性的组件详解

    1.使用组件的原因

    2.组件的使用方法

    1. 全局注册

      Vue.component('my-component',{
      	template:'<div>我是组件的内容</div>'
      })
      优点:所有的nue实例都可以用
      缺点:权限太大,容错率降低
      
    2. 全局注册

      let app = new Vue({
        el: "#app",
        components: {
          "my-component": {
            template: "<div>我是组件的内容</div>",
          },
        },
      });
      

    注:

    vue组件的模板在某些情况下会受到html标签的限制,

    比如table中只能含有<tr><td>这些元素, 所以直接在table中使用组件是无效的,此时可以使用is属性来挂载组件

    <table>
    	<tbody is="my-component">
    	</tbody>
    </table>
    

    3.组件使用的奇淫技巧

    1. 推荐使用小写字母加­进行命名(必须) child, my­-componnet命名组件
    2. template中的内容必须被一个DOM元素包括 ,也可以嵌套
    3. 在组件的定义中,除了template之外的其他选项—data,computed,methods
    4. data必须是一个方法

    4.使用props传递数据 父亲向儿子传递数据

    1. 在组件中使用props来从父亲组件接收参数,

      注意:在props中定义的属性,都可以在组件中直接使用

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

    3. props的值有两种,一种是字符串数组,一种是对象,本节先只讲数组

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

    5. 单向数据流

    解释

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

    目的

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

    应用场景

    业务中会经常遇到两种需要改变 prop 的情况

    <div id="app">
    	<my-comp init-count="666"></my-comp>
    </div>
    <script>
    var app = new Vue({
      el: "#app",
      components: {
        "my-comp": {
          props: ["init-count"],
          template: "<div>{{init-count}}</div>",
          data: function () {
            return {
              count: this.initCount,
            };
          },
        },
      },
    });
    </script>
    
    <div id="app">
       <inputtype="text" v-model="width">
        <my-comp :width="width"></my-comp>
      </div>
    
    
    let app = new Vue({
      el:'#app',
      data:{
        width:'' 
      },
      components:{
            'my-comp':{
            props:['width'],
            template:'<div :style="style">{{init-count}}</div>',
            computed:{
              style:function () {
                return{
                  width:this.width+'px',
                  background:'red'
                }
              }
            }
          }
        }
    })
    

    数据验证

    总结:除了在html里 都用驼峰就完事了。

    类型

    • String
    • Number
    • Boolean
    • Object
    • Array
    • Function
    Vue.component ('my-compopent',{
      props : {
        //必须是数字类型
        propA : Number ,
        //必须是字符串或数字类型
        propB : [String , Number] ,
        //布尔值,如果没有定义,默认值就是 true
        propC: {
        type : Boolean ,
        default : true
        },
        //数字,而且是必传
        propD: {
        type: Number ,
        required : true
        },
        //如果是数组或对象,默认值必须是一个函数来返回
        propE: {
          type : Array ,
          default : function () {
            return [] ;
          }
        },
        //自定义一个验证函数
        propF: {
            validator : function (value) {
            return value > 10;
          }
        }
      }
    })
    

    7.组件通信

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

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

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

    JavaScript 的设计模式 一一观察者模式,dispatchEvent 和 addEventListener这两个方法。

    Vue组件也有与之类似的一套模式,子组件用emit()来触发事件,父组件用emit()来 触发事件 ,父组件用 emit()来触发事件,父组件用on()来 监昕子组件的事件 。

    直接甩代码

    第一步:自定义事件

    第二步: 在子组件中用$emit触发事件,第一个参数是事件名,后边的参数是要传递的数据

    第三步:在自定义事件中用一个参数来接受

    <template>
      <div id="app">
        <p>您好,您现在的银行余额是{{ total }}元</p>
        <btn-compnent @change="handleTotal"></btn-compnent>{{ myString }}
      </div>
    </template>
    
    <script>
    export default {
      name: "App",
      components: {
        "btn-compnent": {
          template:
            '<div>\
               <button @click="handleincrease">+1</button> \
             <button @click="handlereduce">-1</button>\
              </div>',
          data: function () {
            return {
              count: 0,
              myString1: "俺又赚钱了,哈哈哈哈哈哈哈",
              myString2: "俺又赔钱了,呜呜呜呜呜",
            };
          },
          methods: {
            handleincrease: function () {
              this.count += 1;
              this.$emit("change", this.count, this.myString1);
            },
            handlereduce: function () {
              this.count--;
              this.$emit("change", this.count, this.myString2);
            },
          },
        },
      },
      data() {
        return {
          total: 0,
          myString: "",
        };
      },
      methods: {
        handleTotal: function (total, string) {
          this.total = total;
          this.myString = string;
        },
      },
    };
    </script>
    
    <style>
    </style>
    
    

    2.在组件中使用v­mode

    $emit的代码,这行代码实际上会触发一个 input事件, 'input'后的参数就是传递给v­model绑定的属性的值

    v­model 其实是一个语法糖,这背后其实做了两个操作

    • v-­bind 绑定一个value属性
    • v-­on 指令给当前元素绑定 input 事件

    要使用v­model,要做到:

    • 接收一个 value 属性。
    • 在有新的 value 时触发 input 事件
    <div id="app">
    	<p>您好,您现在的银行余额是{{total}}元</p>
    	<btn-compnent v-model="total"></btn-compnent>
    </div>
    
    <script>
            var app = new Vue({
      el: "#app",
      data: {
        total: 0
      },
      components: {
        "btn-compnent": {
          template:
            '<div>\
      <button @click="handleincrease">+1</button> \
      <button @click="handlereduce">-1</button>\
      </div>',
          data: function () {
            return {
              count: 0
            };
          },
          methods: {
            handleincrease: function () {
              this.count++;
            --------注意观察.这一行,emit的是input事件---------					
            this.$emit("input", this.count);
            },
            handlereduce: function () {
              this.count--;
              this.$emit("input", this.count);
            }
          }
        }
      },
      methods: {
        /* handleTotal:function (total) {
      this.total = total;
      }*/
      }
    });
    
     </sciprt>
    

    3.非父组件之间的通信

    有时候两个组件也需要通信,(非父子关系)。

    在简单的场景下,可以使用一个空的Vue实例作为中央时间总线

    图案实例

    可复用性的组件详解

     <div id="app" >
    	<my-acomponent></my-acomponent>
    	<my-bcomponent></my-bcomponent>
    </div>
    
     components: {
        "my-acomponent": {
          template:
            '<div><button @click="handle">点击我向B组件传递数据</button></div>',
          data: function () {
            return {
              aaa: "我是来自A组件的内容",
            };
          },
          methods: {
            handle: function () {
              this.$root.bus.$emit("lala", this.aaa);
            },
          },
        },
        "my-bcomponent": {
          template: "<div></div>",
          created: function () {
            //A组件在实例创建的时候就监听事件---lala事件
            this.$root.bus.$on("lala", function (value) {
              alert(value);
            });
          },
        },
      },
    

    父链:this.$parent

    Vue.component("child-component", {
      template: '<button @click="setFatherData">通过点击我修改父亲的数据</button>',
      methods: {
        setFatherData: function () {
          this.$parent.msg = "数据已经修改了";
        }
      }
    });
    

    子链:this.$refs

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

    let app = new Vue({
      el: "#app",
      data: {
        //bus中介
        bus: new Vue(),
        msg: "数据还未修改",
        formchild: "还未拿到"
      },
      methods: {
        getChildData: function () {
          //用来拿子组件中的内容 ---- $refs
          this.formchild = this.$refs.c.msg;
        }
      }
    });
    
    

    4.使用slot分发内容

    1.什么是slot(插槽)

    为了让组件可以组合,我们需要一种方式来混合父组件的内容与子组件自己的模板。

    这个过程被称为内容分发,Vue.js 实现了一个内容分发 API,

    使用特殊的 'slot'元素作为原始内容的插槽。

    2.编译的作用域

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

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

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

    答案是父组件。

    组件作用域简单地说是:

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

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

    3.插槽的用法

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

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

    单个插槽:
    <div id="app">
      <my-component>
        <p>我是父组件的内容</p>
      </my-component>
    </div>;
    Vue.component("my-component", {
      template:
        "<div>\
            <slot>\
            如果父组件没有插入内容,我就作为默认出现\
            </slot>\
    	</div>"
    });
    
    具名插槽:
    <name-component>
        <h3 slot="header">我是标题</h3>
        <p>我是正文内容</p>
        <p>正文内容有两段</p>
        <p slot="footer">我是底部信息</p>
    </name-component>
    
    Vue.component("name-component", {
      template:
        '<div>\
      <div class="header">\n' +
        ' <slot name="header">\n' +
        " \n" +
        " </slot>\n" +
        "</div>\n" +
        '<div class="contatiner">\n' +
        " <slot>\n" +
        " \n" +
        " </slot>\n" +
        "</div>\n" +
        '<div class="footer">\n' +
        ' <slot name="footer">\n' +
        "\n" +
        " </slot> \n" +
        "</div>" +
        " </div>"
    });
    

    4.作用域插槽

    作用域插槽是一种特殊的slot,

    使用一个可以复用的模板来替换已经渲染的元素

    从子组件获取数据

    template模板是不会被渲染的

    Vue.component("my-component", {
      template:
        '<div>\
              <slot text="我是来自子组件的数据" ss="fdjkfjlsd" name="abc">\
              </slot>\
         </div>'
    });
    
    

    5.访问slot

    通过this.$slots.(NAME)
    mounted:function () {
      //访问插槽
      let header = this.$slots.header;
      let text = header[0].elm.innerText;
      let html = header[0].elm.innerHTML;
      console.log(header)
      console.log(text)
      console.log(html)
    }
    

    5.组件高级用法–动态组件

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

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

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


    起源地下载网 » 可复用性的组件详解

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元