Vue.js前端框架(三)

Vue.js前端框架(三)

  vue新版本解析,代号”one-piece“

其他组件

clipboard-polyfill xgplayer qrcode

vue-echarts

安装

1
npm install echarts vue-echarts

在vue2中使用还需要安装compostion包

1
npm i -D @vue/composition-api

如果在NuxtJS中使用还需要安装另外一个包

1
npm i -D @nuxtjs/composition-api

并且在nuxt.config.js中添加配置

1
@nuxtjs/composition-api/module

在vue3中使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import { createApp } from 'vue'
import ECharts from 'vue-echarts'
import { use } from "echarts/core"

// import ECharts modules manually to reduce bundle size
import {
CanvasRenderer
} from 'echarts/renderers'
import {
BarChart
} from 'echarts/charts'
import {
GridComponent,
TooltipComponent
} from 'echarts/components'

use([
CanvasRenderer,
BarChart,
GridComponent,
TooltipComponent
])

const app = createApp(...)

// register globally (or you can do it locally)
app.component('v-chart', ECharts)

app.mount(...)

在vue2中使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import Vue from 'vue'
import ECharts from 'vue-echarts'
import { use } from 'echarts/core'

// import ECharts modules manually to reduce bundle size
import {
CanvasRenderer
} from 'echarts/renderers'
import {
BarChart
} from 'echarts/charts'
import {
GridComponent,
TooltipComponent
} from 'echarts/components'

use([
CanvasRenderer,
BarChart,
GridComponent,
TooltipComponent
]);

// register globally (or you can do it locally)
Vue.component('v-chart', ECharts)

new Vue(...)

轮播图

安装包

1
npm install vue-awesome-swiper --save

引入

1
2
3
4
5
6
7
8
9
//全局引入
import VueAwesomeSwiper from 'vue-awesome-swiper'

import 'swiper/dist/css/swiper.css'
Vue.use(VueAwesomeSwiper)
//组件引入
import 'swiper/dist/css/swiper.css'

import {Swiper,swiperSlide} from 'vue-awesome-swiper'

修改swiper属性,自动播放与延时

1
2


验证码

https://www.npmjs.com/package/vue2-verify

多级菜单

递归组件实现

子组件,MenuItem 是一个 li 标签和 slot 插槽,允许往里头加入各种元素

1
2
3
4
5
6
// Menuitem
<template>
<li class="item">
<slot />
</li>
</template>

父组件Menu,Menu中有两种情况需要做判断,一种是 item 没有 children 属性,直接在 MenuItem 的插槽加入一个 span 元素渲染 item 的 title 即可;另一种是包含了 children 属性的 item 这种情况下,不仅需要渲染 title 还需要再次引入 Menu 做递归操作,将 item.children 作为路由传入到 router prop

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<!-- Menu -->

<template>
<ul class="wrapper">
<!-- 遍历 router 菜单数据 -->
<menuitem :key="index" v-for="(item, index) in router">
<!-- 对于没有 children 子菜单的 item -->
<span class="item-title" v-if="!item.children">{{item.name}}</span>

<!-- 对于有 children 子菜单的 item -->
<template v-else>
<span @click="handleToggleShow">{{item.name}}</span>
<!-- 递归操作 -->
<menu :router="item.children" v-if="toggleShow"></menu>
</template>
</menuitem>
</ul>
</template>

<script>
import MenuItem from "./MenuItem";

export default {
name: "Menu",
props: ["router"], // Menu 组件接受一个 router 作为菜单数据
components: { MenuItem },
data() {
return {
toggleShow: false // toggle 状态
};
},
methods: {
handleToggleShow() {
// 处理 toggle 状态的是否展开子菜单 handler
this.toggleShow = !this.toggleShow;
}
}
};
</script>

路由数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
[
{
name: "About",
path: "/about",
children: [
{
name: "About US",
path: "/about/us"
},
{
name: "About Comp",
path: "/about/company",
children: [
{
name: "About Comp A",
path: "/about/company/A",
children: [
{
name: "About Comp A 1",
path: "/about/company/A/1"
}
]
}
]
}
]
},
{
name: "Link",
path: "/link"
}
];

