Blogger Information
Blog 29
fans 1
comment 0
visits 35288
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
组件基础与组件之间的通信
祥子弟弟
Original
789 people have browsed it

一、组件知识

组件,从形式上看,组件就是一个自定义的 html 标签;组件本质上来看是一个可复用的 Vue 实例,是构造函数 Vue 的一个子类;组件实现了代码复用。从组件的层面上来理解,Vue 的挂载点就是一个组件,不过它是一个隐式声明根组件。

创建一个组件需要进行两个步骤

  1. 创建组件,定义一个名字为child-component的新组件(使用 Vue.component 创建的组件为全局组件)
  1. <!-- 创建一个新组件 -->
  2. <script>
  3. Vue.component("child-component", {
  4. template: `<h1>Helo World</h1>`,
  5. data() {
  6. return {};
  7. },
  8. });
  9. </script>

其中 “child-component” 是创建的组件的名字(用户自定义的 html 标签),后边的对象{}中的内容是组件的配置项,其中 template 中的内容是一个字符串模板,作为 Vue 实例的标识使用。模板将会替换挂载的元素,也就是挂载点上的<child-component></child-component>这一对自定义 html 标签。挂载元素的内容都将被忽略,除非模板的内容有分发插槽。由于组件是一个 Vue 的子类,所以它的属性也是由一个函数data(){return{}}返回一个对象来实现的。

2.挂载,将自定义的 html 标签放到 Vue 挂载点的子结点上

  1. <body>
  2. <!-- 挂载点是一个隐式声明根组件, -->
  3. <div class="app">
  4. <!-- 自定义html标签 -->
  5. <child-component></child-component>
  6. </div>
  7. <script>
  8. // 将组件名放到挂载点的子结点中
  9. const vm = new Vue({
  10. el: ".app",
  11. data() {
  12. return {};
  13. },
  14. });
  15. </script>
  16. </body>

声明组件的目的就是实现代码复用,将这个组件可以重复的放置在已经挂载好的根节点中

例如

  1. <body>
  2. <!-- 挂载点是一个隐式声明根组件, -->
  3. <div class="app">
  4. <!-- 自定义html标签 -->
  5. <child-component></child-component>
  6. <child-component></child-component>
  7. <child-component></child-component>
  8. </div>
  9. </body>


上述示例中,组件的创建是通过Vue.component来实现的。这样声明的组件是全局组件,它在全局可见,声明在 Vue 实例外部,全局组件可以在多个 Vue 实例中共享,不过尽可能不要去声明一个全局组件,减少全局污染。因为通常一个项目只有一个 Vue 实例,所以尽可能不要用全局组件,而应该使用局部组件代替。

