New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

组件之间通信 - (Communicate Between Components) #16

Open
Tancy opened this Issue Jun 16, 2016 · 30 comments

Comments

Projects
None yet
@Tancy

Tancy commented Jun 16, 2016

新版中文网站及文档已经上线,请访问 https://weex-project.io/cn/ , 此处后续不再维护,谢谢理解。

子-父 通信

子组件可以使用this.$dispatch([String type], [Object detail]) 方法传递消息给父组件。
第一个参数定义消息类型,第二个参数为消息对象。如果父组件中的任何子组件使用$on([String type], [Function callback])注册监听事件,则回调执行第一个参数,参数中的 detail属性是消息数据。

案例:

<we-element name="foo">
  <template>
    <div>
      <image src="{{imageUrl}}" onclick="test"></image>
      <text>{{title}}</text>
    </div>
  </template>
  <script>
    module.exports = {
      data: {
        title: '',
        imageUrl: ''
      },
      methods: {
        test: function () {
          this.$dispatch('notify', {a: 1})
        }
      }
    }
  </script>
</we-element>

<template>
  <foo title="..." image-url="..."></foo>
</template>

<script>
  module.exports = {
    created: function () {
      this.$on('notify', function(e) {
        //  when <foo> image tag  be clicked ,the function will be executing.
        // e.detail is  `{a: 1}`
      })
    }
  }
</script>

父 - 子 通信

父组件可以使用 this.$([String id]) 来获取子组件的上下文。你可以使用上下文对象访问子组件的信息。

<we-element name="foo">
  <template>
    <div>
      <image src="{{imageUrl}}"></image>
      <text>{{title}}</text>
    </div>
  </template>
  <script>
    module.exports = {
      data: {
        title: '',
        imageUrl: ''
      },
      methods: {
        setTitle: function (t) {
          this.title = t
        }
      }
    }
  </script>
</we-element>

<template>
  <div>
    <text onclick="test">click to update foo</text>
    <foo id="fooEl" title="..." image-url="..."></foo>
  </div>
</template>

<script>
  module.exports = {
    methods: {
      test: function (e) {
        var foo = this.$('fooEl')
        foo.setTitle('...')
        foo.imageUrl = '...'
      }
    }
  }
</script>

父 - 子(多子)通信

父组件可以使用this.$broadcast([String type], [Object detail]) 广播消息给所有子组件。

案例:

<we-element name="bar">
  <template>
    <div>
      <image src="{{imageUrl}}"></image>
    </div>
  </template>
  <script>
    module.exports = {
      data: {
        imageUrl: ''
      },
      created: function() {
        var self = this
        this.$on('changeImage', function(e) {
          self.imageUrl = e.detail.imageUrl
        })
      }
    }
  </script>
</we-element>

<we-element name="foo">
  <template>
    <div>
      <bar></bar>
      <text>{{title}}</text>
    </div>
  </template>
  <script>
    module.exports = {
      data: {
        title: ''
      },
      created: function() {
        var self = this
        this.$on('changeTitle', function(e) {
          self.title = e.detail.title
        })
      }
    }
  </script>
</we-element>

<template>
  <div>
    <text onclick="test">click to update foo</text>
    <foo></foo>
    <foo></foo>
  </div>
</template>

<script>
  module.exports = {
    methods: {
      test: function (e) {
        this.$broadcast('changeTitle', {
          title: '...'
        })
        this.$broadcast('changeImage', {
          imageUrl: '...'
        })
      }
    }
  }
</script>

兄弟间通信

兄弟组件间通过公共的父组件作为桥梁来传递消息。

案例:

<we-element name="foo">
  <template>...</template>
  <script>
    module.exports = {
      methods: {
        callbar: function () {
          this.$dispatch('callbar', {a: 1})
        }
      }
    }
  </script>
</we-element>

<we-element name="bar">
  <template>...</template>
  <script>
    module.exports = {
      created: function() {
        this.$on('callbar', function(e) {
          // e.detail.a
        })
      }
    }
  </script>
</we-element>

<template>
  <div>
    <foo></foo>
    <bar></bar>
  </div>
</template>

<script>
  module.exports = {
    created: function () {
      var self = this
      this.$on('callbar', function(e) {
        self.$broadcast('callbar', e.detail)
      })
    }
  }
</script>

最后,你将学习怎么给Weex页面写 配置 & 数据

@emptywalker

This comment has been minimized.

Show comment
Hide comment
@emptywalker

emptywalker Aug 12, 2016

<we-element name="foo">这个标签是什么意思