markdown编辑器

mavon-editor

1
npm install mavon-editor --save

在app.js引入

1
2
import mavonEditor from 'mavon-editor'
Vue.use(mavonEditor)

在页面引入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
<div>
<mavon-editor v-model='content'/>
</div>
</template>
<script>
export default{
data(){
return{
content:'',
}
},
}
</script>

直播

播放器使用的是 vue-video-player,其实就是 video.js 集成到 vue 中,后台主要输出 RTMP 和 HLS 的直播流

  1. 如果需要播放 HLS 流,需要安装 videojs-contrib-hls 插件,非原生支持的浏览器,直播服务端需要开启 CORS(后面会讲到)
  2. 如果需要播放 RTMP 流,需要安装 videojs-flash 插件
  3. 如果两个流都需要播放,flash 插件需要安装到 hls 插件之前

兼容性:

  1. RTMP: 上面说了 RTMP 是 Adobe 公司研发的协议,目前主要的直播服务都主推 RTMP 流,它延时小,但是需要 flash 插件的支持,也需要的上面提到的安装 videojs-flash 的插件。但是在 MAC 下对 flash 插件支持不友好,而且 MAC 下的 flash 插件 firefox 浏览器和 chrome 还是两个插件。。这就很尴尬。
  2. HLS: 这个协议兼容性较好,但是最大的缺点是延迟较高,大概 20s 左右,所以只能当做备选方案。

说 HLS 兼容性较好,主要是指可以通过 JS 让用户免配置(不必安装flash),可以在 caniuse 看下 HLS 的支持程度

最后我们使用的方案是。优先使用 RTMP 流,如果不支持,就切换到 HLS 流。好在这个切换过程 video.js 会自动替我们做。下面贴一下相关配置代码。

https://segmentfault.com/a/1190000011346597

循环播放插件

Vue-seamless-scroll

安装

1
npm install vue-seamless-scroll --save

在文件中引入

1
2
3
4
5
6
7
8
9
10
11
import vueSeamlessScroll from 'vue-seamless-scroll'

export default {
data(){
return {
components:{
vueSeamlessScroll
}
}
}
}

在页面中使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<template>
<vue-seamless-scroll :data="Array" :class-option="classOption">
<ul>
<li>

</li>
</ul>
</vue-seamless-scroll>
</template>
<script>
export default {
computed:{
classOption () {
return {
//上下滚动时父容器指定height和overflow:hidden,左右滚动时指定width
step:0.2 //数值越大,滚动速度越快
limitMoveNum: 2 //开始无缝滚动的数据量
hoverStop: true //是否开启鼠标悬停stop
direction: 0 //0向下,1向上,2向左,3向右
}
}
}
}
</script>

vue-auth

安装包

1
npm install @websnaova/vue-auth

vue-pdf

输出导入excel文件

使用sheetjs库

安装

1
npm install xlsx

输出打印

vue-print-nb

安装

1
npm install --save vue-print-nb

在main.js中全局引入

1
2
3
import Print from 'vue-print-nb'

Vue.use(Print)

通过id打印

1
2
3
4
5
6
7
8
<tr id="printInfo">

</tr>
<el-button
type = "primary"
key = "printInfo"
v-print = "'#printInfo'">
</el-button>

要打印的组件必须渲染出来,否则会报错。

地图

leafletjs

leaflet是一个对移动端优化的交互地图并且开源的JavaScript库,是一个十分轻量级的WebGIS库。

安装

1
npm install leaflet --save

引入

vue-amap

安装包

1
npm install -S vue-amap // 可在package.json查看是否安装

在入口文件main.js引入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 引入高德地图
// 高德地图组件使用
import VueAMap from 'vue-amap'

