Vue组件传值

1.父传子(props)

  • props只能是父组件向子组件进行传值,props使得父子组件之间形成一个单向的下行绑定。子组件的数据会随着父组件的更新而响应式更新。
  • props可以显示定义一个或一个以上的数据,对于接收的数据,可以是各种数据类型,同样也可以是传递一个函数。

父组件:

<template>
  <div id="root">
    <div class="todo-container">
      <div class="todo-wrap">
        <Header :addTodo="addTodo"></Header>
        <List :todos="todos" :checkTodo="checkTodo" :deleteTodo="deleteTodo"></List>
        <Footer :todos="todos" :checkAllTodo="checkAllTodo" :clearAllTodo="clearAllTodo"></Footer>
      </div>
    </div>
  </div>
</template>

<script>
import Header from "@/components/Header";
import List from "@/components/List";
import Footer from "@/components/footer";

export default {
  name: 'App',
  data() {
    return {
      todos: [
        {id: '001', title: '测试数据1', done: false},
        {id: '002', title: '测试数据2', done: true},
        {id: '003', title: '测试数据3', done: false}
      ]
    }
  }, methods: {
    addTodo(todoObj) {
      this.todos.unshift(todoObj);
    },
    /* 勾选或者 取消勾选   */
    checkTodo(id) {
      this.todos.forEach((todo) => {
        if (todo.id == id) {
          todo.done = !todo.done;
          return;
        }
      });
    },
    deleteTodo(id) {
      this.todos = this.todos.filter(todo=>todo.id != id);
    },
    /* 全选 与 全反选 */
    checkAllTodo(done){
      this.todos.forEach(todo=> todo.done = done);
    },clearAllTodo(){
      this.todos = this.todos.filter(todo=> !todo.doen);
    }
  },
  components: {
    Footer,
    List,
    Header
  }
}
</script>

子组件

<template>
  <div class="todo-header">
    <input type="text" placeholder="请输入信息" @keydown.enter="add" v-model="title"/>
  </div>
</template>

<script>
import {nanoid} from 'nanoid'
export default {
  name: "Header",
  data() {
    return {
      title: ''
    }
  }, methods: {
    add() {
      if (!this.title.trim()) {
        console.log("当前input为空");
        return;
      }
      const todoObj = {
        id: nanoid(),
        title: this.title,
        done: false
      };
      this.addTodo(todoObj);
      this.title = '';
    }
  },
  props:['addTodo']
}
</script>

<style scoped>
.todo-header input {
  width: 560px;
  height: 28px;
  border: 1px solid #ccc;
  border-radius: 4px;
  padding: 4px 7px;
  font-size: 14px;
}

.todo-header input:focus {
  outline: none;
  border-color: pink;
  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.8),
  0 0 8px pink;


}
</style>

2.子传父($emit)

  • $emit 绑定一个自定义事件,当这个事件被执行的时候就会将参数传递给父组件,而父组件通过v-on监听并接收参数

父组件

<template>
  <div>
    <!--  通过父组件 给子组件绑定一个自定事件 实现子组件给父组件 -->
    <!-- ****** 传递数据 -->
    <Student @zhangsan="getStudentName"></Student>
    <hr/>
    <Student ref="student"></Student>
  </div>
</template>
<script>
import Student from "@/components/Student";

export default {
  name: 'App',
  data() {
    return {}
  }, components: {
    Student
  }, methods: {
    getStudentName(name) {
      console.log("获取到了学生的的信息" + name)
    }
  },mounted() {
    /*  $on(eventName) 监听事件 */
    /* Vue 为每个窗口 都提供了一个 事件接口  Events interface */
    this.$refs.student.$on('zhangsan',this.getStudentName)

  }

}
</script>

子组件:

<template>
  <div>
    <h2>学生姓名:{{ name }} </h2>
    <h2>学生性别:{{ sex }} </h2>
    <button @click="sendStudentName">点我传递学生信息</button>
    <button @click="unbind">解绑自定义事件</button>
  </div>
</template>

<script>
export default {
  name: "Student",
  data() {
    return {
      name: '张三',
      sex: '男'
    }
  },methods:{
    sendStudentName(){
      //  $emit 触发事件   >>> $emit(eventName)
      this.$emit('zhangsan',this.name);
      // this.$emit('zhangsan',this.name,.,.,.,.,.,.);

    },unbind(){
      // 解除一个自定义事件
      // this.$off('zhangsan');
      //解除多个自定事件绑定
      // this.$off(['zhangsan']);
      // 解除所有自定义事件绑定
      this.$off();
    }

  }
}
</script>

<style scoped>

</style>

3.全局事件总线 $emit,$on,$off

父组件:

<template>
  <div>
    <!--  通过父组件 给子组件绑定一个自定事件 实现子组件给父组件 -->
    <!-- ****** 传递数据 -->
    <School></School>
    <Student ></Student>
  </div>
</template>
<script>
import Student from "@/components/Student";
import School from "@/components/School";

export default {
  name: 'App',
  data() {
    return {}
  }, components: {
    School,
    Student
  }

}
</script>

子组件1:

<template>
  <div>
    <h2>学校名称:{{ name }}</h2>
    <h2>学校地址:{{ address }}</h2>
  </div>
</template>

<script>
export default {
  name: "School",
  data() {
    return {
      name: '猿究院',
      address: '太白南路'
    }
  }, methods: {
    myShowInfo(data) {
      console.log("这是School组件,收到了数据:"+data);
    }
  },
  mounted() {
    this.$bus.$on('showInfo',this.myShowInfo)
  },beforeDestroy() {
      this.$bus.$off('showInfo');
  }
}
</script>

<style scoped>

</style>

子组件2:

<template>
  <div>
    <h2>学生姓名:{{ name }} </h2>
    <h2>学生性别:{{ sex }} </h2>
    <button @click="sendStudentName">点我传递学生信息</button>
  </div>
</template>

<script>
export default {
  name: "Student",
  data() {
    return {
      name: '张三',
      sex: '男'
    }
  },methods:{
    sendStudentName(){
      //  $emit 触发事件   >>> $emit(eventName)
      this.$bus.$emit('showInfo',this.name);
    }

  }
}
</script>

<style scoped>

</style>

4.组件之间得通信:


1.安装
npm i pubsub-js

2.引入
import pubSub from 'pubsub-js'

接收数据 A想要数据  需要在A中订阅消息
methods: {
    myShowInfo(msg, data) {
      console.log("这是School组件,收到了数据:" + msg + data);
    }
},
mounted() {
    // 订阅消息
    this.pubId = pubSub.subscribe('MyShowInfo', this.myShowInfo);
}
提供数据
pubSub.publish('MyShowInfo',data)

销毁
beforeDestroy() {
    // 取消订阅的消息  this.myShowInfo
    pubSub.unsubscribe(this.pubId);
}

例子:

APP.vue

<template>
  <div>
    <!--  通过父组件 给子组件绑定一个自定事件 实现子组件给父组件 -->
    <!-- ****** 传递数据 -->
    <School></School>
    <Student ></Student>
  </div>
</template>
<script>
import Student from "@/components/Student";
import School from "@/components/School";

export default {
  name: 'App',
  data() {
    return {}
  }, components: {
    School,
    Student
  }

}
</script>

组件1:

<template>
  <div>
    <h2>学校名称:{{ name }}</h2>
    <h2>学校地址:{{ address }}</h2>
  </div>
</template>

<script>
import pubSub from 'pubsub-js'

export default {
  name: "School",
  data() {
    return {
      name: '猿究院',
      address: '太白南路',
      pubId: ''
    }
  }, methods: {
    myShowInfo(msg, data) {
      console.log("这是School组件,收到了数据:" + msg + data);
    }
  },
    mounted() {
    // 订阅消息
    this.pubId = pubSub.subscribe('myShowInfo', this.myShowInfo);
  },
  beforeDestroy() {
    // 取消订阅的消息  this.myShowInfo
    pubSub.unsubscribe(this.pubId);
  }
}
</script>

<style scoped>

</style>

组件2:

<template>
  <div>
    <h2>学生姓名:{{ name }} </h2>
    <h2>学生性别:{{ sex }} </h2>
    <button @click="sendStudentName">点我传递学生信息</button>
  </div>
</template>

<script>
import pubSub from 'pubsub-js'

export default {
  name: "Student",
  data() {
    return {
      name: '张三',
      sex: '男'
    }
  },methods:{
    sendStudentName(){
      pubSub.publish('myShowInfo',this.name);
    }
  }
}
</script>

<style scoped>

</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值