安装环境:
vue2.0
cli小于5.0
核心功能:
- 组件渲染
- 工具类:rem单位转换/ 用户信息/跨源信息
- 动态组件加载page模块自定义组件
- cms和manager打通(重点)
跨原通信如何进行的,如何渲染的。
vue-router
- npm i vue-router@3.0.1
- 创建 vue.cofig.js
publicPath
devServer
module.exports = {
publicPath:'/crs/',
devServer: {
host:'127.0.0.1',
port:3001,
open:false
}
}
router下新建
3. index.js 配置路由信息routes
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
export default new Router({
routes: [
{
path:'/',
name:'page',
component: () => import('../pages/page.vue'),
meta: {
title:'配置页'
}
},
{
path:'/pagePreiview',
name:'pagePreiview',
component: () => import('../pages/pagePreiview.vue'),
meta: {
title:'预览页'
}
},
{
path:'/activity',
name:'activity',
component: () => import('../pages/activity.vue'),
meta: {
title:'活动页'
}
},
]
})
main.js
import router from '@/router'
router,
- src 新建pages,page.vue
<templata>
page页面
</templata>
- 新建pagePreiview.vue
<templata>
pagePreiview页面
</templata>
- npm i element-ui@2.15.1
main.js:引入ElementUI
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
// 全局注入
Vue.use(ElementUI)
- 引入vant-ui
npm install vant@2.12.10
import Vant from 'vant'
import 'vant/lib/index.css'
Vue.use(Vant)
- 引入 less
npm i less@4.1.1 less-loader@7.3.0
import less from 'less'
Vue.use(less)
- vuex的引入和axios的二次封装
pagePreiview.vue 详情预览页面
<templata>
<div class="wrap" id="wrap">
<div class="main" :style="pageStyle">
<div>
</templata>
<script>
// 调用接口,获取数据,存入store中
import {getH5PageJson } from '@/apis/preview'
computed: {
pageStyle() {
}
}
定义api: 定义项目的所有api
获取getH5PageJson的数据
preview 接口文档
import nodeFetch from '../utils/nodeFetch'
export async function getH5PageJson(params) {
const res = await nodeFetch.get('/getH5PageJson',{ params })
return res.data
}
定义axios
在utils下的nodeFetch.js,
直接拷贝cms
新建config index.js
module.exports = {
nodeUrl:'http:127.0.0.1:3300/atlas-cms'
}
npm install vuex@3.1.1
main.js
import store from '@/store'
store
新建store
index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
pageData: {
componentList: []
},
previewId:null,
previewHeight:0,
componentsTopList:[]
},
mutations: {},
actions:{},
})
组件渲染和图文广告组件
pagePreview.vue
<templata>
<div class="wrap" id="wrap">
<div class="main" :style="pageStyle">
<div v-for="element in pageData.componentList" :key="element.id">
<component :is="element.data.component" :property="element.data" :style="styleObject(element)" />
</templata>
<script>
import {getH5PageJson} from '@/apis/preview'
import Carousel from '@/components/Carousel'
data() {
return {
pageData: {}
}
}
mounted() {
const id = this.$route.query.id
getH5PageJson({id}).then(res => {
document.title = res.data.name
this.pageData = res.data
})
},
computed: {
pageStyle() {
return {
backgroundColor: this.pageData.backgroundColor,
backgroundImage:`url(${this.pageData.backgroundImage})`,
backgroundPosition:`center ${this.pageData.backgroundPosition}`
}
}
},
methods: {
styleObject(item) {
return {
color: item.textColor,
borderRadius:item.radius + 'px',
marginTop: item.marginTop + 'px'
}
}
}
Carousel
div class="carousel-box"
div v-if="property.layout === 'swiper'" :style = "boxStyle"
van-swiper class = "my-Carousel" :autoplay = "3000" indeicator-color="white"
van-swiper-item v-for="(item,i) in imageList" :key="i" :style="itemStyle" @click="jumpLink(item.link)"
van-image :style="imgStyle" :radius="radius" fit="fill" :src="item.imageUrl ? item.imageUrl : defaultImage"
div v-else = "single" :style="boxStyle"
div v-for="(item,i) in imageList" :key="i" :style="imageList.length - 1 ? iemStyle : ''" @click="jumpLink(item.link)
van-image :style="imgStyle" :radius="radius" :src="item.imageUrl ? item.imageUrl : defaultImage"
import defaultImage from '../assets/swipe-default.png'
props: {
property: {
type:Object,
default: () => {
return {}
}
}
},
data() {
return {
imageList:[] // 图片的列表字段
imgStyle: {},
boxStyle: {},
itemStyle: {},
radius:0,
defaultImage:defaultImage
}
},
watch: {
property: {
handler:function(val) {
if (val) {
this.imageList = this.property.imageList
this.setMyStyle()
}
}
}
},
methods: {
setMyStyle() {
let padding = '0',
let height = '100%',
this.radius = this.property.isBorderRadius ? this.property.radius : 0
if (this.property.isDefaultMargin) {
padding = `${this.property.marginSize[0]}px ${this.property.marginSize[1]}px` + ''
}
this.imgStyle = {
height,
verticalAlign:'top'
}
this.boxStyle = {
padding,
backgroundColor: this.property.backgroundColor
},
this.itemStyle = this.property.layout === 'swiper' ? { backgroundColor: this.property.backgroundColor}: {
backgroundColor: this.property.backgroundColor ,
marginBottom: (this.property.isDefaultMargin && this.property.imageMargin ? this.property.imageMargin : 0) + 'px'}
},
jumpLink() {}
}
vant ui,移动端的ui框架,微信小程序,vue2、vue3
vuedraggable拖拽插件,跨域通信
page.vue
<div id="wrap" class="wrap">
<draggable
v-model="pageData.componentList"
class="draggable"
group="people"
style="page"
:style="pageStyle"
@click ="changePosition"
/>
</div>
import draggable from 'vuedraggable'
components: {
draggable
},
computed: {
pageData: {
get:function() {
return this.$store.getters.pageData
},
set:function() {}
},
pageStyle() {
const s = {
backgroundColor:this.pageData.backgroundColor,
backgroundPosition:`center ${this.pageData.backgroundPosition}`
}
if (this.pageData.backgroundImage) {
s.backgroundImage = `url(${this.pageData.backgroundImage})`
}
return s
}
},
methods: {
// 组件变化时,返回当前位置的索引和上一个位置的索引
changePosition (e) {
let { newIndex,oldIndex,element } = e.moved
// 更新数据源,通知cms
this.$store.commit('changeComponentPosition',{newIndex,oldIndex,element})
}
}
npm install vuedraggable@2.24.3
store 下的index
import Postmessage from '@/utils/Postmessage '
getters: {
pageData:state => {
return state.pageData
}
}
mutations: {
changeComponentPosition() {
this.commit('postPageChange')
},
postPageChange(state) {
// 1. 跨原通信传递数据
Postmessage.postMessage('pageChange',state.pageData)
},
changeComponent(state,{value}) {
state.pageData = value
},
//预添加
setPreview(state,data) {
state.pageData.componentList = data
},
deletePreview(state) {
state.pageData.componentList = state.pageData.componentList.filter(item => item.data.component != "black")
},
setActiveId (state,id) {
state.previewId = id
}
}
utils 下Postmessage.js
import store from 'store'
// 对当前事件的监听,当前事件的触发
const Postmessage {
constructor() {
this.targetOrigin = process.env.NODE_ENV === 'production' ? window.location.origin:'http://127.0.0.1:3001'// 判断当前环境
this.postMessageType = {
pageHeightChange:'pageHeightChange',
pageChange:'pageChange',
setActive:'setActive'
}
}
postMessage(type,json) {
let message = {
type:this.postMessageType[type],
value:json
}
window.parent.postMessage(message,this.targetOrigin)
}
listenMessage () {
window.addEventListener('message', (event) => {
if (event.origin === this.targetOrigin ) {
switch (event.data.type) {
case 'pageChange':
store.commit('changeComponent',event.data.value)
break;
case 'setPreview':
store.commit('setPreview',event.data.value)
break;
case 'deletePreview':
store.commit('deletePreview',event.data.value)
break;
case 'setActiveId':
store.commit('setActiveId',event.data.value)
break;
}
}
},false)
}
}
export default new Postmessage()
渲染动态组件
page.vue
<div v-for="element in pageData.componentList" :key="element.id"
class="components">
<componentResolve v-if="element.data.component !== 'blank'" :component-config-prop="element"/>
<div v-else class="blankComponent">
<div class="preview-height-tag">
<span class="preview-height-tag-tex"/></div>
import componentResolve from '@/components/componentResolve '
src component 下componentResolve
<div style="position: relative">
div v-show="dialogShow" @click="sensorsTest" :class="[componentConfig.data.component === 'Dialog' ? (componentConfig.id === previewId ? 'componentDialog selected' : 'componentDialog '):'component']"
div @click="!preview ? changeSelectd()componentConfig.id : ''"
component
:is = "componentConfig.data.component"
:property="componentConfig.data"
:style="styleObject"
:class="{componentDom:true,selected:componentConfig.id === previewId}"
div v-if="!preview" class="modal" @click="preview ? changeSelected(componentConfig.id):''"
div v-if="!preview" class="name" :class="operateIagClass"
{{componentConfig.name}}
div v-if="!preview" class="delete" :class="operateTagClass" @click="deleteComponent(componentConfig.id)"
div v-show="componentConfig.data.component === 'Dialog'" class="hideDialog" @click="dialogSwitch"
{{dialogShow ? '隐藏弹窗':'显示弹窗'}}
import {mapState,mapMutations} from 'vuex'
name:'componentResolve '
props: {
componentConfigProp: {
type:Object,
default: () => {
return {}
}
},
preview: {
type:Boolean,
default:false
}
},
data() {
return{
dialogShow:true,
componentConfig:JSON.parse(JSON.stringify(this.componentConfigProp)),
styleObject: {}
}
},
mounted() {
this.styleObject = {
color: this.componentConfig.textColor,
borderRadius:this.componentConfig.radius + 'px',
marginTop:this.componentConfig.marginTop + 'px',
'--selected-width':this.componentConfig.data.component ==='OnlineService' ? '54px':(this.componentConfig.data.component === 'FloatLayer' ? '100px' : '375px')
}
}
watch: {
handler:function(value) {
this.componentConfig = value
},
deep:true
},
computed:{
...mapState(['previewId']),
operateIagClass() {
return this.componentConfig.data.component === 'OnlineService' ? 'online-service-pos':(this.componentConfig.data.component === 'FloatLayer' ? 'float-layer-pos':'')
}
},
methods: {
...mapMutations([
'changeSelected',
'deleteComponent'
]),
sensorsTest() {
},
dialogSwitch() {
this.dialogShow = !this.dialogShow
}
}
store,mutations
deleteComponent(state,id) {
const index = state.pageData.componentList.findIndex(item => item.id === id)
state.pageData.componentList.splice(index,1)
this.commit('postPageChange')
},
changeSelected(state,id) {
state.previewId = id
Postmessage.postMessage('setActive',id)
}
预添加组件和跨源事件注册
page下
import Postmessage from '@/utils/Postmessage'
mounted() {
Postmessage
}
微信sdk引入与小程序通信实现
web-view
src传入链接,全局铺满,页面在小程序显示
微信sdk引入,接收数据
npm i weixin-js-sdk@1.6.0
pagePreview.vue
const wx = require('weixin-js-sdk')
mounted() {
// 请求数据后
const { shareDesc,shareImage } = res.data
if (shareDesc || shareImage) {
const data = {
shareDesc,
shareImage
}
//miniProgram 微信通信api,微信内部拿到h5传递的消息
wx.miniProgram.postMessage(data)
}
}
打通链路
跨原通信postMessage,定义地址,通过messager调用,
cms写了地址127.0.0.1
setPreview (state,data) {
// 添加预组件位
this.commit('deletePreview')
const previewComponent = {
data: {
component:'blank'
}
}
state.pageData.componentList.splice(index,0,previewComponent)
}