源代码地址 异步组件 众所周知,vue 在使用单页时,会生成一个 app.js,app.js 就是打包的各项依赖的集合,我们常用 import 引入包或者组件,每次 import 后,都会把打包的代码放入 app.js 中,有时候我们希望在进入另一个路由的时候,再加载某个组件,达到异步的效果。2.4 之前是能通过 路由懒加载 或者 keep-alive 提升性能,2.4 版本中提出了异步组件的概念…

异步组件

众所周知,vue 在使用单页时,会生成一个 app.js,app.js 就是打包的各项依赖的集合,我们常用 import 引入包或者组件,每次 import 后,都会把打包的代码放入 app.js 中,有时候我们希望在进入另一个路由的时候,再加载某个组件,达到异步的效果。2.4 之前是能通过路由懒加载或者 keep-alive 提升性能,2.4 版本中提出了异步组件的概念:按需加载组件,达到提升性能的目的。
使用条件:vue 版本大于 2.4 vue-router 大于 2.4

1. 路由的异步导入

// router/index.js
// import Demo1 from "../components/demo1.vue"
// import Demo2 from "../components/demo1.vue"
routes: [
  {
    path: "/",
    redirect: "/demo1"
  },
  {
    path: "/demo1",
    component: () => import("../components/demo1.vue")
    // component: Demo1
  },
  {
    path: "/demo2",
    component: () => import("../components/demo2.vue")
    // component: Demo2
  }
];
  • 这里面需要注意:只要 import 组件后,就会打包放入 app.js 中

  • 使用异步导入:先进入/demo1,demo2.vue 是没有加载的

  • 使用 import 导入组件:先进入/demo1,demo2.vue 加载了

2. 组件异步导入

<!-- demo01.vue -->
<div class="">
  这就是1
  <!-- 我就是注释,这次我不删除 -->
  <Child></Child>
</div>
Child: () => import("./demo3.vue");
<!-- demo02.vue -->
<div class="">
  这就是2
</div>
  • 先进入/demo2 先加载 demo2 组件,进入/demo1 后才去加载 demo1.vue 和 demo2.vue 组件
  • 使用 import 导入组件,一次性 demo1.vue demo2.vue demo3.vue 同时加载

父子组件数据传递( inheritAttrs + $attrs)

众所周知,如果父组件想传给孙组件值(父-子-孙)就得父=>子 子->孙,可不可以父直接到孙?2.4 支持了

<!-- 父:demo2.vue -->
<Child :propa="propa" :propb="propb"></Child>
// 父:demo2.vue
export default {
  props: ["propa"]
};
  • 子没有注册 propb,渲染结果
<!-- 子:demo3.vue -->
<div propb="propb">propa</div>
  • 设置 inheritAttrs:false 不会把未被注册的 propb 呈现为普通的 HTML 属性 并且子可以通过**$attrs**获取到未注册的 propb,传递给孙
<!-- 子:demo3.vue -->
<InnerChild :propb="$attrs.propb"></InnerChild>
<!-- 孙:demo4.vue -->
<div>
  inner-child的propb:{{propb}}
</div>

这样子组件可以不用注册 propb,孙组件依然能获取到 propb

父子组件通信$listeners

$listeners官方解释:包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。通俗理解就是子组件可以触发父组件的事件。

  • demo1.vue
<div class="">
  这就是1
  <Child :name="name" :sex="sex" @click="onTest"></Child>
</div>
export default {
  components: {
    Child: () => import("./demo3.vue")
  },
  data() {
    return {
      name: "child",
      sex: "man"
    };
  },
  computed: {},
  watch: {},
  methods: {
    onTest() {
      console.log("父级组件的点击事件");
    }
  },
  created() {},
  mounted() {}
};
  • demo2.vue
<div class="">
  <div class="">
    这就是2
  </div>
</div>
export default {
  components: {},
  data() {
    return {};
  },
  computed: {},
  watch: {},
  methods: {},
  created() {},
  mounted() {}
};
  • demo3.vue
<div class="">
  child的name:{{name}}
  <InnerChild :sex="$attrs.sex" @click="onTest" v-on="$listeners"></InnerChild>
</div>
export default {
  inheritAttrs: false,
  props: {
    name: String
  },
  components: {
    InnerChild: () => import("./demo4.vue")
  },
  data() {
    return {};
  },
  computed: {},
  watch: {},
  methods: {
    onTest() {
      console.log("子级组件的点击事件");
    }
  },
  created() {},
  mounted() {}
};
  • demo4.vue
<div class="">
  inner-child的Sex:{{sex}}
  <div @click="test">button</div>
</div>
export default {
  props: {
    sex: String
  },
  data() {
    return {};
  },
  computed: {},
  watch: {},
  methods: {
    test() {
      console.log("孙级组件派发点击事件");
      this.$emit("click");
    }
  },
  created() {},
  mounted() {}
};

可以看出,只要在孙组件注册了“click”事件,点击派发一次,那么子组件,父组件都会响应,因为子父都监听了“click”事件,如果取消了 v-on="$listeners",那么子组件可以监听“click”,但是父组件就监听不了了。

暂无评论