Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to implement Page Builder with javascript

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly introduces "javascript how to achieve page generator" related knowledge, editor through the actual case to show you the operation process, the method of operation is simple and fast, practical, I hope that this "javascript how to achieve page generator" article can help you solve the problem.

target

Our goal is to achieve a page production background, in the background, we can select the components of the page-> layout style adjustment-- > publish online-- > edit and modify such process operations.

Architecture design

First of all, to be able to provide components for users to choose, then we need a component library, and then we need to adjust the layout style of the selected components, so we need a page editing background, and then we need to render the edited data into a real page, so we need a node service and a template template for filling. Release online, this directly connected to each company's internal release system is good, here we do not elaborate too much. The final editing and modification function is to modify the configuration, so we need a database, here I choose to use mysql. Of course, you can also do rights management, page management by the way. Wait, that kind of work. After such a long talk, let's draw a picture and understand the general process:

Implementation of opening and pulling component

First of all, let's implement this part of the component, because the component is associated with the preview of the background editor and the use of the final release. Component design we should try to maintain the external consistency of the component, so that when rendering, we can provide a unified external data interface. Our technology selection here is based on Vue, so the following code is mainly based on Vue, but it remains the same, and other languages are similar.

According to the figure above, our components will be split and released to the npm repository one by one. Why is it so designed? In fact, we have also considered designing a component library, where all components are contained in a component library, so we only need to publish a component library package and load it on demand when we use it. Later, in the process of practice, it is found that this is not suitable for collaborative development, and if other front ends want to contribute components, the transformation cost of access is also very high. For example: Xiao Ming wrote a Button component in his business, which is often reused by other projects. He wants to contribute this component to our system and be used by templates. If it is a component library, he first has to pull the code of our component library and then submit it according to the standard format of the component library. As a result, lazy Xiao Ming may not be willing to do so, the best way is to build a npm library locally, we don't care whether the developer uses TypeScript or other things, we don't care about the Css preprocessor, or even the ESLint of the coding specification. Finally, all you have to do is pass the compiled file. This avoids the constraints of a component library. Relying on the perfect release / pull and version control mechanism of NPM, we can not only do less extra work, but also quickly build the platform.

After all that has been said, where is the code? Let's take an Button as an example, where we provide components in this form:

{{data.context}} export default {name: 'WButton', props: {data: {type: Object, default: () = > {}

You can see that we have only exposed one props to the outside. The advantage of this approach is that we can unify the data exposed by the component and how it is played inside the component. Note that we can also introduce some third-party component libraries, such as mint-ui.

Implementation of background Editing

Before we write the code, let's consider what functions we need to implement:

A property editing area that provides users with the ability to edit the internal props of the component

A component selection area that provides the user to select the required components

A component preview area that provides users with the ability to drag and drop a preview of the sorting page

Realization of Editing area

In order, let's first implement the property editing function of the component. We need to consider what configurable information a component exposes. How to synchronize this configurable information to the background editing area for editing by the user, the configurable information for a button may be as follows:

If you write all these configurations in the backend library, loading different configurations according to the currently selected components will be very troublesome to maintain, and as the number of components increases, it will become bloated. So we can store these configurations on the server, and the backend only needs to parse according to the storage rules. For example, we can actually store such editing configurations:

[{"blockName": "button layout settings", "settings": {"src": {"type": "input", "require": true, "label": "button copy"}]

We are in the editing background, and we can request these configurations through the API to render regularly:

/ * according to the type, select to create the corresponding component * @ param {VNode} vm * @ returns {any} * / createEditorElement (vm: VNode) {let dom = null switch (vm.config.type) {case 'align': dom = this.createAlignElement (vm) break Case 'select': dom = this.createSelectElement (vm) break; case' actions': dom = this.createActionElement (vm) break; case 'vue-editor': dom = this.createVueEditor (vm) break; default: dom = this.createBasicElement (vm)} return dom} component selection function

The first thing we need to consider is, how do components register? Because we need to render the component when it is selected by the user, we can provide a node script to traverse the required component and register the installation of the component:

/ / define rendering template and path var OUTPUT_PATH = path.join (_ _ dirname,'. / packages/index.js'); console.log (chalk.yellow ('generating package reference file...') var INSTALL_COMPONENT_TEMPLATE ='{{name}}'; var IMPORT_TEMPLATE = 'import {{componentName}} from\\' {{name}}\' Var MAIN_TEMPLATE = `/ * Automatic generated by'. / compiler/build-entry.js' * / {{include}} const components = [{{install}}] const install = function (Vue) {components.map ((component) = > {Vue.component (component.name, component)})} / * istanbul ignore if * / if (typeof window! = = 'undefined' & & window.Vue) {install (window.Vue)} export {install, {{list}` / / render reference file var template = render (MAIN_TEMPLATE, {include: includeComponentTemplate.join (endOfLine), install: installTemplate.join (`, ${endOfLine}`), version: process.env.VERSION | | require ('.. / package.json'). Version, list: listTemplate.join (`, ${endOfLine}`)}); / / write reference fs.writeFileSync (OUTPUT_PATH, template)

The final rendered file looks something like this:

Import WButton from 'w-button'const components = [WButton] const install = function (Vue) {components.map ((component) = > {Vue.component (component.name, component)})} / * istanbul ignore if * / if (typeof window! = =' undefined' & & window.Vue) {install (window.Vue)} export {install, WButton}

This is also a common way to write a component library, so the idea here is to aggregate the components published on the npm into a component package reference, which needs to be fully introduced when editing in the background:

Import * as W_UI from'.. /.. / packages'Vue.use (W_UI)

In this way, our component registration is finished, the component selection area is mainly to provide options for the component, we can traverse the component and provide a List for the user to choose, of course, if we provide only one component name, the user may not know what the component looks like, so we had better provide a thumbnail of what the component looks like. Here we can also do this through the node script when the component is released. There is a lot of code to be implemented here, so I will briefly talk about the process, because it is not the core logic and is dispensable. It can only be said that it would be better to have the experience:

Users enable dev-server for coding testing

The server script uses the Chrome tool puppeteer to adjust the page to the mobile mode and take a screenshot of the current dev-server.

Generate screenshot files, upload them to node service, and associate components

This allows you to attach a thumbnail to the component when the component selection area is loaded.

Component preview area

When the user selects components in the selection area, we need to display them in the preview area, so how do we know which components the user has selected? You can't write all the components into the rendering area in advance, and you can judge the choice by v-if, right? Not so stupid, of course. Vue already provides the functionality of dynamic components:

Why don't we use thumbnails instead of real components? On the one hand, there are problems with the size of the generated thumbnails, on the other hand, we need the linkage of editors, that is, editors in the editing area need timely feedback to users.

Additional questions

Having said so much, everything seems to be going well, but in practice, we found that there is an obvious problem: the preview area among us is actually designed to simulate the effect of the mobile page as much as possible. But if we add some components that contain a similar position: fixed style, we will find that there is an obvious problem with the style. Typical, such as Dialog Loading, etc. So we refer to the design of the m-ui component library and show the intermediate preview operation container as an iframe. Resize the iframe to 375x667to simulate the mobile end of iPhone 6. In this way, there will be no style problems. However, another difficulty arises in this way, that is, how can the editing data on the left be reflected in iframe in time? Yes, it's postMessgae. The general idea is as follows:

Using vuex as the data storage pool, all the changes are synchronized through postMessgae, so that we only need to make sure that the data changes in the data pool can be mapped to the changes in the rendering layer. For example, if we do component selection and drag-and-drop sorting in the preview area, we only need to synchronize the information via vuex:

/ / action.tsconst action = {setCurrentPage ({commit, state}, page: number) {/ / update the current store commit ('setCurrentPage',page) / / corresponding postMessage helper.postMsgToChild ({type:' syncState', value: state})}, / /...} implementation of the Template template

For the design and implementation of the template, I refer to the idea of Vue-cli version 2.x and store the template here in the corresponding git repository. When users need to build a page, they can pull the corresponding template directly from the git repository. Of course, after pulling, a copy will be cached locally, and then rendered and read directly from the local cache. We now focus on the format and specification of the template. It doesn't matter what kind of syntax we use in the template. Here I use the same Handlerbars engine as Vue-cli. Here goes directly to the design of our template:

{{# components}} {{/ components}} {{noRepeatCpsName}} import {{upcasefirst this}} from'{{this}}'{{/ noRepeatCpsName}} export default {name:'{{upcasefirst repoName}}', components: {noRepeatCpsName}} {{upcasefirst this}}, {{/ noRepeatCpsName}

To simplify the logic, we designed the templates as a streaming layout, with all the components stacked down one by one. This file is the App.vue in our vue-webpack-simple template. We rewrote it. In this way, a single Vue file can be rendered by filling ten thousand data. Here I only give one example, we can also implement multi-page templates and other complex templates, according to the needs of different templates can be pulled.

Node rendering service

When the backend submits a rendering request, our node service mainly does the following:

Pull the corresponding template

Render data

Compile

Pull is to go to the designated repository to pull the template through the download-git-repo plug-in. Compilation is actually through the metalsmith static template generator to the template as the input, data as the fill, according to the handlebars syntax for regular rendering. Finally, the directory built by build is produced. At this step, the components we needed before will be rendered into the package.json file. Let's take a look at the core code:

/ / it is like a pipeline, which takes the data entry as the generation source and compiles and outputs to the destination directory function build (data, temp_dest, source, dest, cb) {let metalsmith = Metalsmith (temp_dest) .use (renderTemplateFiles (data)) .source (source) .destination (dest). Clean (false) return metalsmith.build ((error, files) = > {if (error) console.log (error)) Let f = Object.keys (files) .filter (o = > fs.existsSync (path.join (dest, o)) .map (o = > path.join (dest, o)) cb (error F)})} function renderTemplateFiles (data) {return function (files) {Object.keys (files). ForEach ((fileName) = > {let file = files [fileName] / / rendering method file.contents = Handlebars.compile (file.contents.toString ()) (data)})}}

In the end, what we get is a Vue project, which can not be run directly on the browser side at this time, so it is related to the form supported by the current release system. How to say that ? If your company's release system needs to be compiled online, you can upload the source file directly to the git warehouse and trigger the warehouse's WebHook to let the release system send the project for you. If your distribution system requires you to compile and submit compiled files for release, then you can use the node command to build locally to produce HTML, CSS, and JS. You can submit it directly to the publishing system.

This is the end of the introduction to "how javascript implements the page generator". Thank you for your reading. If you want to know more about the industry, you can follow the industry information channel. The editor will update different knowledge points for you every day.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report