Vue高级(一)- 组件 | 青训营

91 阅读3分钟

Vue 高级-组件

参考:《Spring Boot + Vue 开发实战》第12章,12.1。

1 组件

组件是Vue的核心之一,它们可以扩展HTML元素,封装可重用代码,并能让开发者独立的、可复用的小组件来构建大应用。一个组件可以定义很多选项,最核心的如下:

  • 模板: 反映了数据和最终实现给用户的DOM之间的映射关系。
  • 初始数据:一个组件的数据初始化状态。对于可重复组件来说,通常私有状态。
  • 接受的外部参数:组件之间通过参数进行数据的传递共享,参数默认是单向绑定,但也可以声明为双向绑定。
  • 方法:对数据的改动操作一般都在组件内进行,可以通过v-on指令将用户输入的事件和组件方法进行绑定。
  • 声明周期函数:一个组件会触发多个生命周期函数,在这些函数中可以封装一些自定义的逻辑。

Vue官网中的组件文档: cn.vuejs.org/guide/essen…

1.1 定义组件

一个简单的内容转换:点击button后将中文转换为英文语句。

<template>
  <div id="container">
    <div>
      {{ message }}
    </div>
    <button @click="change">点击</button>
  </div>
</template>

<script lang="ts">
export default {
  name: 'A',
  props: {},
  data () {
    return {
      message: "你好,我是A组件",
    }
  },
  methods: {
    change: function () {
      this.message = "Hello, this is A component"
    }
  },
}
</script>

<style scoped>
  #container{
    width: 800px;
    margin: 10px auto;
  }
  
</style>

在JavaScript中,使用了export default的方式到处定义的对象,而没有使用new Vue({})的方式。这是因为new Vue({})只是创建一个Vue示例,相当于创建一个跟组件,而export default是将组件加入组件树中,可以复用组件。

另外data()也不再是一个属性,而是一个方法,这是因为组件可以被复用。

有两种方式可以对此组件进行访问:一是通过配置路由的方式直接访问,二是在已经配置好的路由的组件中引入该组件,即复用组件。

1.2 复用组件

复用组件就像是在Vue项目的Home组件中引入HelloWorld组件。因为Home组件已经配置了路由,即可以通过路由地址在浏览器中访问Home组件。那如果在Home组件中引入A组件,则可以实现组件的复用,即在没有学习Vue路由之前,方便地访问A组件。

将Home组件略加改造,让它不再引入HelloWorld组件,而是引入A组件:

将A引入App.vue

<script setup lang="ts">
// 导入子组件
//import HelloWorld from './components/HelloWorld.vue'
import A from './components/A.vue'

</script>

中间插入Page.vue,将A.vue和B.vue引入Page.vue,最后将Page.vue引入App.vue。通过修comp的值可以在Vue页面A和B之间切换。

<template>
  <div v-if="comp=='A'">
    <A></A>
  </div>
  <div v-else-if="comp=='B'">
    <B></B>  
  </div>
</template>

<script lang="ts">
  // 导入子组件
  import A from "./A.vue"
  import B from "./B.vue"

export default {
  name: 'Home',
  data () {
    return {
      comp:''
    }
  },
  components: {
    A, B
  },
  created () {
    this.comp="B"
  },
}
</script>

<style scoped>
  
</style>

1.3 组件传参

在大多数情况下,组件都是父组件向子组件传参,但也有某些场景由于子组件处理完毕后会影响子组件,因此需要向父组件传参。

首先,先看一下父组件向子组件传参的情况。在子组件中通过props属性接收父组件的传参,props属性值是一个JavaScript对象。在该对象中指定接收的参数名和类型。如果不限制传参类型,则可以使用props:[name,gender,……]的方式,这样参数类型默认是字符串。

子组件中添加参数name

  props:{
    name: String
  },

父组件中传参:

  <component v-bind:is="comp" name="Ryam" ></component>

接下来,看一下子组件向父组件传参的情况。在父组件Home中,使用@符号指定一个子组件调用父组件的方法,赋值给父组件中已定义的方法,即当子组件使用$emit调用函数receiveMes()方法时,则会调用父组件的changeMes方法,代码如下:

<template>
  <div class="home">
    <div>{{ message }}</div>
  <component v-bind:is="comp" name="Ryam" @receiveMes="changeMes"></component>
  </div>
</template>

<script lang="ts">
  // 导入子组件
  import A from "./A.vue"
  import B from "./B.vue"

export default {
  name: 'Home',
  data () {
    return {
      comp: "",
      message: {}
    }
  },
  components: {
    A, B
  },
  computed: {
    
  },
  watch: {
    
  },
  methods: {
    changeMes: function (mes:String){
      this.message = mes;
    },
  },
  created () {
    this.comp="A"
  },
  mounted () {
    
  },
}
</script>

<style scoped>
  
</style>

<template>
  <div id="container">
    <div>
      <!-- {{ name + message }} -->
      {{ name }}
      {{ message }}
    </div>
    <button @click="change">点击</button>

    <br>

    <button @click="sendMes">发送消息到父组件</button>
  </div>
</template>

<script lang="ts">

export default {
  name:"A",
  props:{
    name: String
  },
  data () {
    return {
      message: "你好, 我是A组件",
    }
  },
  methods: {
    change: function () {
      this.message = "Hello, this is A component"
    },
    sendMes: function(){
      this.$emit("receiveMes", "这是A组件发送到父组件的信息")
    }
  }
}
</script>

<style scoped>
  #container{
    width: 800px;
    margin: 10px auto;
  }
</style>