vue组件通讯等常用功能使用介绍

一、安装项目

可以使用vue UI 工具创建一个项目,具体过程看以往文章: 使用VUE UI 创建前端项目,这里我使用的版本是vue3

运行项目

npm run serve

运行启动成功,点击控制台地址
在这里插入图片描述
在这里插入图片描述
项目初始版本启动完成

二、父子组件通讯

1.Props:父组件向子组件传递数据,子组件通过props属性接收数据

测试案例:添加一个测试页面,并在index.js,App.vue中添加路由

index.js中添加
{
    path: '/test',
    name: 'test',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import('../components/ChildParentTset.vue')
  }
App.vue中添加
<template>
  <nav>
    <router-link to="/">Home</router-link> |
    <router-link to="/about">About</router-link> |
    <router-link to="/test">测试页面</router-link>
  </nav>
  <router-view/>
</template>

编写一个子组件,并接受来自父组件的数据

<template>
    <div>
        <h1>子组件</h1>
      <p>子组件接收到的数据:{{ parentData }}</p>
    </div>
  </template>
   
  <script>
  export default {
    props: {
      parentData: String
    }
  }
  </script>

引入子组件

<template>
    <div>
        <h1>引入子组件</h1>
      <child-component :parentData="data"></child-component>
    </div>
  </template>
   
  <script>
  import ChildComponent from './ChildComponent.vue'
   
  export default {
    components: {
      ChildComponent
    },
    data () {
      return {
        data: '父组件传递的数据'
      }
    }
  }
  </script>

运作第一个案例,刷新页面查看
在这里插入图片描述

或者你可以这样传递数据

<!-- 根据一个变量的值动态传入 -->
<BlogPost :title="post.title" />

<!-- 根据一个更复杂表达式的值动态传入 -->
<BlogPost :title="post.title + ' by ' + post.author.name" />

传递不同类型的数据

export default {
  props: {
    title: String,
    likes: Number
  }
}

对于以对象形式声明的每个属性,key 是 prop 的名称,而值则是该 prop 预期类型的构造函数。比如,如果要求一个 prop 的值是 number 类型,则可使用 Number 构造函数作为其声明的值。

对象形式的 props 声明不仅可以一定程度上作为组件的文档,而且如果其他开发者在使用你的组件时传递了错误的类型,也会在浏览器控制台中抛出警告。
传递不同的值类型​
在上述的两个例子中,我们只传入了字符串值,但实际上任何类型的值都可以作为 props 的值被传递。

Number

<!-- 虽然 `42` 是个常量,我们还是需要使用 v-bind -->
<!-- 因为这是一个 JavaScript 表达式而不是一个字符串 -->
<BlogPost :likes="42" />

<!-- 根据一个变量的值动态传入 -->
<BlogPost :likes="post.likes" />

Boolean

<!-- 仅写上 prop 但不传值,会隐式转换为 `true` -->
<BlogPost is-published />

<!-- 虽然 `false` 是静态的值,我们还是需要使用 v-bind -->
<!-- 因为这是一个 JavaScript 表达式而不是一个字符串 -->
<BlogPost :is-published="false" />

<!-- 根据一个变量的值动态传入 -->
<BlogPost :is-published="post.isPublished" />

Array

<!-- 虽然这个数组是个常量,我们还是需要使用 v-bind -->
<!-- 因为这是一个 JavaScript 表达式而不是一个字符串 -->
<BlogPost :comment-ids="[234, 266, 273]" />

<!-- 根据一个变量的值动态传入 -->
<BlogPost :comment-ids="post.commentIds" />

Object

<!-- 虽然这个对象字面量是个常量,我们还是需要使用 v-bind -->
<!-- 因为这是一个 JavaScript 表达式而不是一个字符串 -->
<BlogPost
  :author="{
    name: 'Veronica',
    company: 'Veridian Dynamics'
  }"
 />

<!-- 根据一个变量的值动态传入 -->
<BlogPost :author="post.author" />

使用一个对象绑定多个 prop
如果你想要将一个对象的所有属性都当作 props 传入,你可以使用没有参数的 v-bind,即只使用 v-bind 而非 :prop-name。例如,这里有一个 post 对象:

const post = {
  id: 1,
  title: 'My Journey with Vue'
}

以及下面的模版

<BlogPost v-bind="post" />

而实际上等价于

<BlogPost :id="post.id" :title="post.title" />

单向数据流
所有的 props 都遵循着单向绑定原则,props 因父组件的更新而变化,自然地将新的状态向下流往子组件,而不会逆向传递。如果子组件执意要修改则会警告

