Vue 快速上手 - 组件、插槽、生命周期

3 篇文章 0 订阅
本文介绍了Vue的基础知识,包括组件的模板定义、组件通信(如props、$emit、ref)及插槽的使用。此外,还详细讲解了Vue组件的生命周期,包括beforeCreate、created、beforeMount、mounted等各个阶段,帮助理解Vue实例从创建到销毁的过程。
摘要由CSDN通过智能技术生成

github

更多学习资源和知识整理:https://github.com/ChenMingK/WebKnowledges-Notes

组件

模板

.vue 文件的模板大致是这样的:

<template>
  <div class="component-class"></div>
</template>

<script>
  import { } from ...

  export default {
    mixins: [],     // 混入(组合)
    components: {}, // 子组件(模板内使用的资源)
    props: { title: { type: Boolean, default: true} },  // 接口
    data () {},     // 本地状态-实例的数据对象
    computed: {},   // 本地状态-计算属性
    watch: {},      // 侦听属性
    methods: { plus: function () { this.a++ } },        // 方法

    // 生命周期钩子
    created () {},
    mounted () {}
  }
</script>

<style lang="scss" scoped>
  @import "../../mixin.scss"
</style>

组件通信

组件间的通信可分为父子组件通信、兄弟组件通信、跨级组件通信。
1.父子组件通信

  • props 选项:子组件可以通过 props 选项来接收父组件的数据,数据流的传输是单向的。
  • $emitv-on:子组件通过调用内置的 $emit 方法并传入事件名称来触发一个事件,父组件使用 v-on 监听子组件实例的任何事件。
  • $children$parent(不推荐使用):在子组件中,使用 this.$parent 可以直接访问该组件的父实例或组件,父组件也可以通过 this.$children 访问它所有的子组件,而且可以递归向上或向下无限访问,直到根实例或最内层的组件。
    -ref:父组件可以用特殊的属性 ref 来为子组件(或者DOM)指定一个索引名称。通过this.$refs.xxx可以访问到这个子组件。

2.兄弟组件通信与跨级组件通信

  • 中央事件总线 bus:创建一个名为 bus 的空 Vue 实例。其他组件都通过 bus 来发送事件并且监听来自 bus 的事件。
  • vuex:如果业务逻辑复杂,很多组件之间需要同时处理一些公共的数据,就需要使用 vuex,vuex 的做法就是将这一些公共的数据抽离出来,然后其他组件就可以对这个公共数据进行读写操作,这样达到了解耦的目的。

插槽

1.作用域:父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。

<navigation-link url="/profile">
  Clicking here will send you to: {{ url }}
  <!--
  这里的 `url` 会是 undefined,因为 "/profile" 是
  传递给 <navigation-link> 的而不是
  在 <navigation-link> 组件*内部*定义的。
  -->
</navigation-link>

2.后备内容:我们可能希望在一个<button>内绝大多数情况下都渲染文本“Submit”。为了将“Submit”作为后备内容,我们可以将它放在<slot>标签内:

<button type="submit">
  <slot>Submit</slot>
</button>

现在当我在一个父级组件中使用 <submit-button> 并且不提供任何插槽内容时:

<submit-button></submit-button>

后备内容“Submit”将会被渲染:

<button type="submit">
  Submit
</button>

内置组件

1.<component>

<!-- 动态组件由 vm 实例的属性值 `componentId` 控制 -->
<component :is="componentId"></component>

