Vue中使用JSX練習(xí)
目標(biāo): 實(shí)現(xiàn)一個(gè)組件, 組件掛載到 APP.vue中, 在業(yè)務(wù)組件中可以向該組件傳遞dom, 并實(shí)現(xiàn)雙向綁定, 一般該組件應(yīng)該為一個(gè)輕量的模糊彈出層
App.vue
<template>
<div id="app">
<router-view />
<layer v-model="_layerData"></layer>
</div>
</template>
<script>
import layer from '@/components/layer.js'
import { mapState, mapMutations } from 'vuex'
export default {
name: 'app', // 組件名稱
components: { layer },
filters: { // 過濾器
},
computed: { // 計(jì)算屬性
...mapState(['layerData']),
_layerData: {
get () {
return this.layerData
},
set (val) {
this.setLayer(val)
}
}
},
watch: { // 監(jiān)聽屬性
},
data () {
return {
/*
* 頁面狀態(tài)
* */
/*
* 頁面數(shù)據(jù)
* */
}
},
methods: {
...mapMutations(['setLayer'])
},
beforeCreate () { // 播放加載動(dòng)畫
},
created () { // 結(jié)束加載動(dòng)畫, 發(fā)起異步請(qǐng)求
},
mounted () { // DOM構(gòu)建完成, 即將顯示頁面
},
updated () { // view重新渲染, 數(shù)據(jù)更新
},
beforeDestroy () { // 組件實(shí)例銷毀之前
}
}
</script>
<style>
#app {
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB",
"Microsoft YaHei", "微軟雅黑", Arial, sans-serif;
}
</style>
Store.js
import Vue from 'vue'
import Vuex from 'vuex'
import home from '@/store/modules/home'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
layerData: {}
},
mutations: {
setLayer (state, payload) {
if (payload !== '') {
state.layerData = { ...state.layerData, ...payload }
} else {
state.layerData = payload
}
}
},
actions: {
},
modules: {
home
}
})
Home.vue (業(yè)務(wù)組件)
<template>
<div class="home">
<button @click="setTimeoutClick">打開彈出框</button>
</div>
</template>
<script>
import { mapMutations } from 'vuex'
export default {
name: 'home', // 組件名稱
components: {},
props: [], // 組件參數(shù)
model: { // 用于 props 綁定父級(jí) v-model
},
filters: { // 過濾器
},
computed: { // 計(jì)算屬性
},
watch: { // 監(jiān)聽屬性
},
data () {
return {
/*
* 頁面狀態(tài)
* */
/*
* 頁面數(shù)據(jù)
* */
}
},
methods: {
...mapMutations(['setLayer']),
setTimeoutClick () {
this.handleClick()
setTimeout(() => {
this.handleClick()
}, 1000)
},
handleClick () {
new Promise((resolve, reject) => {
// 定義 內(nèi)容DOM (Vue-cli2寫法中, 沒有 v-model綁定, 需要自己實(shí)現(xiàn), vue-cli4可以直接使用 v-model)
const contentRender = function (h, context) {
return <div>
<div>標(biāo)題位置: {context.layerData._data.title}</div>
<input value={context._data.inputOne} onInput={(event) => { context.myVModel(event, 'inputOne') }} />
<br />
<input value={context._data.inputTwo} onInput={(event) => { context.myVModel(event, 'inputTwo') }} />
<br />
</div>
}
// 定義 底部DOM
const footerRender = function (h, context) {
return <div>
<button onClick={context.confirm}>確定</button>
<button onClick={context.cancel}>取消</button>
</div>
}
// 設(shè)置數(shù)據(jù)
this.setLayer({
contentRender,
footerRender,
_data: {
title: '我的標(biāo)題啊',
inputOne: '',
inputTwo: ''
},
resolve,
reject,
isShow: true
})
})
.then((data) => { console.log('then', data) })
.catch((data) => { console.log('catch', data) })
}
},
beforeCreate () { // 播放加載動(dòng)畫
},
created () { // 結(jié)束加載動(dòng)畫, 發(fā)起異步請(qǐng)求
},
mounted () { // DOM構(gòu)建完成, 即將顯示頁面
},
updated () { // view重新渲染, 數(shù)據(jù)更新
},
beforeDestroy () { // 組件實(shí)例銷毀之前
}
}
</script>
<style scoped lang="scss">
</style>
Layer.js (該組件)
export default {
name: 'layer', // 組件名稱
components: {},
props: ['layerData'], // 組件參數(shù)
model: { // 用于 props 綁定父級(jí) v-model
prop: 'layerData',
event: 'layer-data-callback'
},
filters: { // 過濾器
},
computed: { // 計(jì)算屬性
},
watch: { // 監(jiān)聽屬性
},
data () {
return {
_data: {} // 用于綁定 v-model
}
},
methods: {
myVModel (event, name) {
this._data[name] = event.target.value
},
isRunRender (renderFun, h, context) {
if (typeof renderFun === 'function') {
return renderFun(h, context)
} else {
return ''
}
},
confirm () {
this.layerData.resolve(this._data)
this.resetLayer()
},
cancel () {
this.layerData.reject()
this.resetLayer()
},
resetLayer () {
this.$emit('layer-data-callback', '')
this._data = {}
}
},
render (h) {
const context = this
const baseRender = function (h, context) {
if (context.layerData.isShow) {
return <div class="main">
<div class="content">
{ context.isRunRender(context.layerData.contentRender, h, context)}
</div>
<div class="footer">
{ context.isRunRender(context.layerData.footerRender, h, context)}
</div>
</div>
}
return ''
}
return baseRender(h, context)
},
beforeCreate () { // 播放加載動(dòng)畫
},
created () { // 結(jié)束加載動(dòng)畫, 發(fā)起異步請(qǐng)求
},
mounted () { // DOM構(gòu)建完成, 即將顯示頁面
},
updated () { // view重新渲染, 數(shù)據(jù)更新
},
beforeDestroy () { // 組件實(shí)例銷毀之前
}
}