chaihongjun.me

Vue中父子组件的生命周期

利用Vuecli脚手架搭建一个Demo:

App.vue

<template>
  <div id="nav">
    <router-link to="/">Home</router-link> |
    <router-link to="/about">About</router-link>
  </div>
  <router-view />
</template>
<script>
export default {
  name: "App",
  beforeCreate() {
    console.log("App beforeCreate", this.$data, this.$el);
  },
  created() {
    console.log("App created", this.$data, this.$el);
  },
  beforeMount() {
    console.log("App beforeMount", this.$data, this.$el);
  },
  mounted() {
    console.log("App mounted", this.$data, this.$el);
  },
  beforeUpdate() {},
  updated() {},
};
</script>
<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}
#nav {
  padding: 30px;
  a {
    font-weight: bold;
    color: #2c3e50;
    &.router-link-exact-active {
      color: #42b983;
    }
  }
}
</style>

Home.vue

<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png" />
    <HelloWorld
      msg="Welcome to Your Vue.js App"
      proper="1"
      @custome="handler"
      :list="list"
    >
      <template v-slot:two="{ slottwo }">
        {{ home }} - 子组件插槽的数据: {{ slottwo }}
      </template>
    </HelloWorld>
  </div>
</template>
<script>
import HelloWorld from "@/components/HelloWorld.vue";
export default {
  name: "Home",
  data() {
    return {
      home: "主页",
      list: [
        { name: "马冬梅", age: 19, gender: "女" },
        { name: "周冬雨", age: 23, gender: "女" },
        { name: "周杰伦", age: 20, gender: "男" },
        { name: "温兆伦", age: 22, gender: "男" },
      ],
    };
  },
  components: { HelloWorld },
  methods: {
    handler(args) {
      console.log("子组件传递的参数:", args);
    },
  },
  beforeCreate() {
    console.log("Home beforeCreate", this.$data, this.$el);
  },
  created() {
    console.log("Home created", this.$data, this.$el);
  },
  beforeMount() {
    console.log("Home beforeMount", this.$data, this.$el);
  },
  mounted() {
    console.log("Home mounted", this.$data, this.$el);
  },
  beforeUpdate() {
    console.log("Home beforeUpdate", this.$data, this.$el);
  },
  updated() {
    console.log("Home updated", this.$data, this.$el);
  },
};
</script>

HelloWorld.vue

<template>
  <div>
    <h1>{{ msg }}</h1>
    <span>这里是插槽内容:</span>
    <slot slotone="01" name="one"></slot>
    <slot :slottwo="keyword" name="two"></slot>
    <hr />
    <button @click="$emit('custome', '参数')">点击传递参数</button>
    <hr />
    <p>输入姓名只显示相关信息</p>
    <input
      type="text"
      placeholder="请输入姓名"
      v-model="keyword"
      @keyup.delete="backspace"
    />
    <button @click="sort(1)">正序排序</button>
    <button @click="sort(-1)">倒序排序</button>
    <button @click="sort(0)">恢复默认</button>
    <ul>
      <li v-for="(item, index) in infos" :key="index">
        {{ item.name }}-{{ item.age }}-{{ item.gender }}
      </li>
    </ul>
    <hr />
    自定义指令:
    <p v-big>自定义指令</p>
  </div>
</template>
<script>
export default {
  name: "HelloWorld",
  data() {
    return {
      keyword: "",
      infos: this.list,
      type: 0,
    };
  },
  props: {
    msg: String,
    list: Array,
  },
  watch: {
    keyword(newVal, oldVal) {
      if (!newVal) {
        this.infos = this.list;
      }
      this.infos = this.infos.filter((item) => {
        return item.name.indexOf(newVal) !== -1;
      });
    },
  },
  methods: {
    backspace() {
      this.infos = this.list;
      this.infos = this.infos.filter((item) => {
        return item.name.indexOf(this.keyword) !== -1;
      });
    },
    sort(type) {
      if (type === 0) {
        this.infos = this.list;
      } else if (type === 1) {
        this.infos = this.infos.sort(function (a, b) {
          return a.age - b.age;
        });
      } else if (type === -1) {
        this.infos = this.infos.sort(function (a, b) {
          return b.age - a.age;
        });
      }
    },
  },
  directives: {
    big(a, b) {
      // console.dir(b);
    },
  },

  // setup(props, context) {
  //   console.log("props:", props);
  //   console.log("context:", context);
  //   const { attrs, slots, emit } = context;
  //   console.log("attrs:", attrs);
  //   console.log("slots:", slots);
  //   console.log("emit:", emit);
  // },

  beforeCreate() {
    console.log("HelloWorld beforeCreate", this.$data, this.$el);
  },
  created() {
    console.log("HelloWorld created", this.$data, this.$el);
  },
  beforeMount() {
    console.log("HelloWorld beforeMount", this.$data, this.$el);
  },
  mounted() {
    console.log("HelloWorld mounted", this.$data, this.$el);
  },
  beforeUpdate() {
    console.log("HelloWorld beforeUpdate", this.$data, this.$el);
  },
  updated() {
    console.log("HelloWorld updated", this.$data, this.$el);
  },
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

QQ截图20210922103648.png

页面加载效果如上图,helloworld是Home的子组件,父子组件加载顺序是:

父组件(beforeCreate)->父组件(created)->父组件(beforeMount)->子组件(beforeCreate)->子组件(created)->子组件(beforeMount)->子组件(mounted)->父组件(mounted)

子组件的生命周期“插队”添加到了父组件挂载(mounted)之前。也就是说,父组件在挂载完成前会完成子组件的创建和挂载

另外,图示的箭头部分说明DOM的渲染是在挂载(mounted)部分完成的,蓝色和绿色框说明数据的“识别监测”是在(created)完成的。

知识共享许可协议本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。作者:chaihongjun»