emptywalker commented Aug 12, 2016

<we-element name="foo">这个标签是什么意思

@sandy53

This comment has been minimized.

Show comment
Hide comment
@sandy53

sandy53 Aug 12, 2016

@emptywalker
这个标签应该是自定组件的意思,可以看下组件封装这个文档
#2

sandy53 commented Aug 12, 2016

@emptywalker
这个标签应该是自定组件的意思,可以看下组件封装这个文档
#2

@mrKylinZhou

This comment has been minimized.

Show comment
Hide comment
@mrKylinZhou

mrKylinZhou Aug 23, 2016

自定义组件显示不出来啊 组建封装的例子和这节课的例子都好蒙啊
新东西 希望能解释一下

mrKylinZhou commented Aug 23, 2016

自定义组件显示不出来啊 组建封装的例子和这节课的例子都好蒙啊
新东西 希望能解释一下

@ruohuan

This comment has been minimized.

Show comment
Hide comment
@ruohuan

ruohuan Aug 23, 2016

“如果父组件中的任何子组件使用……”,应该是“在子组件的父组件中通过$on([String type], [Function callback])注册事件监听……”吧

ruohuan commented Aug 23, 2016

“如果父组件中的任何子组件使用……”,应该是“在子组件的父组件中通过$on([String type], [Function callback])注册事件监听……”吧

@ruohuan

This comment has been minimized.

Show comment
Hide comment
@ruohuan

ruohuan Aug 23, 2016

@emptywalker <we-element name="foo">XXX</we-element>的意思是中间的XXX这部分是foo组件代码,因为把子组件都写在一个.we文件里面了,如果不这么设置,文件里如果有多个组件,就会出现同级多个template,多个style和多个script

如果foo组件的代码放在单独的foo.we文件里面,就不需要写 <we-element name="foo">XXX</we-element>,直接写<template>...</template><style>...</style><script>...</script>即可

应该是这么理解的,哈哈

ruohuan commented Aug 23, 2016

@emptywalker <we-element name="foo">XXX</we-element>的意思是中间的XXX这部分是foo组件代码,因为把子组件都写在一个.we文件里面了,如果不这么设置,文件里如果有多个组件,就会出现同级多个template,多个style和多个script

如果foo组件的代码放在单独的foo.we文件里面,就不需要写 <we-element name="foo">XXX</we-element>,直接写<template>...</template><style>...</style><script>...</script>即可

应该是这么理解的,哈哈

@emptywalker

This comment has been minimized.

Show comment
Hide comment

emptywalker commented Sep 10, 2016

@zhouyuexie

This comment has been minimized.

Show comment
Hide comment
@zhouyuexie

zhouyuexie Sep 26, 2016

我把子组件写到单独的.we文件里,为何无法和父组件通信?

而且自带的wx-tabbar组件不支持子组件,难道需要自己实现?或者有其他的方法?

zhouyuexie commented Sep 26, 2016

我把子组件写到单独的.we文件里,为何无法和父组件通信?

而且自带的wx-tabbar组件不支持子组件,难道需要自己实现?或者有其他的方法?

@AlenGao

This comment has been minimized.

Show comment
Hide comment
@AlenGao

AlenGao Oct 8, 2016

@sandy53 你觉得你给的答案 是人家想要的吗

AlenGao commented Oct 8, 2016

@sandy53 你觉得你给的答案 是人家想要的吗

@AlenGao

This comment has been minimized.

Show comment
Hide comment
@AlenGao

AlenGao Oct 8, 2016

@ruohuan 你这样理解的你自己试过吗

AlenGao commented Oct 8, 2016

@ruohuan 你这样理解的你自己试过吗

@AlenGao

This comment has been minimized.

Show comment
Hide comment
@AlenGao

AlenGao Oct 9, 2016

兄弟组建之间的通信,父组建的js代码:
module.exports = {
created: function () {
var self = this
this.$on('callbar', function(e) {
self.$broadcast('callbar', e.detail)
})
}
}
这段代码貌似有问题,广播后父组建也能监听到会陷入死循环造成越界错误
events.js:39 Uncaught RangeError: Maximum call stack size exceeded
所以感觉$broadcast第一个参数不能和父组建监听的消息类型一样。

AlenGao commented Oct 9, 2016

兄弟组建之间的通信,父组建的js代码:
module.exports = {
created: function () {
var self = this
this.$on('callbar', function(e) {
self.$broadcast('callbar', e.detail)
})
}
}
这段代码貌似有问题,广播后父组建也能监听到会陷入死循环造成越界错误
events.js:39 Uncaught RangeError: Maximum call stack size exceeded
所以感觉$broadcast第一个参数不能和父组建监听的消息类型一样。

