Global API
在vue3 中,将全局改变vue行为的全局API移到由新的createApp方法创建的应用程序实例中,并且它们的影响现在仅限于该应用程序实例
vue2可以改变vue行为的全局API和全局配置
常见的全局API:Vue.component 、Vue.mixin 、Vue.extend、Vue.nextTick
常见的全局配置:Vue.config.silent 、Vue.config.devtools、Vue.config.productionTip
vue2中创建全局组件可以应用在任何vue实例上
<body> <div id="app"> <mycom></mycom> </div> <div id="app2"> <mycom></mycom> </div> <script> Vue.component('mycom',{ template:'<div>我是一个全局组件</div>' }) var vue=new Vue({ el:'#app' }) var vue2=new Vue({ el:'#app2' }) </script> </body>
vue2中创建全局指令
<body> <input type="text" v-focus> <script> Vue.directive('focus',{ inserted:el=>{ el.focus() } }) </script> </body>
此时就会自动获取焦点
像上面的方法都是挂载到Vue的构造函数上面,这样就会导致一些问题:
- vue2是没有app的概念,通过new Vue()得到的根实例作为app,这样的话所有创建的根实例是共享相同的全局配置,这在测试时会污染其他测试用例,导致测试变得困难
- 在单页面创建不同全局配置的多个app实例
比如:
<body>
<div id="app">
<mycom></mycom>
</div>
<div id="app2">
<mycom></mycom>
</div>
<input type="text" v-focus>
<script>
Vue.component('mycom',{
template:'<div>我是一个全局组件</div>'
})
Vue.directive('focus',{
insert:el=>{
el.focus()
}
})
Vue.mixin({
mounted:()=>{
console.log("vue.mixin")
}
})
var vue=new Vue({
el:'#app'
})
var vue2=new Vue({
el:'#app2'
})
</script>
</body>
如果app和app2它们想有不同的全局配置的话,就会出现问题,比如我们创建的mixin函数此时打开浏览器就会输出
它们现在只能拥有共同的全局配置,
vue3引入了应用程序实例 createApp可以很好的解决以上问题
createApp
调用createApp会返回一个应用程序实例,该应用程序实例提供了应用程序上下文,应用程序实例挂载的整个组件树共享相同的应用程序上下文,该上下文提供了先前在vue2中全局的配置
<body> <div id="app">{{name}}</div> <script> var {createApp} =Vue; //createApp返回应用程序实例 var app=createApp({ data(){ return { name:'createApp', } } }) //挂载到app节点 app.mount("#app") </script> </body>
应用实例暴露了 Vue 2 全局 API 的一个子集,经验法则是,任何全局改变 Vue 行为的 API 现在都会移动到应用实例上,以下是 Vue2 全局 API 及其相应的实例 API 列表:
2.x 全局 API | 3.x 实例 API (app ) |
---|---|
Vue.config | app.config |
Vue.config.productionTip | 移除 |
Vue.config.ignoredElements | app.config.compilerOptions.isCustomElement |
Vue.component | app.component |
Vue.directive | app.directive |
Vue.mixin | app.mixin |
Vue.use | app.use |
Vue.prototype | app.config.globalProperties |
Vue.extend | 移除 |
配置全局的属性
以axios为例
main.js中配置全局属性
import Axios from 'axios' import { createApp , } from 'vue' import App from './App.vue' const app=createApp(App) // 配置全局属性 app.config.globalProperties.$http=Axios app.mount('#app')
组件中使用全局配置属性
axios.vue
<script> import { getCurrentInstance, onMounted } from '@vue/runtime-core' export default { setup(props){ //在组件中使用全局配置的属性axios,要使用composition api提供的方法, //getCurrentInstance用来获取当前组件的实例,然后通过ctx获取当前的上下文 const{ctx}=getCurrentInstance() onMounted(()=>{ ctx.$http.get('http://jsonplaceholder.typicode.com/posts?userId=2') .then(res=>{ console.log(res.data) }) }) } } </script>
创建自定义组件
import { createApp , h} from 'vue' import App from './App.vue' const app=createApp(App) //创建自定义组件 app.component('my',{ render:()=>{ /** * h是createElement函数的别名 * createElement是一个函数,以组件实例为参数进行调用,生成Vnode节点 * render函数得到这个Vnode节点 之后,返回给Vue的mount函数,渲染成真实DOM节点,并挂载到根节点上 */ return h('div','全局自定义组件') } }) app.mount('#app')
在app.vue中引用
<template> <div> app <my></my> </div> </template>
也可以这样使用,我们定义一个组件muapi.vue,然后再mian.js中引入
import { createApp , h} from 'vue' import App from './App.vue' const app=createApp(App) import muapi from "./components/muapi.vue" //创建自定义组件 app.component('my',{ render:()=>{ /** * h是createElement函数的别名 * createElement是一个函数,以组件实例为参数进行调用,生成Vnode节点 * render函数得到这个Vnode节点 之后,返回给Vue的mount函数,渲染成真实DOM节点,并挂载到根节点上 */ // return h('div','全局自定义组件') return h(muapi) } }) app.mount('#app')
此时就会渲染该组件的内容
在应用之间共享配置
在应用之间共享配置的方法就是创建工厂函数
新建一个fun.vue文件
<template>
<div>
<input type="text" v-focus>
</div>
</template>
main.js文件
import { createApp , h} from 'vue' import App from './App.vue' import fun from "./components/fun.vue" const app=createApp(App) app.mount('#app') const createMy=options=>{ const app1 =createApp(options) app1.directive('focus',{ mounted:el=>el.focus() }) return app1 } //挂载到app.vue中的#fun上 createMy(fun).mount('#fun')
app.vue文件
<template>
<div>
app
<div id="fun"></div>
</div>
</template>
Global和内部API重构可做摇树优化
在vue2中不少global api是作为静态函数直接挂在到构造函数上的,比如Vue.nextTick(),如果从未在代码中用过它们,就会形成所谓的dead code ,这类global api造成的dead code,无法使用webpack的tree sharking排除掉
在vue3做了相应的变化,将他们抽取称为独立的函数,这样打包工具的摇树优化可以将这些dead code排除掉
不会改变vue行为的全局API,现在被成为Global API Treesharking
import {nextTick} from ‘vue’ nextTick(()=>{ })
受影响的api:
- Vue.nextTick()
- Vue.observable
- Vue.version
- Vue.compile
- Vue.set (非兼容)
- Vue.delete (非兼容)