const props = defineProps(['foo'])

// ❌ 警告!prop 是只读的!
props.foo = 'bar'

prop的校验

defineProps({
  // 基础类型检查
  // (给出 `null` 和 `undefined` 值则会跳过任何类型检查)
  propA: Number,
  // 多种可能的类型
  propB: [String, Number],
  // 必传,且为 String 类型
  propC: {
    type: String,
    required: true
  },
  // 必传但可为空的字符串
  propD: {
    type: [String, null],
    required: true
  },
  // Number 类型的默认值
  propE: {
    type: Number,
    default: 100
  },
  // 对象类型的默认值
  propF: {
    type: Object,
    // 对象或数组的默认值
    // 必须从一个工厂函数返回。
    // 该函数接收组件所接收到的原始 prop 作为参数。
    default(rawProps) {
      return { message: 'hello' }
    }
  },
  // 自定义类型校验函数
  // 在 3.4+ 中完整的 props 作为第二个参数传入
  propG: {
    validator(value, props) {
      // The value must match one of these strings
      return ['success', 'warning', 'danger'].includes(value)
    }
  },
  // 函数类型的默认值
  propH: {
    type: Function,
    // 不像对象或数组的默认,这不是一个
    // 工厂函数。这会是一个用来作为默认值的函数
    default() {
      return 'Default function'
    }
  }
})

2. $emit 和$on:子组件向父组件传递数据,子组件通过$emit触发事件,父组件通过$on监听事件并接收数据。

$emit():在当前组件触发一个自定义事件。任何额外的参数都会传递给事件监听器的回调函数。
子组件定义事件名,及传递参数

<template>
  <div>
    <button @click="handleClick">点击发送数据给父组件</button>
  </div>
</template>
 
<script>
export default {
  methods: {
    handleClick () {
      this.$emit('childEvent', '子组件传递的数据')
    }
  }
}
</script>

父组件声明事件,并接受参数数据的传递

<template>
  <div>
    <child-component @childEvent="handleChild"></child-component>
  </div>
</template>
 
<script>
import ChildComponent from './ChildComponent.vue'
 
export default {
  components: {
    ChildComponent
  },
  methods: {
    handleChild (data) {
      alert('父组件接收到的数据:' + data);
    }
  }
}
</script>

运行查看
在这里插入图片描述
在这里插入图片描述
传递多个参数
示例:

export default {
  created() {
    // 仅触发事件
    this.$emit('foo')
    // 带有额外的参数
    this.$emit('bar', 1, 2, 3)
  }
}

3.使用$refs.调用组件实例来传递

父组件

<template>
  <div>
    <button @click="handleClick">向子组件传递数据</button>
    <child-component ref="child"></child-component>
  </div>
</template>
 
<script>
import ChildComponent from './ChildComponent.vue'
 
export default {
  components: {
    ChildComponent
  },
  methods: {
    handleClick () {
      this.$refs.child.handleData('父组件传递的数据')
    }
  }
}
</script>

子组件

<template>
  <div>
    子组件
  </div>
</template>
 
<script>
export default {
  methods: {
    handleData (data) {
      console.log('子组件接收到的数据:' + data)
    }
  }
}
</script>

刷新查看
在这里插入图片描述

4.依赖注入:Provide (提供),nject (注入)

Prop 逐级透传问题​
通常情况下,当我们需要从父组件向子组件传递数据时,会使用 props。想象一下这样的结构:有一些多层级嵌套的组件,形成了一棵巨大的组件树,而某个深层的子组件需要一个较远的祖先组件中的部分数据。在这种情况下,如果仅使用 props 则必须将其沿着组件链逐级传递下去,这会非常麻烦:
在这里插入图片描述
provide 和 inject 可以帮助我们解决这一问题
在这里插入图片描述

provide(/* 注入名 */ 'message', /* 值 */ 'hello!')

provide() 函数接收两个参数。第一个参数被称为注入名,可以是一个字符串或是一个 Symbol。后代组件会用注入名来查找期望注入的值。一个组件可以多次调用 provide(),使用不同的注入名,注入不同的依赖值。第二个参数是提供的值,值可以是任意类型,包括响应式的状态

父组件

<script setup>
import { ref, provide } from 'vue'
import GrandChild from './ChildComponent.vue'

const message = ref('hello')
provide('message', message)
</script>

<template>
  <input v-model="message">
  <GrandChild />
</template>

子组件

<script setup>
import { inject } from 'vue'

const message = inject('message')
</script>

<template>
  <p>
    Message to grand child: {{ message }}
  </p>
</template>

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值