1.Vue.extend(options)
- 參數(shù):
{Object} options - 用法:
使用基礎(chǔ)Vue構(gòu)造器,創(chuàng)建一個(gè)"子類"。參數(shù)是一個(gè)包含組件選項(xiàng)的對(duì)象。
data選項(xiàng)是特例,需要注意,在Vue.extend()中它必須是函數(shù)。
<html>
<head>
<title>Vue.extend 用法</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="mount-point"></div>
<script>
// 創(chuàng)建構(gòu)造器
var Profile = Vue.extend({
template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
data: function () {
return {
firstName: 'Walter',
lastName: 'White',
alias: 'Heisenberg'
}
}
})
// 創(chuàng)建 Profile 實(shí)例,并掛載到一個(gè)元素上。
new Profile().$mount('#mount-point')
</script>
</body>
</html>
結(jié)果顯示如下:

image.png
可以看到,extend 創(chuàng)建的是 Vue 構(gòu)造器,而不是我們平時(shí)常寫(xiě)的組件實(shí)例,所以不可以通過(guò) new Vue({ components: testExtend }) 來(lái)直接使用,需要通過(guò) new Profile().$mount('#mount-point') 來(lái)掛載到指定的元素上。
我個(gè)人的理解來(lái)看,extend提供了一個(gè)能夠構(gòu)造組件的函數(shù)(也就是構(gòu)造器)。在一些特定的應(yīng)用場(chǎng)景(如自己構(gòu)建一個(gè)復(fù)雜彈窗)下,我們使用這種函數(shù)式的構(gòu)造組件的方法,會(huì)更靈活一些。
2.Vue.extend實(shí)現(xiàn)加載效果
<html>
<head>
<title>Vue.extend 用法2</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
#loading-wrapper {
position: fixed;
top: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
background: rgba(0,0,0,.7);
color: #fff;
}
</style>
</head>
<body>
<div id="root">
<button @click="showLoading">顯示Loading</button>
</div>
<script>
function Loading(msg) {
const LoadingComponent = Vue.extend({
template: '<div id="loading-wrapper">{{msg}}</div>',
props: {
msg: {
type: String,
default: msg
}
},
name: 'LoadingComponent'
})
const div = document.createElement('div')
div.setAttribute('id', 'loading-wrapper')
document.body.append(div)
new LoadingComponent().$mount('#loading-wrapper')
return () => {
document.body.removeChild(document.getElementById('loading-wrapper'))
}
}
Vue.prototype.$loading = Loading
new Vue({
el: '#root',
methods: {
showLoading() {
const hide = this.$loading('正在加載,請(qǐng)稍等...')
setTimeout(() => {
hide()
}, 2000)
}
}
})
</script>
</body>
</html>
3.Vue.extend()實(shí)現(xiàn)MessageBox彈窗
(1)新建一個(gè)messageBox.vue
<template>
<div id="confirm" v-if='flag'>
<div class="contents" >
<div class="content-top">{{text.title}}</div>
<div class="content-center">{{text.msg}}</div>
<div class="content-bottom">
<button type='primary' @click='ok' class="left">{{text.btn.ok}}</button>
<button type='info' @click='no' class="right">{{text.btn.no}}</button>
</div>
</div>
</div>
</template>
<script>
export default {
data () {
return {
flag:true,
text:{
title:'標(biāo)題',
msg:'這是一個(gè)彈出框組件',
btn:{
ok:'確定',
no:'取消'
}
}
}
},
methods: {
ok(){
this.flag=false;
},
no(){
this.flag=false;
}
}
}
</script>
<style scoped>
#confirm{
position:fixed;
left:0;
top:0;
right:0;
bottom:0;
background:rgba(0,0,0,0.3);
}
.contents{
width:250px;
height:180px;
border:1px solid #ccc;
border-radius:10px;
background-color:#fff;
position:fixed;
top:50%;
left:50%;
margin-top:-90px;
margin-left:-125px;
}
.content-top{
width:100%;
height:40px;
border-bottom:1px solid #ccc;
text-align: center;
font-size:20px;
font-weight: 700;
line-height:40px;
}
.content-center{
width:90%;
height:80px;
margin:5px auto;
}
.content-bottom{
width:85%;
height:40px;
margin:0 auto;
/* border:1px solid red; */
position:relative;
}
.left{
position:absolute;
left:0;
width:40%;
}
.right{
position:absolute;
right:0;
width:40%;
}
</style>
(2) 新建messageBox.js
import Vue from 'vue'
import Confirm from './MessageBox.vue'
let confirmStructor=Vue.extend(Confirm) //返回一個(gè)實(shí)例創(chuàng)建的構(gòu)造器,但實(shí)例構(gòu)造器需要進(jìn)行掛載到頁(yè)面中
let theConfirm=function(text){
return new Promise((res,rej)=>{ //返回一個(gè)promise,進(jìn)行異步操作,成功時(shí)返回,失敗時(shí)返回
let confirmDom=new confirmStructor({
el:document.createElement('div')
})
//在body中動(dòng)態(tài)創(chuàng)建一個(gè)div元素,之后此div將會(huì)替換成整個(gè)vue文件的內(nèi)容
//此時(shí)的confirmDom通俗講就是相當(dāng)于是整個(gè)組件對(duì)象,通過(guò)對(duì)象調(diào)用屬性的方法來(lái)進(jìn)行組件中數(shù)據(jù)的使用
//可以通過(guò)$el屬性來(lái)訪問(wèn)創(chuàng)建的組件實(shí)例
document.body.appendChild(confirmDom.$el)
//此時(shí)進(jìn)行創(chuàng)建組件的邏輯處理
confirmDom.text=text //將需要傳入的文本內(nèi)容傳給組件實(shí)例
confirmDom.ok=()=>{ //箭頭函數(shù),在()和{}之間增加=>,且去掉function
res() //正確時(shí)返回的操作
confirmDom.flag=false;
}
confirmDom.no=()=>{
rej() //失敗時(shí)返回的操作
confirmDom.flag=false;
}
})
}
//將邏輯函數(shù)進(jìn)行導(dǎo)出和暴露
export default theConfirm
(3)mian.js引入掛載到全局
import Vue from 'vue';
import store from './store/index'
import App from './App.vue';
import router from './router';
import theConfirm from './components/messageBox.js'
Vue.config.productionTip = false;
Vue.prototype.$Myconfirm=theConfirm
new Vue({
router,
store,
render: h => h(App),
}).$mount('#app')
(4)頁(yè)面使用
this.$Myconfirm({
title:'標(biāo)題',
msg:'內(nèi)容',
btn:{ ok:'確定', no:'取消'}
}).then(()=>{
console.log('ok')
}).catch(()=>{
console.log('no')
})
(5)效果如下:

image.png