@codercuixin

This comment has been minimized.

Show comment
Hide comment
@codercuixin

codercuixin Oct 12, 2016

@Tancy

<!-- foo.we -->
<template>
  <container style="flex-direction: row;">
    <image class='image' src="{{image}}"></image>
    <text>{{title}}</text>
  </container>
</template>
<style>
  .image{width:100;height: 100}
</style>
<script>
  module.exports = {
    data: {
      title: null,
      image: null
    },
     methods: {
        setTitle:function(t){
          this.title=t;
        }
      }
  }
</script>


<!--main.we-->
<template>
  <div>
    <foo  id='fooId' title="Foo" image="http://t.cn/RGE3uo9"></foo>
    <text onclick='updateFoo'>Click to update Foo</text>
  </div>
</template>
<script>
  module.exports = {
   updateFoo:function(){
      var foo=this.$('fooId');
      foo.setTitle('我变了');
   }
  }
</script>

但是点击图片之后,控制台会出现TypeError: fn is undefine
不知道什么原因呢。谢谢了麻烦帮忙看下

codercuixin commented Oct 12, 2016

@Tancy

<!-- foo.we -->
<template>
  <container style="flex-direction: row;">
    <image class='image' src="{{image}}"></image>
    <text>{{title}}</text>
  </container>
</template>
<style>
  .image{width:100;height: 100}
</style>
<script>
  module.exports = {
    data: {
      title: null,
      image: null
    },
     methods: {
        setTitle:function(t){
          this.title=t;
        }
      }
  }
</script>


<!--main.we-->
<template>
  <div>
    <foo  id='fooId' title="Foo" image="http://t.cn/RGE3uo9"></foo>
    <text onclick='updateFoo'>Click to update Foo</text>
  </div>
</template>
<script>
  module.exports = {
   updateFoo:function(){
      var foo=this.$('fooId');
      foo.setTitle('我变了');
   }
  }
</script>

但是点击图片之后,控制台会出现TypeError: fn is undefine
不知道什么原因呢。谢谢了麻烦帮忙看下

@colys

This comment has been minimized.

Show comment
Hide comment
@colys

colys Oct 17, 2016

Tab里面怎么不能用父子通信?

colys commented Oct 17, 2016

Tab里面怎么不能用父子通信?

@codercuixin

This comment has been minimized.

Show comment
Hide comment
@codercuixin

codercuixin Oct 23, 2016

有些涉及图片的代码,建议个人使用的时候加上<image style="width:200;height:200" src="{{imageUrl}}"></image> ,图片的width,heght都是图片的基本属性,不加图片会显示不出来。这些都是基础 的,作者就没写可能。

codercuixin commented Oct 23, 2016

有些涉及图片的代码,建议个人使用的时候加上<image style="width:200;height:200" src="{{imageUrl}}"></image> ,图片的width,heght都是图片的基本属性,不加图片会显示不出来。这些都是基础 的,作者就没写可能。

@codercuixin

This comment has been minimized.

Show comment
Hide comment
@codercuixin

codercuixin Oct 23, 2016

@Tancy @emptywalker @sandy53 @mrKylinZhou @ruohuan
兄弟间通信.参数传递问题

为了不进入死循环(即main.we里既广播事件又监听事件),更改了名称,使得foo控件可以发布事件;在main.we使用on监听该事件,收到该事件再发出广播,然后再bar.we对该事件进行监听,然而参数传递还是有问题。。。。
使用上面的参数传递方式也有问题,自己改了一下。然而控制台输出
Object { a=1}
undefined ;
请问如何解决,谢谢了。
代码如下:

<!-- foo.we -->
<template>
<text onclick="callbar">foo dispatch event to call bar</text>
</template>
<script>
  module.exports = {
    methods: {
      callbar: function () {
        this.$dispatch('callbar1', {a: 1});
      }
    }
  }
</script>


<!-- bar.we -->
 <template>
    <text>{{textContent}}</text>
 </template>
<script>
module.exports = {
  created: function() {
    this.$on('callbar2', function(e) {
      // e.detail.a
      console.log(e.detail);
      this.textContent=e.detail;
    })
  }
}
</script>

<!--main.we -->
<template>
  <div>
    <foo></foo>
    <bar></bar>
  </div>
</template>