局部组件的声明
局部组件是属于 Vue 实例的,使用 components 声明。

  1. <body>
  2. <div class="app">
  3. <child-hello></child-hello>
  4. </div>
  5. <script>
  6. const vm = new Vue({
  7. el: ".app",
  8. data() {
  9. return {};
  10. },
  11. // 声明一个局部组件
  12. components: {
  13. childHello: {
  14. template: `<p>Hello {{site}}</p>`,
  15. data() {
  16. return {
  17. site: "php中文网",
  18. };
  19. },
  20. },
  21. });
  22. </script>
  23. </body>

<child-hello></child-hello>,是定义的局部组件。但是在 dom 结构中是找不到的。

二、组件之间的通信

父组件向子组件传参

父组件是通过自定义属性的方式将参数传到子组件中的, 然后子组件中用固定属性名称 props 来接收父组件自定义的属性名。

现在我们来声明一个子组件,将其放到挂载点下,然后在子组件中不进行属性声明,所有的属性在父组件中声明定义,然后试着将这些父组件中的属性传递到子组件中。

  1. <body>
  2. <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>
  3. <div id="app">
  4. <!-- 父组件,父组件是通过自定义属性的方式将参数传到子组件中的 -->
  5. <btn-inc :user-name="username" :parent-count="count"></btn-inc>
  6. <p>{{count}}</p>
  7. </div>
  8. <script>
  9. const vm = new Vue({
  10. el: "#app",
  11. data() {
  12. return {
  13. username: "父组件的变量",
  14. count: 0,
  15. };
  16. },
  17. // 局部组件
  18. components: {
  19. btnInc: {
  20. // 使用固定属性名称props来接收父组件自定义的属性名
  21. props: ["userName", "parentCount"],
  22. // 组件之间的数据传递是单向的,不允许在子组件中更新父组件中的数据
  23. template: `<div>
  24. <button @click="num++">点赞:+ {{num}}</button>
  25. <span>{{userName}}</span>
  26. </div>`,
  27. data() {
  28. return {
  29. num: this.parentCount,
  30. };
  31. },
  32. },
  33. },
  34. });
  35. // 子组件中的数据变化更新父组件的数据,通过消息传递(事件)实现
  36. console.log(vm.count);
  37. </script>
  38. </body>

父组件中的自定义属性的值可以来自根组件的 data,不过如果使用根组件上的变量就要对自定义属性进行 v-bind 绑定,父组件中的自定义属性名尽量写成”:user-name”,而在子组件中接收的时候应该写成”userName”的形式。

试着直接使用父组件data中的count直接使用在子组件的template,会发现根本就不可以进行渲染,根本就识别不出来。只能通过父组件自定义属性绑定到父组件上,然后再传参才可以在子组件中拿到父组件中的数据。而且父组件中的数据拿过来之后,也就是通过props获取到之后,不能对其进行修改,如果想要进行改变值的操作,就只能在子组件的data中重新定义一个变量接收,然后对这个变量进行修改,如果不这样做,Vue 就会报错。

在子组件的template中直接使用父组件的属性进行修改,会出现如下报错情况。

template: <div> <button @click="parentCount++">点赞:+ {{parentCount}}</button> <span>{{userName}}</span> </div>,

报错情况

而且改变之后,对于父组件中的 count 是没有影响的。

子组件向父组件传参

子组件中的数据变化更新父组件的数据,通过消息传递(事件)实现,子组件向父组件传参是通过声明同名事件来实现的。
在子组件的templatehtml 字符串中定义事件,必须对事件使用$emit()事件方法,$emit(父组件中要使用的方法名称,子组件要传给父组件的值)

现在来列举一个子组件向父组件传参的例子

  1. <body>
  2. <div id="app">
  3. <btn-inc
  4. :user-name="username"
  5. :parent-count="count"
  6. @click-count="handle"
  7. ></btn-inc>
  8. </div>
  9. <script>
  10. const vm = new Vue({
  11. el: "#app",
  12. data() {
  13. return {
  14. username: "父组件的变量",
  15. count: 0,
  16. };
  17. },
  18. // 局部组件
  19. components: {
  20. btnInc: {
  21. // 使用固定属性名称props来接收父组件自定义的属性名
  22. props: ["userName", "parentCount"],
  23. // 必须使用$emit()事件方法
  24. // $emit(父组件中要使用的方法名称,子组件要传给父组件的值)
  25. template: `<div>
  26. <button @click="$emit('click-count',num)">点赞:+ {{parentCount}}</button>
  27. <span>{{userName}}</span>
  28. </div>`,
  29. data() {
  30. return {
  31. num: 1,
  32. };
  33. },
  34. },
  35. },
  36. // 父组件更新数据的方法
  37. methods: {
  38. handle(value) {
  39. console.log(this.count);
  40. this.count += value;
  41. },
  42. },
  43. });
  44. </script>
  45. </body>

父组件中通过定义同名事件,来对子组件中的数据进行接收,另外,这个子组件传递的参数可以是任何类型。

总结:

  1. 父组件向子组件传参:通过自定义属性
  2. 子组件向父组件传参:通过自定义方法
Correcting teacher:天蓬老师天蓬老师

Correction status:qualified

Teacher's comments:
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!