Vue.config.productionTip = false
Vue.use(VueAMap);
VueAMap.initAMapApiLoader({
key: 'your amap key',
plugin: [
'AMap.Autocomplete',
'AMap.PlaceSearch', // POI搜索插件
'AMap.Scale', // 右下角缩略图插件 比例尺
'AMap.OverView',
'AMap.ToolBar', // 地图工具条
'AMap.MapType',
'AMap.PolyEditor',
'AMap.CircleEditor',// 圆形编辑器插件
'AMap.Geolocation'// 定位控件,用来获取和展示用户主机所在的经纬度位置
],
// 默认高德 sdk 版本为 1.4.4
v: '1.4.4'
});

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<div class="getlocation">
定位
</div>
<el-amap vid="amap" :plugin="plugin" class="amap-demo" :center="center"> </el-amap>
<div class="toolbar">
<span v-if="loaded">location: lng = {{ lng }} lat = {{ lat }}</span>
<span v-else>正在定位</span>
</div>
<script>
export default {
data() {
let self = this;
return {
center: [121.59996, 31.197646],
lng: 0,
lat: 0,
loaded: false,
plugin: [
{
pName: "Geolocation", //定位
events: {
init(o) {
// o 是高德地图定位插件实例
o.getCurrentPosition((status, result) => {
if (result && result.position) {
console.log(status, result);
self.lng = result.position.lng; //设置经度
self.lat = result.position.lat; //设置维度
self.center = [self.lng, self.lat]; //设置中心坐标
self.loaded = true;
self.$nextTick();
}
});
}
}
}
]
};
},
</script>
<style>
.getlocation{
margin-left:4rem;
font-size:15px;
font-weight: 500;
margin-top:0.3rem;
}
.amap-demo {
height: 15rem;
margin-top: 0.3rem;
}
</style>

与vue2相比重大变化

全局变量

Vue 2.x 有许多全局 API 和配置,这些 API 和配置可以全局改变 Vue 的行为,比如说创建全局组件、声明全局指令。

虽然这种声明方式很方便,但它也会导致一些问题。从技术上讲,Vue 2 没有“app”的概念,我们定义的应用只是通过 new Vue() 创建的根 Vue 实例。从同一个 Vue 构造函数创建的每个根实例共享相同的全局配置

Vue3中新的api

createapp

调用 createApp 返回一个应用实例,进行挂载

1
2
3
4
5
import { createApp } from 'vue'
import MyApp from './MyApp.vue'

const app = createApp(MyApp)
app.mount('#app')

其他全局api变化

2.x 全局 API 3.x 实例 API (app)
Vue.config app.config
Vue.config.productionTip removed (见下方)
Vue.config.ignoredElements app.config.isCustomElement (见下方)
Vue.component app.component
Vue.directive app.directive
Vue.mixin app.mixin
Vue.use app.use (见下方)

利用这种方式,可以在应用之间共享全局组件和指令

1
2
3
4
5
6
7
8
9
10
11
12
13
import { createApp } from 'vue'
import Foo from './Foo.vue'
import Bar from './Bar.vue'

const createMyApp = options => {
const app = createApp(options)
app.directive('focus' /* ... */)

return app
}

createMyApp(Foo).mount('#foo')
createMyApp(Bar).mount('#bar')

上面代码中,createMyApp(Bar).mount(‘#bar’)Foo 和 Bar 实例及其后代中都可以使用 focus 指令

模版语法变化(Fragment片段)

在 2.x 中,不支持多根组件,当用户意外创建多根组件时会发出警告,因此,为了修复此错误,许多组件被包装在一个 <div> 中。

在 3.x 中,组件现在可以有多个根节点!但是,这确实要求开发者明确定义属性应该分布在哪里。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//vue2
<template>
<div>
<header>...</header>
<main>...</main>
<footer>...</footer>
</div>
</template>
//vue3
<template>
<header>...</header>
<main v-bind="$attrs">...</main>
<footer>...</footer>
</template>

生命周期函数变化

filter将不再被继续允许使用,鼓励使用computed或mothod替代filter功能

其他生命周期函数:

被弃用/替换:

  1. beforeCreate -> setup()
  2. created -> setup()

重命名的生命周期:

beforeMount -> onBeforeMount

mounted -> onMounted

beforeUpdate -> onBeforeUpdate

updated -> onUpdated

beforeDestroy -> onBeforeUnmount

destroyed -> onUnmounted

errorCaptured -> onErrorCaptured

组合式API/composition

组合式API是vue中类似于react hook类似的功能,尤雨溪在关于此部分功能的考虑和征求意见稿的全文如下

https://vue3js.cn/vue-composition/

简言之,vue在两种情况下不太友好:

1.随着功能的增长,复杂组件的代码变得越来越难以阅读和理解。这种情况在开发人员阅读他人编写的代码时尤为常见。根本原因是 Vue 现有的 API 迫使我们通过选项组织代码,但是有的时候通过逻辑关系组织代码更有意义。

目前vue缺少一种简洁且低成本的机制来提取和重用多个组件之间的逻辑。

2.来自大型项目开发者的常见需求是更好的 TypeScript 支持,不支持typescript意味着意味推断不够好。Vue 当前的 API 在集成 TypeScript 时遇到了不小的麻烦,其主要原因是 Vue 依靠一个简单的 this 上下文来暴露 property,我们现在使用 this 的方式是比较微妙的。

3.缺少一种比较「干净」的在多个组件之间提取和复用逻辑的机制。

Vue 现有的 API 在设计之初没有照顾到类型推导,这使适配 TypeScript 变得复杂。

composition核心函数:

1.setup函数

  • setup 就是将 Vue2.x 中的 beforeCreatecreated 代替了,以一个 setup 函数的形式,可以灵活组织代码了。
  • setup 还可以 return 数据或者 template,相当于把 datarender 也一并代替了!

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<template>
<div>{{ count }} {{ object.foo }}</div>
</template>

<script>
import { ref, reactive } from 'vue'

export default {
setup() {
const count = ref(0)
const object = reactive({ foo: 'bar' })

// expose to template
return {
count,
object
}
}
}
</script>

需要注意的是,setup函数中取消this,取消了 this,取而代之的是 setup 增加了2个参数:props,组件参数和context,上下文信息

2.Reactive方法:

reactive 方法包裹后的 对象 就变成了一个代理对象,相当于 Vue2.x 中的 Vue.observable()。也就可以实现页面和数据之间的双向绑定了。

这个包裹的方法是 deep 的, vue3.md 对所有嵌套的属性都生效。

3.ref方法

ref 方法包裹后的 元素 就变成了一个代理对象。一般而言,这里的元素参数指 基本元素 或者称之为 inner value,如:number, string, boolean,null,undefined 等,object 一般不使用 ref,而是使用上文的 reactive

也就是说 ref 一般适用于某个元素的;而 reactive 适用于一个对象。

4.isRef方法

判断一个对象是否 ref 代理对象。

1
const unwrapped = isRef(foo) ? foo.value : foo

5.toRefs 方法

将一个 reactive 代理对象打平,转换为 ref 代理对象,使得对象的属性可以直接在 template 上使用。

6.computed函数

与 Vue2.x 中的作用类似,获取一个计算结果。当然功能有所增强,不仅支持取值 get(默认),还支持赋值 set

结果是一个 ref 代理对象,js中取值需要 .value

当 computed 参数使用 object 对象书写时,使用 get 和 set 属性。set 属性可以将这个对象编程一个可写的对象。

也就是说 computed 不仅可以获取一个计算结果,它还可以反过来处理 ref 或者 reactive 对象

7.readonly函数

使用 readonly 函数,可以把 普通 object 对象reactive 对象ref 对象 返回一个只读对象。

返回的 readonly 对象,一旦修改就会在 console 有 warning 警告。程序还是会照常运行,不会报错。

8.watch函数

watch 函数用来侦听特定的数据源,并在回调函数中执行副作用。默认情况是惰性的,也就是说仅在侦听的源数据变更时才执行回调。

监听不同的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
//侦听reactive的数据
import { defineComponent, ref, reactive, toRefs, watch } from "vue";
export default defineComponent({
setup() {
const state = reactive({ nickname: "xiaofan", age: 20 });

setTimeout(() => {
state.age++;
}, 1000);

// 修改age值时会触发 watch的回调
watch(
() => state.age,
(curAge, preAge) => {
console.log("新值:", curAge, "老值:", preAge);
}
);

return {
...toRefs(state),
};
},
});

//侦听ref定义的数据
const year = ref(0);

setTimeout(() => {
year.value++;
}, 1000);

watch(year, (newVal, oldVal) => {
console.log("新值:", newVal, "老值:", oldVal);
});


//侦听多个数据时进行合并监听
watch([() => state.age, year], ([curAge, newVal], [preAge, oldVal]) => {
console.log("新值:", curAge, "老值:", preAge); console.log("新值:", newVal,
"老值:", oldVal); });

//侦听复杂数据
const state = reactive({
room: {
id: 100,
attrs: {
size: "140平方米",
type: "三室两厅",
},
},
});
watch(
() => state.room,
(newType, oldType) => {
console.log("新值:", newType, "老值:", oldType);
},
{ deep: true }
);

停止监听

1
2
3
4
5
6
7
8
const stopWatchRoom = watch(() => state.room, (newType, oldType) => {
console.log("新值:", newType, "老值:", oldType);
}, {deep:true});

setTimeout(()=>{
// 停止监听
stopWatchRoom()
}, 3000)

9.watcheffect函数

watcheffect与watch的区别:

  1. watchEffect 不需要手动传入依赖
  2. watchEffect 会先执行一次用来自动收集依赖
  3. watchEffect 无法获取到变化前的值, 只能获取变化后的值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { reactive, watchEffect } from 'vue'

const state = reactive({
count: 0,
})

function increment() {
state.count++
}

const renderContext = {
state,
increment,
}

watchEffect(() => {
// 假设的方法,并不是真实的 API
renderTemplate(
`<button @click="increment">{{ state.count }}</button>`,
renderContext
)
})

自定义hook

约定这些「自定义 Hook」以 use 作为前缀,和普通的函数加以区分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import { ref, Ref, computed } from "vue";

type CountResultProps = {
count: Ref<number>;
multiple: Ref<number>;
increase: (delta?: number) => void;
decrease: (delta?: number) => void;
};

export default function useCount(initValue = 1): CountResultProps {
const count = ref(initValue);

const increase = (delta?: number): void => {
if (typeof delta !== "undefined") {
count.value += delta;
} else {
count.value += 1;
}
};
const multiple = computed(() => count.value * 2);

const decrease = (delta?: number): void => {
if (typeof delta !== "undefined") {
count.value -= delta;
} else {
count.value -= 1;
}
};

return {
count,
multiple,
increase,
decrease,
};
}

使用useCount这个hook

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
<p>count: {{ count }}</p>
<p>倍数: {{ multiple }}</p>
<div>
<button @click="increase()">加1</button>
<button @click="decrease()">减一</button>
</div>
</template>

<script lang="ts">
import useCount from "../hooks/useCount";
setup() {
const { count, multiple, increase, decrease } = useCount(10);
return {
count,
multiple,
increase,
decrease,
};
},
</script>

Vue2.x 实现,分散在data,method,computed等, 如果刚接手项目,实在无法快速将data字段和method关联起来,而 Vue3 的方式可以很明确的看出,将 count 相关的逻辑聚合在一起, 看起来舒服多了, 而且useCount还可以扩展更多的功能。 项目开发完之后,后续还会写一篇总结项目中使用到的「自定义 Hooks 的文章」,帮助大家更高效的开发,

teleport

在子组件Header中使用到Dialog组件,我们实际开发中经常会在类似的情形下使用到 Dialog ,此时Dialog就被渲染到一层层子组件内部,处理嵌套组件的定位、z-index和样式都变得困难。 Dialog从用户感知的层面,应该是一个独立的组件,从 dom 结构应该完全剥离 Vue 顶层组件挂载的 DOM;同时还可以使用到 Vue 组件内的状态(data或者props)的值。简单来说就是,即希望继续在组件内部使用Dialog, 又希望渲染的 DOM 结构不嵌套在组件的 DOM 中。 此时就需要 Teleport 上场,我们可以用<Teleport>包裹Dialog, 此时就建立了一个传送门,可以将Dialog渲染的内容传送到任何指定的地方。

Suspense

在前后端交互获取数据时, 是一个异步过程,一般我们都会提供一个加载中的动画,当数据返回时配合v-if来控制数据显示。 如果你使用过vue-async-manager这个插件来完成上面的需求, 你对Suspense可能不会陌生

Vue3.x 新出的内置组件Suspense, 它提供两个template slot, 刚开始会渲染一个 fallback 状态下的内容, 直到到达某个条件后才会渲染 default 状态的正式内容, 通过使用Suspense组件进行展示异步渲染就更加的简单。:::warning 如果使用 Suspense, 要返回一个 promise :::Suspense 组件的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  <Suspense>
<template #default>
<async-component></async-component>
</template>
<template #fallback>
<div>
Loading...
</div>
</template>
</Suspense>

<<template>
<div>
<h4>这个是一个异步加载数据</h4>
<p>用户名:{{user.nickname}}</p>
<p>年龄:{{user.age}}</p>
</div>
</template>

<script>
import { defineComponent } from "vue"
import axios from "axios"
export default defineComponent({
setup(){
const rawData = await axios.get("http://xxx.xinp.cn/user")
return {
user: rawData.data
}
}
})
</script>

slot变化

vue2中使用slot插槽

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- 父组件中使用 -->
<template slot="content" slot-scope="scoped">
<div v-for="item in scoped.data">{{item}}</div>
<template>

// 子组件
<slot name="content" :data="data"></slot>
export default {
data(){
return{
data:["走过来人来人往","不喜欢也得欣赏","陪伴是最长情的告白"]
}
}
}

Vue3将slotslot-scope进行了合并同意使用。 Vue3.0 中v-slot

1
2
3
4
5
6
7
8
9
<!-- 父组件中使用 -->
<template v-slot:content="scoped">
<div v-for="item in scoped.data">{{item}}</div>
</template>

<!-- 也可以简写成: -->
<template #content="{data}">
<div v-for="item in data">{{item}}</div>
</template>

异步组件

Vue3 中 使用 defineAsyncComponent 定义异步组件,配置选项 component 替换为 loader ,Loader 函数本身不再接收 resolve 和 reject 参数,且必须返回一个 Promise,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<template>
<!-- 异步组件的使用 -->
<AsyncPage />
</tempate>

<script>
import { defineAsyncComponent } from "vue";

export default {
components: {
// 无配置项异步组件
AsyncPage: defineAsyncComponent(() => import("./NextPage.vue")),

// 有配置项异步组件
AsyncPageWithOptions: defineAsyncComponent({
loader: () => import(".NextPage.vue"),
delay: 200,
timeout: 3000,
errorComponent: () => import("./ErrorComponent.vue"),
loadingComponent: () => import("./LoadingComponent.vue"),
})
},
}
</script>

tree-shaking

Vue3.x 在考虑到 tree-shaking的基础上重构了全局和内部 API, 表现结果就是现在的全局 API 需要通过 ES Module的引用方式进行具名引用

如vue中使用nextTick()

1
2
3
4
5
6
7
8
9
10
11
12
// vue2.x
import Vue from "vue"

Vue.nextTick(()=>{
...
})

import { nextTick } from "vue"

nextTick(() =>{
...
})

类似的api变化

  • Vue.nextTick
  • Vue.observable(用 Vue.reactive 替换)
  • Vue.version
  • Vue.compile(仅限完整版本时可用)
  • Vue.set(仅在 2.x 兼容版本中可用)
  • Vue.delete(与上同)

Element-plus

评论

You forgot to set the app_id or app_key for Valine. Please set it in _config.yml.

 

本文章阅读量:

  0

IT学徒、技术民工、斜杠青年

机器人爱好者、摄影爱好者

PS、PR、LR、达芬奇潜在学习者

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×