Vue中父子组件传值详解

原文链接:小火柴的蓝色理想-Vue组件选项props
参考:塗塗-简单了解vue中父子组件如何相互传递值(基础向)

最简单的父子组件传值例子-todoList:
参考:菜鸟教程-vue3-在组件上使用v-for
在这里插入图片描述
父组件div模板:

<div id="todo-list-example">
  <form v-on:submit.prevent="addNewTodo">
    <label for="new-todo">添加 todo</label>
    <input
      v-model="newTodoText"
      id="new-todo"
      placeholder="例如:明天早上跑步"
    />
    <button>添加</button>
  </form>
  <ul>
    <todo-item
      v-for="(todo, index) in todos"
      :key="todo.id"
      :title="todo.title"
      @remove="rootComRemove(index)"
    ></todo-item>
  </ul>
</div>

注意:这里是子组件给父组件传值,<todo-item>元素内使用了v-bind绑定了方法remove,给它赋值rootComRemove(index)表示父组件的remove指向了父组件内的rootComRemove(index)方法,因此要在父组件的methods内写方法rootComRemove(index);
在这里插入图片描述
父组件给子组件传值:
在子组件内使用props选项声明需要接收的父组件数据,父组件内用该声明名称传递数据,就可以在子组件内使用父组件传来的值:
在这里插入图片描述

在这里插入图片描述
子组件给父组件传值:
在父组件模板中先在子组件的标签上给元素绑定要发送的方法:
在这里插入图片描述
注意上图倒数第四行@remove这里,当父组件接收到的方法处理很简单时,这里可以不写rootComRemove方法名,而是使用内联Javascript写法,直接写对应的父组件处理函数,比如这里可以直接用@remove="todos.splice(index, 1)"删除一项。

父组件中写接收到的方法的处理函数:
在这里插入图片描述

子组件中使用emits选项声明要发送的方法,
在这里插入图片描述

全部代码:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="todo-list-example">
  <form v-on:submit.prevent="addNewTodo">
    <label for="new-todo">添加 todo</label>
    <input
      v-model="newTodoText"
      id="new-todo"
      placeholder="例如:明天早上跑步"
    />
    <button>添加</button>
  </form>
  <ul>
    <todo-item
      v-for="(todo, index) in todos"
      :key="todo.id"
      :title="todo.title"
      @remove="rootComRemove(index)"
    ></todo-item>
  </ul>
</div>
 
<script>
const app = Vue.createApp({
  data() {
    return {
      newTodoText: '',
      todos: [
        {
          id: 1,
          title: '看电影'
        },
        {
          id: 2,
          title: '吃饭'
        },
        {
          id: 3,
          title: '上 RUNOOB 学习'
        }
      ],
      nextTodoId: 4
    }
  },
  methods: {
    addNewTodo() {
      this.todos.push({
        id: this.nextTodoId++,
        title: this.newTodoText
      })
      this.newTodoText = ''
    },
	rootComRemove(index) {
		this.todos.splice(index, 1)
	}
  }
})

//子组件,采用Vue.component()全局注册,第一个参数是子组件名,第二个参数是选项对象
app.component('todo-item', {
	// template中,父组件向子组件传值时,使用props选项中接收到的数据名称
	// 子组件向父组件传值时,给元素绑定事件,采用$emit('事件名')声明点击子组件中该元素后发生的事件	
  template: `
    <li>
      {{ title }}
      <button @click="$emit('remove')">删除</button> 
    </li>
  `,
  props: ['title'], // 子组件中使用props选项声明需要从父组件中接收的数据,注意使用中括号包裹字符串
  // 子组件向父组件传值
  emits: ['remove'] // 需要在子组件中使用emits选项将子组件template选项中某元素绑定的事件名发送出去
})

app.mount('#todo-list-example')
</script>
</body>
</html>

以上案例运行展示:菜鸟教程在线编辑器-vue父子组件传值





复制到“命名约定“部分。

组件接受的选项大部分与Vue实例一样,而选项props是组件中非常重要的一个选项。在 Vue 中,父子组件的关系可以总结为 props down, events up。父组件通过 props 向下传递数据给子组件,子组件通过 events 给父组件发送消息。本文将详细介绍Vue组件选项props。
在这里插入图片描述

父子级组件

在介绍props之前,先介绍父子级组件的写法。

在一个良好定义的接口中尽可能将父子组件解耦是很重要的。这保证了每个组件可以在相对隔离的环境中书写和理解,也大幅提高了组件的可维护性和可重用性。

【错误写法】
现在来介绍两种父子级组件的错误写法

下面这种形式的写法是错误的,因为当子组件注册到父组件时,Vue.js会编译好父组件的模板,模板的内容已经决定了父组件将要渲染的HTML<parent>...</parent>运行时,它的一些子标签只会被当作普通的HTML来执行,<child></child>不是标准的HTML标签,会被浏览器直接忽视掉。

<div id="example">
  <parent>
    <child></child>
    <child></child>
  </parent>
</div>

在父组件标签之外使用子组件也是错误的:

<div id="example">
  <parent></parent>
  <child></child>
</div>

【正确写法】:

<div id="example">
  <parent></parent>
</div>
<script>
var childNode = {
  template: '<div>childNode</div>',
}
var parentNode = {
  template: `
  <div class="parent">
    <child></child>
    <child></child>
  </div>
  `,
  components: {
    'child': childNode
  } 
};
// 创建根实例
new Vue({
  el: '#example',
    components: {
    'parent': parentNode
  }  
})
</script>

在这里插入图片描述

静态props

组件实例的作用域是孤立的。这意味着不能 (也不应该) 在子组件的模板内直接引用父组件的数据。要让子组件使用父组件的数据,需要通过子组件的 props 选项

使用Prop传递数据包括静态和动态两种形式,下面先介绍静态props.

子组件要显式地用 props 选项声明它期待获得的数据

var childNode = {
  template: '<div>{{message}}</div>',
  props:['message']
}

静态Prop通过为子组件在父组件中的占位符添加特性的方式来达到传值的目的.

<div id="example">
  <parent></parent>
</div>
<script>
var childNode = {
  template: '<div>{{message}}</div>',
  props:['message']
}
var parentNode = {
  template: `
  <div class="parent">
    <child message="aaa"></child>
    <child message="bbb"></child>
  </div>`,
  components: {
    'child': childNode
  }
};
// 创建根实例
new Vue({
  el: '#example',
  components: {
    'parent': parentNode
  }
})
</script>

在这里插入图片描述

命名约定

对于props声明的属性来说,在父级HTML模板中,属性名需要使用中划线写法。

var parentNode = {
  template: `
  <div class="parent">
    <child my-message="aaa"></child>
    <child my-message="bbb"></child>
  </div>`,
  components: {
    'child': childNode
  }
};

子级props属性声明时,使用小驼峰或者中划线写法都可以;而子级模板使用从父级传来的变量时,需要使用对应的小驼峰写法。

var childNode = {
  template: '<div>{{myMessage}}</div>',
  props:['myMessage']
}
var childNode = {
  template: '<div>{{myMessage}}</div>',
  props:['my-message']
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值