我们还需要引入使用到的组件,注意是放在 data 选项中:

  import StaffInfo from '../components/StaffInfo.vue'
  import LeaveTable from '../components/LeaveTable.vue'
  import SalaryTable from '../components/SalaryTable.vue'
  import GateTable from '../components/GateTable.vue'
  export default {
    data: function () {
      return {
        StaffInfo,
        LeaveTable,
        SalaryTable,
        GateTable
      }
    },

2.<transition>

  • 使用 v-show / v-if 动态显示或隐藏元素时,会触发过渡动画
  • transition 需要指定 name,并包裹一个含 v-show / v-if 的 div
  • vue 会为 transition 包裹的 div 动态添加 class,共6种

在这里插入图片描述
v-enter: 显示之前  v-enter-to: 显示之后  v-enter-active: 显示的过程
v-leave: 隐藏之前  v-leave-to: 隐藏之后  v-leave-active: 隐藏的过程
注意 transition 的样式必须和包裹的 div 同级(scss)

例如:

<transition name="fade">
  <div class="popup-bg" @click.stop.prevent="hide()" v-if="popupVisible"></div>
  <!--灰色的背景图层, 点击后弹窗隐藏. 禁止事件冒泡和预设行为-->
</transition>

这是一个淡入淡出的效果:

.fade-enter, .fade-leave-to {
  opacity: 0;
}
.fade-enter-to, .fade-leave {
  opacity: 1;
}
.fade-enter-active, .fade-leave-active {
  transition: all .3s linear;
}

3.<transition-group>

  • 不同于 ,它会以一个真实元素呈现:默认为一个。你也可以通过 tag 特性更换为其他元素。
  • 过渡模式不可用,因为我们不再相互切换特有的元素。
  • 内部元素总是需要提供唯一的 key 属性值。 不仅可以进入和离开动画,还可以改变定位。要使用这个新功能只需了解新增的 v-move 特性,它会在元素的改变定位的过程中应用。 像之前的类名一样,可以通过 name 属性来自定义前缀,也可以通过 move-class 属性手动设置。
<transition-group name="list"
                  tag="div"
                  id="item-list">
  <div class="item" v-for="(item, index) in items" :key="item.id"></div>   
</transition-group>
.list-move {
  transition: transform 1s;
}
.list-leave-active {
  display: none;
}

还需要注意以下事项:

  • name:用于自动生成 CSS 过渡类名
  • tag:这个<transition-group>组件在DOM中实际以什么样的形式存在,默认渲染为 <span>
  • 每个 <transition-group> 的子节点必须有独立的 key ,动画才能正常工作

可以看下这个 demo

4.<keep-alive>
https://cn.vuejs.org/v2/api/#keep-alive

生命周期

生命周期函数就是组件在初始化或者数据更新时会触发的钩子函数。

Vue 实例从创建到销毁的过程,就是生命周期。从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、销毁等一系列过程,称之为 Vue 的生命周期。

  • beforeCreate(创建前) 在实例初始化之后,数据观测 (data observer) 和event/watcher 事件配置之前被调用。从下面截取的 vue 源码可以看到beforeCreate调用的时候,是获取不到 props 或者 data 中的数据的,因为这些数据的初始化都在initState
Vue.prototype._init = function(options) {
  initLifecycle(vm)
  initEvents(vm)
  initRender(vm)
  callHook(vm, 'beforeCreate') // 拿不到 props data
  initInjections(vm)
  initState(vm)
  initProvide(vm)
  callHook(vm, 'created')
}
  • created(创建后) 在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el属性目前不可见。
export function mountComponent {
    callHook(vm, 'beforeMount')
    // ...
    if (vm.$vnode == null) {
        vm._isMounted = true
        callHook(vm, 'mounted')
    }
}
  • beforeMount(载入前) 在挂载开始之前被调用,相关的render函数首次被调用。实例已完成以下的配置:编译模板,把data里面的数据和模板生成html。注意此时还没有挂载html到页面上。

  • mounted(载入后) 在el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用。实例已完成以下的配置:用上面编译好的 html 内容替换 el 属性指向的 DOM 对象。完成模板中的 html 渲染到 html 页面中。

注意mounted不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用vm.$nextTick替换掉mounted

在这里插入图片描述
通过上图可以看到在 mounted 之前 p 中还是通过{{message}}进行占位的,因为此时还没有挂在到页面上,还是 JavaScript 中的虚拟 DOM 形式存在的。在 mounted 之后可以看到 h1 中的内容发生了变化。

  • beforeUpdate(更新前) 数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。

  • updated(更新后) 由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用计算属性]取而代之。

注意updated不会承诺所有的子组件也都一起被重绘。如果你希望等到整个视图都重绘完毕,可以用 vm.$nextTick 替换掉updated

updated: function () {
  this.$nextTick(function () {
    // Code that will run only after the
    // entire view has been re-rendered
  })
}
  • beforeDestroy(销毁前) 在实例销毁之前调用。实例仍然完全可用。
  • destroyed(销毁后) 在实例销毁之后调用。调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值