应用场景:
- 一个单组件 拆分成三个组件 a,b,c
- c组件负责整体页面, 是a ,b的父组件 a,b是同级的两个组件
- a点击按钮 ,要实现b的缩放
- 缩放之间 依靠一个 boolen型的变量 collapse
父组件将数据传递给子组件
确保 a,b绑定通相同 ,变量同步
- 父组件中
data(){
return{
collapse:false
}
},
components:{
a,b
},
c 的页面中定义 :子组件变量名=“绑定的父组件变量名” (动态绑定)
<a :collapse="collapse"></a>
<b :collapse="collapse"></b>
- 子组件中 在props中 声明要接收的变量 ,然后可作为data中的变量直接使用
props:{
collapse:Boolean
},
<div v-if="!collapse"></div>
此时a 建立方法 点击 只有本地值发生变化, 要想能够同步
- 在父组件中 创建能够改变变量 collapse 的方法 ,由a去调用c的方法 ,从而使得全局a,b,c,的变量改变,达到a控制b的效果 (父向子传递事件)
- a去改变c(父组件)的值,从而实现全局的变量改变 (子向父传值)
1 父向子传递事件
- 父组件中
定义的事件
methods: {
toShrink(){
this.collapse=true;
},
toRecover(){
this.collapse=false;
}
}
页面中 @子组件接收的事件名=父组件中要传递的事件”
<a :collapse="collapse" @fatherToShark="toShrink" @fatherToRecover="toRecover"></a>
<b :collapse="collapse" @fatherToShark="toShrink" @fatherToRecover="toRecover"></b>
- 子组件中:在自定义的事件中调用父组件的事件
<span @click="recover"><i class="el-icon-s-unfold"> </i></span>
methods:{
shrink(){
this.$emit("fatherToShark");
},
recover(){
this.$emit("fatherToRecover");
},
}
子向父传值
利用自组件调用父组件事件(事件中 形参给数据赋值 在子组件调用中,形参为自己的数据)
methods:{
test(count){
this.count=count
}
}
<a @aa="test"> </a> // 注意此处父组件方法 test不能写为test()
子组件
data(){
return{
countChild:100
}
}
methods:{
testChild(){
this.$emit('aa',this.countChild)
}
}
使用第三方插件 pubsub-js
使用此插件可在任意子父兄关系之间来回传递值
接受者:
导入插件
import PubSub from 'pubsub-js'
订阅消息 在页面初始化完成后调用
npm install pubsub-js --save
create(){
this.token = PubSub.subscribe('my_msg'(订阅消息名称),(_(订阅消息名称 ,可用形参接收 此处不需要 用——占位),stateObj(发送方传递的数据))=>{
this.data.***=stateObj.***
})
token是这个订阅的标识 用于再组件结束时 关闭此订阅
}
beforeDestroy(){
PubSub.unsubscribe(this.token)
}
发送方:
import PubSub from 'pubsub-js'
得到数据后 发布将消息发布
PubSub.publish('my_msg',{users:res.data.***,isLoding:false})
由原来的兄弟组件之间的数据传递 要将数据放到父组件 改为 直接通过消息订阅发布 数据直接放入使用方
react同理
例 搜索框Search搜索 List结果展示:
App.jsx
import React, { Component } from 'react'
import Search from './components/Search'
import List from './components/List'
export default class App extends Component {
render() {
return (
<div className="container">
<Search/>
<List/>
</div>
)
}
}
Search
import React, { Component } from 'react';
import axios from 'axios'
import PubSub from 'pubsub-js'
class Search extends Component {
search=()=>{
const {keyWordElement:{value:key}} =this
axios.get(`http://localhost:3000/search/users?q=${key}`).then(
res=>{
PubSub.publish('my_msg',{users:res.data.items,isLoding:false})
},
err=>{
PubSub.publish('my_msg',{err:err.message,isLoding:false})
}
)
}
render() {
return (
<div>
<section className="jumbotron">
<input type="text" placeholder="enter the name you search" ref={c=>this.keyWordElement=c}/> <button onClick={this.search}>Search</button>
</section>
</div>
);
}
}
export default Search;
List
import React, { Component } from 'react'
import PubSub from 'pubsub-js'
import './index.css'
export default class List extends Component {
state = { //初始化状态
users:[], //users初始值为数组
isFirst:true, //是否为第一次打开页面
isLoading:false,//标识是否处于加载中
err:'',//存储请求相关的错误信息
}
componentDidMount(){
this.token = PubSub.subscribe('my_msg',(_,stateObj)=>{
this.setState(stateObj)
})
}
componentWillUnmount(){
PubSub.unsubscribe(this.token)
}
render() {
const {users,isFirst,isLoading,err} = this.state
return (
<div className="row">
{
isFirst ? <h2>欢迎使用,输入关键字,随后点击搜索</h2> :
isLoading ? <h2>Loading......</h2> :
err ? <h2 style={{color:'red'}}>{err}</h2> :
users.map((userObj)=>{
return (
<div key={userObj.id} className="card">
<a rel="noreferrer" href={userObj.html_url} target="_blank">
<img alt="head_portrait" src={userObj.avatar_url} style={{width:'100px'}}/>
</a>
<p className="card-text">{userObj.login}</p>
</div>
)
})
}
</div>
)
}
}