项目crs

安装环境:
vue2.0
cli小于5.0

核心功能:

  1. 组件渲染
  2. 工具类:rem单位转换/ 用户信息/跨源信息
  3. 动态组件加载page模块自定义组件
  4. cms和manager打通(重点)
    跨原通信如何进行的,如何渲染的。

vue-router

  1. npm i vue-router@3.0.1
  2. 创建 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,
  1. src 新建pages,page.vue
<templata>
page页面
</templata>
  1. 新建pagePreiview.vue
<templata>
pagePreiview页面
</templata>
  1. 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)
  1. 引入vant-ui
    npm install vant@2.12.10
import Vant from 'vant'
import 'vant/lib/index.css'
Vue.use(Vant)
  1. 引入 less
    npm i less@4.1.1 less-loader@7.3.0
import less from 'less'
Vue.use(less)
  1. 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)
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值