- 全域注冊組件
- 區域注冊組件
- 單檔案組件
- 使用x-template引入模板
- jsx注冊組件(后續補充)
- 方法呼叫式創建(render函式注冊組件)
- 注冊全域插件
全域注冊組件
Vue.component('my-component-name', {
// ... 選項 ...
})
我們可以用這種方式來創建全域組件,在實體化Vue之前用Vue.component來創建組件,這樣我們可以在任何實體化Vue的組件(new Vue)中使用,
可能會報錯:
[Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.
處理方法:在專案vue.config.js中,修改runtimeCompiler為true
區域注冊組件
我們可以以普通物件的方式創建組件,物件中可以包含我們常用的data、methods等屬性和方法,比如下面這樣
var ComponentA = { /* ... */ }
注冊區域組件的話,需要我們在要使用組件的地方(大多數情況下也是組件)使用components來注冊
單檔案組件
Demo.vue
<template>
<div>Demo</div>
</template>
首先匯入組件,然后使用components注冊組件,最后在template中使用組件
<template>
<demo></demo>
</template>
<script>
import Demo from './Demo';
export default {
......
components: {
Demo,
}
}
</script>
使用x-template引入模板
<script type="text/x-template" id="xTemplate">
<div>content</div>
</script>
<script>
Vue.component('xTemplateDemo', {
template: '#xTemplate',
......
});
</script>
jsx注冊組件(后續補充)
方法呼叫式創建(render函式注冊組件)
使用過像elementUI和iview之類的第三方組件庫的同學可能都知道,他們提供了很多全域的API可以很方便的創建組件,比如彈出框等,他們是怎么做的呢,我們下面就來看看,
// components/Dialog/Dialog.vue
<template>
<transition name="fade">
<div class="dialog-page" @click.self="close" v-if="isShow">
<div class="dialog-box">
<h3 class="title">{{ title }}</h3>
<span class="close" @click="close">X</span>
<el-button type="primary" class="confirm-btn" @click="confirm">確定</el-button>
</div>
</div>
</transition>
</template>
<script>
export default {
name: "Dialog",
props: {
title: {
type: String,
default: '提示',
}
},
data() {
return {
isShow: false
}
},
mounted() {
window.addEventListener('keyup', this.close)
this.isShow = true;
},
methods: {
close() {
this.isShow = false;
// 這里使用$nextTick是因為我們使用了過渡效果,關閉的時候先過渡,再銷毀
this.$nextTick(() => {
this.$emit('close')
})
},
confirm() {
this.$emit('confirm')
}
}
}
</script>
<style lang="scss" scoped>
.dialog-page {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, 0.6);
z-index: 99999;
.dialog-box {
position: absolute;
top: 20%;
left: 50%;
transform: translateX(-50%);
margin: auto;
width: 700px;
height: 400px;
padding-top: 20px;
background-color: #fff;
border-radius: 10px;
box-shadow: 0 0 6px 0 #fff;
.title {
text-align: center;
font-size: 22px;
color: #333;
}
.close {
position: absolute;
right: 20px;
top: 20px;
cursor: pointer;
}
.confirm-btn {
width: 80%;
position: absolute;
left: 10%;
bottom: 50px;
}
}
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.2s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
opacity: 0;
}
</style>
新建檔案
// components/Dialog/index.js
import Vue from 'vue';
import Dialog from "@/components/Dialog/Dialog";
let vm;
function createVNode(resolve, reject, props) {
return new Vue({
mixins: [{
mounted() {
document.body.appendChild(this.$el);
},
beforeDestroy() {
document.body.removeChild(this.$el);
},
}],
beforeDestroy() {
vm = null;
},
methods: {
confirm() {
resolve('點擊確認');
this.$destroy();
},
close() {
reject('點擊關閉');
this.$destroy();
}
},
render(createElement) {
return createElement(Dialog, {
on: {
confirm: this.confirm,
close: this.close
},
props,
style: {
color: 'red'
},
});
}
})
}
function show(props) {
return new Promise((resolve, reject) => {
// 如果有vm這個實體,先銷毀
if (vm) {
vm.$destroy();
}
vm = createVNode(resolve, reject, props);
vm.$mount();
})
}
export default show;
倒著看,我們匯出了一個show方法,它回傳的是一個Promise,這就是說我們在呼叫這個方法的時候可以用.then的語法在未來某一個時刻(關閉彈框,或者點擊確認)執行一些操作,
接著我們創建了一個vm實體,呼叫了$mount,是不是看著比較熟悉,沒錯,在main.js檔案中
// main.js
...
new Vue({
...
render: h => h(App),
}).$mount('#app');
它把new vue生成的虛擬DOM轉換成真實DOM掛載到了#app上面,那上面我們的$mount沒有傳引數,會掛載到哪里呢?
其實是需要我們手動掛載的,當前組件在渲染完成后,手動把當前組件的DOM插入到body中,在組件銷毀前移除掉,
接著說我們的組件,這里我們又看到一個createVNode方法,不用說,這個就是用來創建組件的方法了,可以看到它回傳了一個Vue的實體化物件(虛擬DOM),new Vue的引數混入了一些生命周期函式,和兩個methods方法,以及上段所說掛載dom與銷毀dom,
最重要的還是下面的render函式,這個內容很多,就不展開說了,想深入了解可以單擊傳送門,可以簡單理解render可以生成VNode,就是虛擬節點,它的第一個引數是剛才我們撰寫的組件,第二個引數是一個物件,可以定義一些引數,比如要傳給組件的引數、樣式還有監聽的事件等,
這樣我們new Vue的時候,沒有用template的方式,而是用了render函式來生成我們要的組件,手動掛載到DOM中去(不在#app里面,是并列的關系,都在body下面),
接下來我們就可以在需要的地方呼叫了,比如App.vue
// App.vue
<template>
<div id="app">
<button @click="handleClick">Dialog</button>
</div>
</template>
<script>
import Dialog from '@/components/Dialog/index'
export default {
name: 'app',
methods: {
handleClick() {
Dialog({
title: '測驗彈框'
}).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
}
}
}
</script>
點擊按鈕的時候,我們呼叫匯入的Dialog方法,傳了title引數,現在我們可以看看效果,
到現在我們已經完成了組件的創建和呼叫,而且我們點擊關閉和確認的時候可以看看控制臺,是不是分別列印了

這就是我們在App.vue里面呼叫Dialog方法的時候分別在then和catch里面列印的,回到上面/components/Dialog/index.js檔案中的show方法,我們回傳的是promise,而且我們把resolve和reject兩個引數傳入了createVNode方法中,分別在methods中的兩個對應確認和關閉的方法中別呼叫,那么confirm和close是怎么被觸發的呢
可以看/components/Dialog/Dialog.vue檔案中,我們在點擊的時候,使用了$emit來觸發對應的事件,那么事件是在哪里被接收的呢?回到/components/Dialog/index.js檔案中的render函式,我們在createElement方法的第二個引數中有一個on物件,是不是感覺很熟悉,沒錯,就是用來監聽事件的,我們上面用$emit觸發的事件也是在這里監聽的,這樣我們就在點擊確認或者關閉后,執行resolve或者reject方法,然后就可以在then和catch中執行相應的操作了,
注冊全域插件
到上面為止,我們已經可以很方便的以API的形式來創建組件,但是可能有人會覺得還不夠方便,每次還要先匯入,再呼叫,有沒有更方便的方式呢?肯定是有的,現在我們就來試試,
其實也很簡單,只需要把剛才的代碼稍微改一下就可以了
// /component/Dialog/index.js
...
- export default show;
+ export default {
+ install(vue) {
+ vue.prototype.$Dialog = show;
+ }
+ }
// main.js
+ import Dialog from '@/components/Dialog/index'
+ Vue.use(Dialog);
看到Vue.use又有了熟悉的感覺吧,我們平常使用插件不就是這么用的嘛!沒錯,第三方的插件能夠以Vue.use的方式注冊,是因為他們都在插件里面匯出了一個install方法,不清楚的看這里哦 Vue.use,
這樣我們就可以在需要的地方使用this.$Dialog呼叫了,也不需要先匯入了,因為方法已經被掛到了Vue的原型上,
現在就來試一下
// App.vue
<template>
<div id="app">
<button @click="handleClick">Dialog</button>
</div>
</template>
<script>
export default {
name: 'app',
methods: {
handleClick() {
this.$Dialog({
title: '測驗彈框'
}).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
}
}
}
</script>
效果和剛才是一樣的,ok,到這里是不是覺得和ElementUI提供的一些方法有點相似呢,沒錯,其實他們也是這么做的,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/254964.html
標籤:其他
上一篇:使用Js制作一個簡單的省市聯動