<script>
  module.exports = {
    created: function () {
      var self = this;
      this.$on('callbar1', function(e) {
        self.$broadcast('callbar2', e.detail);
        console.log(e.datail);
      });
    }
  }
</script>

codercuixin commented Oct 23, 2016

@Tancy @emptywalker @sandy53 @mrKylinZhou @ruohuan
兄弟间通信.参数传递问题

为了不进入死循环(即main.we里既广播事件又监听事件),更改了名称,使得foo控件可以发布事件;在main.we使用on监听该事件,收到该事件再发出广播,然后再bar.we对该事件进行监听,然而参数传递还是有问题。。。。
使用上面的参数传递方式也有问题,自己改了一下。然而控制台输出
Object { a=1}
undefined ;
请问如何解决,谢谢了。
代码如下:

<!-- foo.we -->
<template>
<text onclick="callbar">foo dispatch event to call bar</text>
</template>
<script>
  module.exports = {
    methods: {
      callbar: function () {
        this.$dispatch('callbar1', {a: 1});
      }
    }
  }
</script>


<!-- bar.we -->
 <template>
    <text>{{textContent}}</text>
 </template>
<script>
module.exports = {
  created: function() {
    this.$on('callbar2', function(e) {
      // e.detail.a
      console.log(e.detail);
      this.textContent=e.detail;
    })
  }
}
</script>

<!--main.we -->
<template>
  <div>
    <foo></foo>
    <bar></bar>
  </div>
</template>

<script>
  module.exports = {
    created: function () {
      var self = this;
      this.$on('callbar1', function(e) {
        self.$broadcast('callbar2', e.detail);
        console.log(e.datail);
      });
    }
  }
</script>
@wang111588

This comment has been minimized.

Show comment
Hide comment
@wang111588

wang111588 Oct 25, 2016

最后的链接404,目前是这个:#9

wang111588 commented Oct 25, 2016

最后的链接404,目前是这个:#9

@wang111588

This comment has been minimized.

Show comment
Hide comment
@wang111588

wang111588 Oct 25, 2016

@codercuixin
这行可以这样写,我这测试通过
self.$broadcast('callbar2', e.detail);
self.$broadcast('callbar2', e.detail.a);
你是前端开发还是native?

wang111588 commented Oct 25, 2016

@codercuixin
这行可以这样写,我这测试通过
self.$broadcast('callbar2', e.detail);
self.$broadcast('callbar2', e.detail.a);
你是前端开发还是native?

@wzj583585700

This comment has been minimized.

Show comment
Hide comment
@wzj583585700

wzj583585700 Oct 28, 2016

we-element name="foo" 这是干吗用的

wzj583585700 commented Oct 28, 2016

we-element name="foo" 这是干吗用的

@ltt1987

This comment has been minimized.

Show comment
Hide comment
@ltt1987

ltt1987 Nov 9, 2016

<we-element name="item"> <template> <div> <text>some text</text> </div> </template> </we-element> <template> <div> <item></item> </div> </template>
以上示例页面没有任何输出

ltt1987 commented Nov 9, 2016

<we-element name="item"> <template> <div> <text>some text</text> </div> </template> </we-element> <template> <div> <item></item> </div> </template>
以上示例页面没有任何输出

@zhangdefu3

This comment has been minimized.

Show comment
Hide comment
@zhangdefu3

zhangdefu3 Nov 11, 2016

@codercuixin 我也碰到了和你同样的问题,兄弟间通讯有问题。
我就按示例代码运行的;浏览器中,js报错: “events.js:39 Uncaught RangeError: Maximum call stack size exceeded”.

zhangdefu3 commented Nov 11, 2016

@codercuixin 我也碰到了和你同样的问题,兄弟间通讯有问题。
我就按示例代码运行的;浏览器中,js报错: “events.js:39 Uncaught RangeError: Maximum call stack size exceeded”.

@Jam1zhu

This comment has been minimized.

Show comment
Hide comment
@Jam1zhu

Jam1zhu Nov 22, 2016

@codercuixin 求助
default
在父级调用子件的方法,提醒undefined,是哪里写错了吗?

Jam1zhu commented Nov 22, 2016

@codercuixin 求助
default
在父级调用子件的方法,提醒undefined,是哪里写错了吗?

@wzj583585700

This comment has been minimized.

Show comment
Hide comment
@wzj583585700

wzj583585700 Nov 22, 2016

跳转页面怎么传递参数啊

wzj583585700 commented Nov 22, 2016

跳转页面怎么传递参数啊

@nuptboyzhb

This comment has been minimized.

