向子组件传递对象

使用v-bind形式向子组件传递对象:

  1. <template>
  2. <ul class="todo-main">
  3. <!-- 使用:todo,利用v-bind内容是js表达式的方式,将todoObj传递给子组件MyItem -->
  4. <MyItem v-for="todoObj in todos" :key="todoObj.id" :todo="todoObj"/>
  5. </ul>
  6. </template>
  7. <script>
  8. import MyItem from './MyItem'
  9. export default {
  10. name:'MyList',
  11. components: {MyItem},
  12. data() {
  13. return {
  14. todos: [
  15. {id:'0001', title:'吃饭', done:true},
  16. {id:'0002', title:'睡觉', done:false},
  17. {id:'0003', title:'看电视', done:true},
  18. ]
  19. }
  20. },
  21. }
  22. </script>

子组件接收对象,并进行显示:

  1. <template>
  2. <li>
  3. <label>
  4. <input type="checkbox" :checked="todo.done"/>
  5. <span>{{todo.title}}</span>
  6. </label>
  7. <button class="btn btn-danger" style="display:none">删除</button>
  8. </li>
  9. </template>
  10. <script>
  11. export default {
  12. name: 'MyItem',
  13. props:['todo'] // 接收父组件传入的对象
  14. }
  15. </script>

生成唯一流水号

可以使用UUID生成唯一流水号,但是UUID组件比较重,可以使用轻量版的nanoid代替:

  1. npm i nanoid

用法:

  1. import {nanoid} from 'nanoid'
  2. let id = nanoid();

调用父组件的方法,给父组件传值

父组件定义方法,并传递给子组件:

  1. <template>
  2. <div id="app">
  3. <div class="todo-container">
  4. <div class="todo-wrap">
  5. <!-- 将addTodo方法传递给子组件MyHeader -->
  6. <MyHeader :addTodo="addTodo"/>
  7. </div>
  8. </div>
  9. </div>
  10. </template>
  11. <script>
  12. import MyHeader from './components/MyHeader'
  13. export default {
  14. name: 'App',
  15. components: {MyHeader},
  16. data() {
  17. return {
  18. todos: [
  19. {id:'0001', title:'吃饭', done:true},
  20. {id:'0002', title:'睡觉', done:false},
  21. {id:'0003', title:'看电视', done:true},
  22. ]
  23. }
  24. },
  25. methods: {
  26. // 定义addTodo方法
  27. addTodo(todo) {
  28. this.todos.unshift(todo)
  29. }
  30. }
  31. }
  32. </script>

子组件中接收函数,并在需要时调用:

  1. <template>
  2. <div class="todo-header">
  3. <input type="text" placeholder="请输入你的任务名称,按回车键确认" @keyup.enter="add"/>
  4. </div>
  5. </template>
  6. <script>
  7. import {nanoid} from 'nanoid'
  8. export default {
  9. name:'MyHeader',
  10. props: ['addTodo'], // 接收父组件的addTodo方法
  11. methods: {
  12. add(e) {
  13. const todoObj = {id:nanoid(), title:e.target.value, done:false};
  14. // 调用父组件的addTodo方法,参数也可以通过父组件方法正常传递给父组件
  15. this.addTodo(todoObj);
  16. }
  17. }
  18. }
  19. </script>

复选框的操作

方式1:

使用:checked显示复选框是否被选中。使用@change绑定事件当选择状态变化时触发方法

  1. <template>
  2. <div class="todo-footer" v-show="total">
  3. <!-- 使用:checked显示当前复选框是否被选中。 当选中的状态改变时触发checkAll事件 -->
  4. <input type="checkbox" :checked='isAll' @change="checkAll"/>
  5. </div>
  6. </template>
  7. <script>
  8. export default {
  9. name:'MyFooter',
  10. computed: {
  11. // 定义计算属性isAll, 用来展示复选框是否被选中
  12. isAll() {
  13. return (this.total === this.checkedCount) && (this.total > 0);
  14. },
  15. },
  16. methods: {
  17. // 复选框选中或取消选择时触发该事件
  18. checkAll(e) {
  19. this.checkAllTodo(e.target.checked);
  20. }
  21. }
  22. }
  23. </script>

方式2:

使用v-model双向绑定:

  1. <template>
  2. <div class="todo-footer" v-show="total">
  3. <!-- 使用v-model进行双向绑定 -->
  4. <input type="checkbox" v-model='isAll'/>
  5. </div>
  6. </template>
  7. <script>
  8. export default {
  9. name:'MyFooter',
  10. computed: {
  11. // 使用计算属性的完整写法,给出getter/setter
  12. isAll: {
  13. get(){
  14. return (this.total === this.checkedCount) && (this.total > 0);
  15. },
  16. set(value) { // 获取复选框是否被选中
  17. this.checkAllTodo(value);
  18. }
  19. },
  20. }
  21. }
  22. </script>

总结

组件化编码流程:

  1. 拆分静态组件:组件要按照功能点拆分,命名不要与html元素冲突
  2. 实现动态组件:考虑好数据的存放位置,数据是一个组件在用还是一些组件在用:

    1. 一个组件在用:放在组件自身即可
    2. 一些组件在用:放在他们共同的父组件上(即状态提升)
  3. 实现交互:从绑定事件开始

props适用于:

  • 父组件到子组件的通信
  • 子组件到父组件的通信(要求父组件先给子组件传递一个函数)

使用v-model是要注意:v-model绑定的值不能是props传过来的值,因为props是不可以修改的

props传过来的值如果是对象类型的值,修改对象中的属性时vue不会报错,但是不推荐这么做。