【vue其他相关】总结组件和JS的所有引入写法(按需,动态等),原理不定期更新!

文章目录

  • 组件
    • 单个普通引入
    • 从文件夹中引入
    • 按需/异步引入
    • 按需引入的原理
      • 预加载
      • 懒加载
      • 优缺点
    • 全局引入单个
    • 全局引入文件夹内所有的
    • 动态组件
  • 第三方库或自封工具(JS引入)
    • 按需引入
    • 触发按需引入

组件

单个普通引入

import Header from './components/Header'

从文件夹中引入

需要现在文件夹里创建个index.js导出所有组件:

export { default as Layout } from './Layout/Index.vue'
// ...

然后才能引入

import { Layer } from '@components' // 意思为src/components/Layer/index.vue
import {
    Login,
    Home,
    ErrorPage
} from '@components'

按需/异步引入

使用场景:当一个页面加载的时候,时间过久(特别是首屏)。一般是两个原因,资源太大,接口拉取时间过久;页面中有较为复杂的组件,导致渲染过久。

当我们一个页面中引入的子组件很多时,打包的时候这个组件生成的文件也会很大

按需引入的原理

对于link标签的引入:

<link rel="preload" href="xxxx/sdk.js" />
<link rel="prefetch" href="xxxx/sdk.js" />
  • preload 是告诉浏览器页面必定需要的资源,浏览器一定会预先加载这些资源(如首页资源)
  • prefetch 是告诉浏览器下一个页面可能需要的资源,浏览器空闲的时候再加载这些资源(如路由组件资源、懒加载组件)存在缓存中,真正用到了再拿出来。

预加载

按需引入默认效果是prefetch方式,我称为预加载。先看看写法:

components: {
	fromPage: (resolve) => {
	 	  require(['@/views/fromPage/index.vue'], resolve)
	}
}

// 或者

components: {
    'from-page' : () => import (/*webpackChunkName: "fromPage" */ './components/fromPage') // 注释的地方是说明打包后生成的文件叫什么
}

// 在路由表中
{
	component: function() {
	return import(/* webpackChunkName: "fromPage" */' ../xxx/fromPage.vue'
}

为什么是这种写法,好像是jsonp的原理,以后有空细看下。

使用按需引入的方式后,该组件代码会单独打包,那默认的prefetch方式是什么行为呢?

例如当一个首屏页面,其中有a组件做了按需引入,我们可以通过浏览器的Network记录查看,他拉取首页的资源的同时,也开始要拉取a组件单独打包的资源(是一个预备的状态),但是要等首页拉取完毕后,空闲了才去真正拉取a组件。

如果是路由组件做了按需引入怎么理解,其实很好理解,我们最外层不是有个App.vue,这个就相当于路由组件的父组件,所以逻辑和上面说的一样。

原理:在运行的index.html文件中引入的link标签中打上标识rel="prefetch",其他正常引入的是preload

<link href="/js/fromPage.js" rel="prefetch"<link href="/js/xxx.js" rel="preload"...

懒加载

这是第二种方式,需要在vue.config.js中禁用默认的方式:

chainWebpack: config => config.plugins·delete('prefetch')

当然某个组件还想使用默认方式可以通过webpage注释:

{
	component: function() {
	return import(/* webpackChunkName: "fromPage" */ /*webpackPrefetch:true*/ '../xxx/fromPage.vue'
}

其中webpackPrefetch:true可以使用数字表示优先级。

使用这种script方式的效果是:当你用v-if渲染子组件或者浏览器浏览到的时候,才会去单独拉取该子组件的打包代码文件,可以通过浏览器的Network记录证实。

原理大概是需要加载资源的时候,创建一个script标签去拉取,其实就是下面说的JS触发按需引入。

优缺点

两种方式都有优缺点

预加载:

  • 不需要异步加载的内容能最快呈现给用户,切换到异步加载的内容时也能保证资源已经获取,切换效果快
  • 在拉取资源的时候,还是把所有资源都拉取过来了,如果用户不看异步加载的内容,就很浪费

script:

  • 第一次加载页面时,不拉取按需引入部分,速度最快
  • 但是当切换到按需引入部分时,就要实时去拉取资源,需要等待,会出现留白的情况

全局引入单个

main.js中

import components from '@/utils/components.js'
Vue.use(components)

全局引入文件夹内所有的

在放组件的文件夹中,新建个js文件把所有组件都导出:

// 这里统一把组件都导出,在main.js中引入
import Vue from 'vue'
import pgFrom from './pg-form'
import pgTable from './pg-table'

// 注意每个组件内部一定要有name属性,要不拿下面不到对象的
Vue.component(pgFrom.name, pgFrom)
Vue.component(pgTable.name, pgTable)

export { pgFrom, pgTable }

main.js中

import * as pgComponent from './components/business-components' // 导入全局组件(对象类型),这样写默认导入index.js
Object.values(pgComponent).forEach(i => { // 循环注册组件
    Vue.component(i.name, i)
})

更好的方法是直接用正则去匹配文件:

// 这里统一把组件都导出,在main.js中引入
import Vue from 'vue'

const components = require.context('./', true, /.vue$/)

components.keys().forEach(fileName => {
    const component = components(fileName)
    Vue.component(component.default.name, component.default)
})

main.js中

/* 引入公共组件 */
import '@/components/index.js' 

动态组件

例如有个场景,通过数组的数据去渲染对应的组件:

<template>
  <div>
    <div v-for="(item, index) in list" :key="index">
		<a v-if="item.type === 'a'"></a>
		<b v-else-if="item.type === 'b'"></b>
		<c v-else-if="item.type === 'c'"></c>
		....
	<div>
  </div>
</template>

代码太冗长了,借助动态组件可以解决:

<template>
  <div>
    <div v-for="(item, index) in list" :key="index">
		<component :is="item.type"></component>
	<div>
  </div>
</template>

第三方库或自封工具(JS引入)

按需引入

第三方库一般新版本都支持了按需引入,例如:

import { a, b } from '某某库'

如果是很老的库就实在无法这样写了,例如jQuery

如果是自己封的工具,可以参考【es6入门】模块化的写法export与import 。注意不要把整个对象引入再以obj.a的方式调用,这样打包会把整个obj都囊括了。

触发按需引入

例如某个库只有在触发某个函数的时候才使用

那老旧的库要怎么写呢?例如jQuery这种,默认导出整个对象的,可以这样写:

clickFn() {
	import('jquery').then(res=>{
		let $ = res.default
	})
}

新库可以这样写:

clickFn() {
	import('xlsx').then(res=>{
		let read = res.read
	})
}

这样子做虽然能让接口拉取组件资源的时候比较快(因为容量小了),但是每次触发的时候才会去拉取库中引入的需要的资源,会有个卡顿的过程。

所以最好在mounted这个钩子函数触发后去按需引入,可以定义全局的变量赋值上去。这样当组件挂载完后就去拉取库资源,体验会好很多。

mounted(){
	import(/*webpackPrefetch:2*/'jquery').then(res=>{ // 加载优先级为2,数字越大越优先
		$ = res.default
	})
	import(/*webpackPrefetch:1*/'xlsx').then(res=>{ // 加载优先级为1
		read = res.read
	})
}

你可能感兴趣的:(#,vue其他相关,vue.js,其他,javascript)