最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • vue组件通信方式汇总

    正文概述 掘金(林子酱)   2021-01-26   459

    前提回顾

    为了能让需要通信的两个组件可以说上话,往往需要借助一些手段来实现这个目的,本文的写作目标就是为了总结每一种可以用于通信手段的方法。 vue组件通信方式汇总

    第一:props/$emit

    下面使用了props/$emit方法做到了让Foo组件和Bar组件通信 vue组件通信方式汇总

    • App.vue
    <template>
      <div id="app">
        <Foo></Foo>
      </div>
    </template>
    
    <script>
    import Foo from "./components/Foo";
    export default {
      name: "App",
      components: {
        Foo,
      },
    };
    </script>
    
    • components/Foo.vue
    <template>
    <div id='Foo'>
        使用props/$emit来做到父子组件通信
        <Bar 
        	:
        	@changeTitle='handleChangeTitle'>
        </Bar>
    </div>
    </template>
    
    <script>
    import Bar from './Bar';
    export default {
        name: 'Foo' ,
        components: {
          Bar
        },
        data() {
            return {
              title:"this is a message"
            }
        },
        methods: {
          handleChangeTitle(props){
            this.title=props
          }
        }
    };
    </script>
    
    • components/Bar.vue
    <template>
    <div id='Bar'>
      使用props/$emit来做到父子组件通信
      {{title}}
      <button @click="toParent">改变title</button>
    </div>
    </template>
    
    <script>
    export default {
        name: 'Bar' ,
        props: ['title'],
        methods: {
          toParent(){
            this.$emit('changeTitle','this is a new message')
          }
        }
    };
    </script>
    

    第二:$refs/ref

    vue组件通信方式汇总

    • App.vue的代码同上省略
    • components/Foo.vue
    <template>
    <div id='Foo'>
        Foo
        <Bar 
          : 
          @changeTitle='handleChangeTitle'
          ref='bar'
          ></Bar>
          <button
            @click="getBar"
          >getBar</button>
    </div>
    </template>
    
    <script>
    import Bar from './Bar';
    export default {
        name: 'Foo' ,
        components: {
          Bar
        },
        props: [''],
        data() {
            return {
              title:"this is a message"
            }
        }
        methods: {
          getBar(){
            // 调用了Bar组件上的setBarTitle方法
            console.log(this.$refs.bar.setBarTitle());
            // console.log(this.$refs.bar);
          }
        }
    };
    </script>
    

    vue组件通信方式汇总

    • components/Bar.vue
    <template>
    <div id='Bar'>
      Bar
      {{title}}
      <button @click="toParent">改变title</button>
    </div>
    </template>
    
    <script>
    export default {
        name: 'Bar' ,
        props: ['title'],
        methods: {
          toParent(){
            this.$emit('changeTitle','this is a new message')
          },
          setBarTitle(){
            console.log('changeBarTitle');
          }
        }
    };
    </script>
    

    第三:children/parent

    使用$children获取组件的子组件实例的时候是依赖下标来获取的,这种获取方式是不稳定的,易出错。 vue组件通信方式汇总

    • App.vue的代码同上省略
    • components/Foo.vue
    <template>
    <div id='Foo'>
        Foo
          <button
            @click="getChildren"
          >getChildren</button>
    </div>
    </template>
    
    <script>
    import Bar from './Bar';
    export default {
        name: 'Foo' ,
        components: {
          Bar
        },
        props: ['']
        methods: {
          getChildren(){
            //可以获取到当前Foo组件的所有子组件实例
            //(是数组格式[VueCompoent])
            //依赖下标来获取具体子组件实例
            //即通过this.$children[下标]
            console.log(this.$children);
          }
        }
    };
    </script>
    <style>
    </style>
    
    • components/Bar.vue
    <template>
    <div id='Bar'>
    
      <button
        @click="getParent">
      getBarParent</button>
      
    </div>
    </template>
    
    <script>
    export default {
        name: 'Bar' ,
        methods: {
          getParent(){
            //就可以获取到Bar组件的父级组件了
            //接着可以调用父级组件上的方法等等操作进行通信
            console.log(this.$parent);
          }
        }
    };
    </script>
    

    第四:attrs/listeners

    vue组件通信方式汇总 vue组件通信方式汇总

    • App.vue
    <template>
      <div id="app">
        <Foo></Foo>
      </div>
    </template>
    
    <script>
    import Foo from './components/Foo';
    export default {
      name: "App",
      components: {
        Foo
      },
    };
    </script>
    
    • components/Foo.vue
    <template>
      <div>
        这里是Foo
        <Bar 
           
          class="heihei" 
          @a="handleA" 
          @b="handleB"
          @click='handleFooClick'
          disabled='disabled'
        ></Bar>
      </div>
    </template>
    
    <script>
    import Bar from "./Bar";
    export default {
      components: {
        Bar,
      },
    
      methods: {
        getName() {
          return "CompA";
        },
        handleA() {
          console.log("handleA")
        },
        handleB() {
          console.log("handleB")
        },
        handleFooClick(){
          console.log(" handleFooClick")
        }
      },
    };
    </script>
    
    • components/Bar.vue
    <template>
      <div>
        这里是Bar
        <Baz 
          :
          v-on="$listeners"
          ></Baz>
    
        <button 
          disabled='$attrs.disabled'
        >禁用状态</button>
      </div>
    </template>
    
    <script>
    import Baz from "./Baz";
    export default {
      //一般可以用props来接收父级组件传递下来的内容
      // 如果传入的值没有在 props 中声明,那么就会在 $attrs 获取到
      // props:["title"],
    
    
      //默认行为:
      //我们之前书写了<Bar  ></Bar>
      //并且没有通过props来接收声明title的话Vue会把
      //给添加到组件容器内即<div ></div>
      //如果不希望出现这种情况可以使用inheritAttrs: false
      inheritAttrs: false,
      
      
      components: {
        Baz,
      },
      mounted() {
        // $attrs 属性:
        // 如果传入的值没有在 props 中声明,那么就会在 $attrs 获取到
    
        //{title: "this is a foo"}
        console.log(this.$attrs,'this.$attrs');
        //{a: ƒ, b: ƒ, click: ƒ}
        console.log(this.$listeners,'this is bar');
        
        this.$listeners.a()
      },
    
      methods: {
        getName() {
          return "CompB";
        },
      },
    };
    </script>
    
    • components/Baz.vue
    <template>
      <div>
        这里是Baz
        {{ title }}
      </div>
    </template>
    
    <script>
    export default {
      props: ["title"],
      methods: {
          
      },
      mounted(){
        //成功传递进来了{a: ƒ, b: ƒ, click: ƒ}
        console.log(this.$listeners,'this is baz');
      }
    };
    </script>
    
    <style></style>
    
    

    第五:provide/inject

    vue组件通信方式汇总 vue组件通信方式汇总

    • App.vue
    <template>
      <div id="app">
        <CompA></CompA>
      </div>
    </template>
    
    <script>
    import CompA from "./components/CompA";
    export default {
      name: "App",
      components: {
        CompA
      },
    };
    </script>
    
    • components/CompA.vue
    <template>
      <div>
        这里是CompA
        <CompB></CompB>
      </div>
    </template>
    
    <script>
    import CompB from "./CompB";
    export default {
      components: {
        CompB,
      },
      mounted() {
      },
    
    
      //把当前的组件实例传递给别人
      //别人拿到组件实例后可以调用该组件实例上的方法
      //第二种写法:
      provide() {
        return {
          foo: "foo",
          compA: this,  //注意this的指向问题
        };
      },
    
      // 第一种写法:
      // provide: {
      //   foo: "foo",
      //   compA: this, //注意this的指向问题
      // },
    
      methods: {
        getName() {
          return "CompA";
        },
      },
    };
    </script>
    
    • components/CompB.vue
    <template>
      <div>
        这里是CompB
        <CompC></CompC>
      </div>
    </template>
    
    <script>
    import CompC from "./CompC";
    export default {
      components: {
        CompC,
      },
      provide() {
        return {
          compA: this, //this指向compB组件
                       //名字却故意取为compA
                       //在注入时会取最近的注入名
        };
      },
      methods: {
        getName() {
          return "CompB";
        },
      },
    };
    </script>
    
    • components/CompC.vue
    <template>
      <div>
        CompC
    
        直接就可以使用了:{{foo}}
    
        <button @click="getCompA">getCompA</button>
      </div>
    </template>
    
    <script>
    export default {
      inject: ["foo", "compA"],
      methods: {
        getCompA(){
          //获取到组件实例
          console.log(this.compA);
          //该组件实例上有getName方法
          //输出的结果为CompB(取的是最近的注入名 "compA" )
          console.log(this.compA.getName())
        }
      },
    };
    </script>
    

    第六:EventBus通信

    vue组件通信方式汇总 vue组件通信方式汇总

    • bus.js
    import Vue from "vue";
    
    // event bus
    export const bus = new Vue();
    
    • components/CompA.vue
    <template>
      <div>
        CompA
        <CompB></CompB>
      </div>
    </template>
    
    <script>
    import CompB from "./CompB";
    import {bus} from '../bus';
    export default {
      components: {
        CompB,
      },
      mounted() {
        bus.$on('to-CompoA',(message)=>{
          console.log(message);
        })
      }
    };
    </script>
    
    • components/CompB.vue
    <template>
      <div>
        CompB
        <CompC></CompC>
      </div>
    </template>
    
    <script>
    import CompC from "./CompC";
    export default {
      components: {
        CompC,
      },
    };
    </script>
    
    • components/CompC.vue
    <template>
      <div>
        CompC
        <button @click="getCompA">getCompA</button>
      </div>
    </template>
    
    <script>
    import {bus} from '../bus';
    export default {
      methods: {
        getCompA(){
          bus.$emit('to-CompoA','this is message from  CompoC')
        }
      },
    };
    </script>
    
    • App.vue
    <template>
      <div id="app">
        <CompA></CompA>
      </div>
    </template>
    
    <script>
    import CompA from './components/CompA';
    export default {
      name: "App",
      components: {
         CompA
      },
    };
    </script>
    

    第七:v-model

    vue组件通信方式汇总

    • App.vue
    <template>
      <div id="app">
        <Foo></Foo>
      </div>
    </template>
    
    <script>
    import Foo from './components/Foo';
    export default {
      name: "App",
      components: {
        Foo
      },
    };
    </script>
    
    • components/Foo.vue
    <template>
      <div>
        这里是Foo
        <Bar 
            v-model="initValue"
        ></Bar>
      </div>
    </template>
    
    <script>
    import Bar from "./Bar";
    export default {
      components: {
        Bar,
      },
      data(){
        return{
          initValue:'hello init'
        }
      }
    };
    </script>
    
    • components/Bar.vue
    <template>
      <div>
        这里是Bar
        <input type="text"
          v-bind:value="handle"
          v-on:change="$emit('handleEvent', $event.target.value+'fk')"
        >
      </div>
    </template>
    
    <script>
    export default {
      
      components: {
      },
      model:{
        prop:'handle',
        event:'handleEvent'
      },
      
      //仍然需要在组件的 props 选项里声明
      // handle 这个 prop。
      props: {
        handle: String
      },
    };
    </script>
    

    第八:sync

        <script>
          const Modal = {
            template: `<div v-if="visible">
              modal
              {{visible}}
              {{number}}
              <button @click="handleClick">x</button>
            </div>`,
            props: ["visible", "number"],
            methods: {
              handleClick() {
                this.$emit("update:visible", false);
                this.$emit("update:number", 10);
              },
            },
          };
    
          const app = new Vue({
            el: "#app",
            components: {
              Modal,
            },
            data: {
              msg: "hello",
              showModel: false,
              count: 1,
            },
            methods: {
              handleShowModel() {
                this.showModel = true;
              },
              // handleCloseModel() {
              //   this.showModel = false;
              // },
            },
            template: `<div>
            app
            <button @click="handleShowModel"> showModel</button>
            <Modal :visible.sync="showModel" :number.sync="count" ></Modal>
            </div>`,
          });
        </script>
    

    第九:VueX

    暂时省略


    起源地下载网 » vue组件通信方式汇总

    常见问题FAQ

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

    发表评论

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

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

    联系作者

    请选择支付方式

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