Writing in the front
I have been using Jquery+ jquery-UI to do this project. At that time, there was no design draft and no project requirements. Just because the BOSS said that he wanted to do something like this, at that time… All right! I admit, in fact, has been used to it, doesn’t matter (is helpless, ah)!! In the following period of time, I made a demo, and BOSS was very satisfied with it, so I started to do it slowly, for about two or three months. Then the project was launched, but of course there were some problems due to the imperfect product. But it basically meets the needs of the company, you can edit whatever you want, Component background(including background image) color border box-shadow margin padding width height Alignment (font and component internal elements) border-radius Font (font-size/font-family), etc. These basic can be arbitrarily changed, of course, considering that may not meet the use of the company, we added a custom style function, and this only understand the front end of the people can use, no way, demand will never catch up with the change, so a little insurance. Because we all know, the satisfaction of needs and change always run in the front of the existing demand In addition to these fundamental changes, specific can change the function of each component is basically complete, such as round figure image changes, shuffling, whether control wheel and so on these functions, not introduced including the later one, because there are components within individual elements cannot be modified, Added binding to modify functions, it is for this function is selected, in view of the interface, need to modify the selected elements, can be modified, this feature is a little mean to say so many, in fact at that time because do hasty, storage time remaining is HTML, everybody don’t despise YaoLian (0.0), this is my in the mind have been terrier, Recently, BOSS put forward some new ideas, and there are a lot of things to add. After thinking about it, I decided to reconstruct the project. Considering the vUE responsiveness and pure data operation, I decided to reconstruct the project using VUE.
The development of preparation
Vuedraggable and SorTableJS are used because dragging and dropping components are involved in the process.
Install vuedraggable sortablejs
npm install vuedraggable
npm install sortablejs
Copy the code
We only need to introduce vuedraggable in the project. When sorTableJS is involved, Vuedraggable will load and call the method in SorTableJS by itself, which is not what we need to pay attention to (if you want to know, you can have a look by yourself). 3, install VUEX, because it involves a lot of data interaction, many components need some common data, do not use VUex to manage, will bring more unnecessary trouble for development;
Install vuex
npm install --save vuex
Copy the code
4. Use the third-party UI library, Element-UI, because there is no design draft; The official address of element-UI
Install elememt
NPM install elder-ui // Why elder-ui instead of element? There was already an Element package on NPM (I thought it was funny, 0.0 is so cold!!).Copy the code
5. Axios installation, which will be used for background data interaction
Install axios
npm install --save axios
Copy the code
That’s about all the preparatory work, then we’ll look at the implementation of the project;
Project start
1. Configuration of various files
-> file configuration in main.js
-> Sidebar drag configuration of component data
Among components, there is a layout problem, so have layout components, so that components can be placed in the layout of the component, so that more flexible
-> Js configuration in vuexJS state management
Note: 1, because the user after dragging and dropping to real-time storage in sessionStorage, so the initial time to get data in sessionStroage, to prevent the sudden refresh of the page, has not been saved to the database, the user just edited data all lost; 2, here to explain, may consider used to have submitted data, so after the user closed the window, when coming in again, to combine the background given user’s previous data, store together in the sessionStorage, I believe this point we must want to, here kindly remind 0.0; 3. I temporarily put four parameters here, which are all explained in the picture. I mainly made the basic editing into a component. 4, The role of the editShow is to control the display of the edit component, mainly delete the component, let the edit component hide; Click the display of other components;
That’s the basic configuration, then it’s time for real development;
2. Start of project development
-> app.vue file how to write?
<template>
<! - use element - the UI -- >
<el-container>
<el-aside>
<Draggable class="app-aside-drag" :options="dragOption">
<div class="app-aside-list"
v-for="(dragList,index) in dragData"
:type="dragList.type"
:key="dragList.type">
<div class="aside-item-body">
<i class="aside-item-ele"></i>
<span class="aside-item-ele">{{ list.title }}</span>
</div>
</div>
</Draggable>
<el-aside>
<el-main class="app-main">
<section class="app-phone">
<div class="app-phone-header">
<span class="phone-camera"></span>
<span class="phone-ls"></span>
</div>
<! -- Page View -->
<Sort class="app-phone-body"></Sort>
<div class="app-phone-footer">
<button class="app-phone-menu">RS</button>
</div>
</section>
</el-main>
<el-aside class="app-right">
<! -- Component editing area -->
<BaseEdit></BaseEdit>
</el-aside>
</el-container>
</template>
<script>
import DragApi from "@/dragapi/dragapi.js";
import Draggable from "vuedraggable";
import Sort from "@/view/Sort";
import BaseEdit from "@/view/BaseEdit";
export default {
name: 'app',
data(){
return{
dragData: {},
dragOption: {
group: {
name: 'components'.// This is very important, other drag box can be associated with the name must be consistent
pull: 'clone'.put: false
},
sort: false // Silence is true. Here we just need him to drag, we don't need to be able to drag to sort}}},components: {
Draggable,
Sort,
BaseEdit
},
created(){
// The sidebar drags list data
// Here I only write component data in, not layout
this.dragData = DragApi.configList[1].content; }}</script>
Copy the code
-> Take a look at the Sort View area component
<template>
<Draggable :options="sortOption"
@sort="onSort"
@add="onAdd"
class="app-sort"> <! -- UI components --> <! For those of you who don't know, go to the vUE website to see dynamic components --> <div v-for="(appUi,index) in sortApi"// Loop component :is="appUi.component"// Render based on existing components :content="appUi.content"
:oStyle="appUi.style"
:editPartShow="appUi.editPartShow"
:aIndex="index"// For the component to click, @click.native= @click.native="getIndex(index)"// The key value must be given, otherwise the sorting of the same component may fail :key="appUi.content.code"Import {mapState,mapMutations} from > </div> </Draggable> </template> <script> import {mapState,mapMutations} from'vuex'; // The drag and drop plugin introduces the import Draggable from'vuedraggable'; // Each component introduces the import Carousel from"@/components/Carousel.vue";
import Btn from "@/components/Btn.vue";
export default {
name: 'Sort',
components: {
Draggable,Btn,Carousel
},
data() {return {
sortOption: {
group: {
name: 'components'// Pull (name); // Pull (name);true,
put: true
},
sort: true, animation: 300 // Gives an animation that looks comfortable}}}, computed:{... mapState(['editIndex'.'sortApi']),
},
watch:{
sortApi:{
handler(newVal,oldVal){
window.sessionStorage.setItem('localData',JSON.stringify(newVal));
},
deep: true} }, methods:{ ... mapMutations(['sortCp'.'addCp'.'setStyle'.'setCommon'], onSort(res){// Events generated by sortingif(res.from === res.to){ this.sortCp(res); }}, onAdd(res){this.addcp (res); }, getIndex(index){ this.setCommon({index: index,flag:true});
}
}
}
</script>
Copy the code
-> Take a look at the edit component
<template>
<transition name="slide-right">
<div v-if="sortApi.length > 0 && editShow === true"> // Component-specific editing <el-tabs V-model ="activeName">
<el-tab-pane label="Component Settings" name="first">
<div v-for="(appUi,index) in sortApi"
:is="appUi.component+'Edit'"
:content="appUi.content"
:oStyle="appUi.style"
:editPartShow="appUi.editPartShow"
:aIndex="index"
:currentIndex="editIndex"
:key="appUi.content.code">
</div>
</el-tab-pane>
<el-tab-pane label="Style Settings" name="second"> // Public collapse <el-collapse v-model="colorPicker.name" class="base-edit" accordion>
<el-collapse-item class="tititt" :title="colorPicker.type" :name="colorPicker.type">
<el-form ref="form" :model="colorPicker" size="mini">
<el-form-item class="cui-inline-reset"
v-for="(item,index) in colorPicker.content"
:label="item.title"
:key="item.style"< span style = "box-sizing: border-box; color: RGB (74, 74, 74); line-height: 22px; font-size: 14px! Important; word-break: inherit! Important;" // Here the color picker returns the real-time color value // here I want to pass a corresponding style @active-change=" (value) => setStyle(value,item.style)"
v-model="sortApi[editIndex].style[item.style]"
show-alpha>
</el-color-picker>
<span class="black-text-shadow"
:style="{color: sortApi[editIndex].style[item.style]}">
{{ sortApi[editIndex].style[item.style] }}
</span>
</el-form-item>
</el-form>
</el-collapse-item>
</el-collapse>
</el-tab-pane>
</el-tabs>
</div>
</transition>
</template>
<script>
import { mapState,mapMutations } from 'vuex'; // Here I write the component-specific edit bar as a component, why not write it together with the corresponding component? // It is important to note that I did not think of a way to separate the dom structure from the same component and place it in the edit bar"@/components/BtnEdit.vue";
export default{
name: 'BaseEdit',
components: {
BtnEdit
},
data() {return{
colorPicker: {
type: 'Color Settings',
name: 'Picker',
content:[
{
title: 'Background color',
style: 'background'
},
{
title: 'Font color',
style: 'color'
}
]
},
activeName: 'first'} }, computed:{ ... mapState(['editIndex'.'sortApi'.'editShow'])
},
methods:{
setStyle(value, Style){// Change the existing value this in real time based on the Style attribute passed in above.$set(this.sortApi[this.editIndex].style,style,value);
}
}
}
</script>
Copy the code
-> Select a component and see how it is configured
// Button component, in fact, very simple // component corresponding to the edit component, inside the content is similar to this, I will not write below<template>
<div class="btn-box ui-sortable" :data-code="content.code">
<el-button class="ui-btn"
:style="oStyle">
{{ content.text }}
</el-button>// Since each component has a deletion function, it is written as a component<DeleteCp :aIndex="aIndex"></DeleteCp>
</div>
</template>
<script>
import DeleteCp from "@/components/DeleteCp";
export default {
name: 'Btn'.props: { // The argument passed by the parent component
content: Object.oStyle: Object.aIndex: Number
},
components: {
DeleteCp
},
data(){
return{
btnModel: 'btn-model'}}}</script>
Copy the code
-> Finally, let’s look at deleting components
<template>
<div class="delete-compontent-box">
<div class="el-icon-delete remove-component" @click.stop="dailogStatu"></div>
<el-dialog
title="Tip"
:visible.sync="dialogVisible"
:append-to-body="appendToBody"
width="430px">
<div class="el-message-box__content">
<div class="el-message-box__status el-icon-warning"></div>
<div class="el-message-box__message dialog-message"> This operation will delete the module. Do you want to continue? </div> </div> <span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false" size="small"</el-button> <el-buttontype="primary" @click="onRemove(aIndex)" size="small"</el-button> </span> </el-dialog> </div> </template> <script> import {mapMutations} from"vuex";
export default {
name: 'oText',
props: {
aIndex: Number
},
data() {return{// These two parameters are popup parameters dialogVisible:false,
appendToBody: true} }, methods:{ ... mapMutations(['deleteCp'.'setCommon']),
dailogStatu(){// Basically control the popup window, and display the component's corresponding edit bar this.dialogVisible =true;
this.setCommon({flag: true,index: this.aindex})}, onRemove(index){// Click OK to remove the corresponding componentlet flag = false;
this.deleteCp(index);
this.dialogVisible = false;
this.$message({
message: 'This module has been removed! '.type: 'success'
});
this.setCommon({flag: false,index: 0})
}
}
}
</script>
Copy the code
-> Have a look at the effect
conclusion
Ok, I have written a lot today. Finally, let’s comb through the ideas:
Configure the data in VUEX. Configure the data in app.vue. 4. Edit the configuration of the components
Actually every project, requires a clear path, so you can very good development, so my advice is to get the project, don’t head to write, must want to do well, and sudden things happen (such as the sudden changing requirements), so convenient for us, also convenient for later maintenance, also to prevent unnecessary trouble
Thank you for your patience, after all, this is only a general introduction, there must be a lot of deficiencies, if you have suggestions, welcome to leave a message
Finally: welcome everyone to pay attention to my personal public number: big front-end JS, of course, in order to feedback your attention, I put some learning resources inside, warmly welcome everyone to pay attention to the exchange of front-end but not limited front-end knowledge;
Project open source
It’s time to cash in on what I said before, open source, of course, deleted a lot of things, leaving a big frame under the ideas given in this article, if you want to add their own functions or need to add, delete, change and check on the basis of this idea oh! Without further ado, please provide the project address: project address, if you like, please give more to star oh 23333
Original is not easy, please indicate the source and original link when reprinting, thank you!