Show comment
Hide comment
@nuptboyzhb

nuptboyzhb Nov 22, 2016

兄弟间通信,举例的代码有问题:


this.$on('callbar', function(e) {
        self.$broadcast('callbar', e.detail)
      })

这一块,如果两个兄弟和父组件都使用‘callbar’,会造成broadcast的消息会被自己接收到,造成死循环;栈溢出。

** Uncaught RangeError: Maximum call stack size exceeded(…) **

把文档的举例代码改成如下即可:


<we-element name="foo">
  <template>...</template>
  <script>
    module.exports = {
      methods: {
        callbar: function () {
          this.$dispatch('callbar', {a: 1})
        }
      }
    }
  </script>
</we-element>

<we-element name="bar">
  <template>...</template>
  <script>
    module.exports = {
      created: function() {
        this.$on('callbar2', function(e) {
          // e.detail.a
        })
      }
    }
  </script>
</we-element>

<template>
  <div>
    <foo></foo>
    <bar></bar>
  </div>
</template>

<script>
  module.exports = {
    created: function () {
      var self = this
      this.$on('callbar', function(e) {
        self.$broadcast('callbar2', e.detail)
      })
    }
  }
</script>

nuptboyzhb commented Nov 22, 2016

兄弟间通信,举例的代码有问题:


this.$on('callbar', function(e) {
        self.$broadcast('callbar', e.detail)
      })

这一块,如果两个兄弟和父组件都使用‘callbar’,会造成broadcast的消息会被自己接收到,造成死循环;栈溢出。

** Uncaught RangeError: Maximum call stack size exceeded(…) **

把文档的举例代码改成如下即可:


<we-element name="foo">
  <template>...</template>
  <script>
    module.exports = {
      methods: {
        callbar: function () {
          this.$dispatch('callbar', {a: 1})
        }
      }
    }
  </script>
</we-element>

<we-element name="bar">
  <template>...</template>
  <script>
    module.exports = {
      created: function() {
        this.$on('callbar2', function(e) {
          // e.detail.a
        })
      }
    }
  </script>
</we-element>

<template>
  <div>
    <foo></foo>
    <bar></bar>
  </div>
</template>

<script>
  module.exports = {
    created: function () {
      var self = this
      this.$on('callbar', function(e) {
        self.$broadcast('callbar2', e.detail)
      })
    }
  }
</script>
@DoranYun

This comment has been minimized.

Show comment
Hide comment
@DoranYun

DoranYun Dec 9, 2016

@emptywalker
在同一个文件里定义两个组件用的,现在可以直接使用 element

DoranYun commented Dec 9, 2016

@emptywalker
在同一个文件里定义两个组件用的,现在可以直接使用 element

@DoranYun

This comment has been minimized.

Show comment
Hide comment
@DoranYun

This comment has been minimized.

Show comment
Hide comment
@DoranYun

This comment has been minimized.

Show comment
Hide comment
@DoranYun

This comment has been minimized.

Show comment
Hide comment

DoranYun commented Dec 9, 2016

@yimingtang

This comment has been minimized.

Show comment
Hide comment
@yimingtang

yimingtang Dec 29, 2016

Typo:

同理,首先子组件要监听特定类型的自定义事件,而父组件可以使用 this.$vm(id) 找到父组件,然后再调用 this.$vm(id).$emit(type, detail) 方法,即可实现自上而下的通信。例如:

『而父组件可以使用 this.$vm(id) 找到父组件』应当是找到『子组件』

yimingtang commented Dec 29, 2016

Typo:

同理,首先子组件要监听特定类型的自定义事件,而父组件可以使用 this.$vm(id) 找到父组件,然后再调用 this.$vm(id).$emit(type, detail) 方法,即可实现自上而下的通信。例如:

『而父组件可以使用 this.$vm(id) 找到父组件』应当是找到『子组件』

@DoranYun

This comment has been minimized.

Show comment
Hide comment
@DoranYun

DoranYun Dec 30, 2016

感谢反馈,我在文档里更新一下

DoranYun commented Dec 30, 2016

感谢反馈,我在文档里更新一下

@DoranYun

This comment has been minimized.

Show comment
Hide comment
@DoranYun

DoranYun Jan 20, 2017

新版中文网站及文档已经上线,请访问 https://weex-project.io/cn/ , 此处后续不再维护,谢谢理解。

DoranYun commented Jan 20, 2017

新版中文网站及文档已经上线,请访问 https://weex-project.io/cn/ , 此处后续不再维护,谢谢理解。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment