preface

Read the series in order before reading, for better results! Vue routes to a common component, and then dynamically loads the component based on whether files exist in the path

It is said that the series of articles is difficult to be popular, because the knowledge point baggage is not enough, so we are not willing to collect in the future, but it doesn’t matter, the benefit of the series of articles is to look comfortable, fragmental time is soon finished, isn’t it?

1. Review

The first part basically belongs to the exploration stage, after exploration, Vue’s function is still very powerful! As an important front-end output weapon, it can be said that Xiao Li flying knife, no case of virtual hair, knife deadly.

Now that it’s validated, it shows that the common component does the job and can be easily extended. Even if the automatically generated common components don’t meet the requirements, why not let the flat-lying front-end engineer get up and continue coding on demand?

The second part tries to overview the requirements from the big idea combined with the advantages of the front and back ends. Overall coordination to complete a nearly impossible demand (let the front end of the little brothers lie flat, do not know whether to save the front end, or destroy the front end).

Front end brothers, when you figure this out, you should have advanced, don’t care about this little pressure, right?

In fact, it is still a big project to really complete this demand, and there are still many problems during this period. This is not me again.

2. Back-end interface development

The book is connected back, saying that by the rear end of the operator, the design of the interface table has been shaped, this is not, the product manager A found the door.

Product Manager A: “Wok, Wang, is it there?”

Is the code of the back end of the shaking pot king, suddenly heard the ear spread familiar and with the magic voice, not only a fibrillation in the heart, with reluctance, but still pretending to be a hundred times the spirit of the answer, “Ah ah, in this.”

Product manager A: “Come alive! The design that you said last time is very good, can make a few interfaces today, let front end child shoe play?”

The back end rejects the pot king: “see outside, this is not minute matter? However front end child shoe is not ask for leave (lie flat)?”

Product manager A: “This is not asking for leave to wait in line to get the vaccine. When I arrived, I found that I went to work too early. I ranked first, so I came to work again.”

The back end of the pan king psychological dark scold, this unlucky child, my time to touch fish! And they said, “Ok, let’s give him a job!”

The product manager A patted the back end to shake the pot king, “Big god, I look forward to you!”

Visual Studio 2019 Global Enterprise Planning flagship edition, right-click openEF Core Power Tools”I saw him operate as follows, but in a moment, three five divided by two to fix the entity definition.

All that magic is left is the write service layer and the API control layer.

If not, return the control as a number, text, and date by default.

private string GetDefaultType(Type type)
 {
      if (numberType.Contains(type))
      {
          return "Number";
      }
      else if (dateType.Contains(type)){
          return "DateTime";
      }
      else
      {
          return "Text"; }}Copy the code

The definitions that automatically get the column information according to the EF definition and generate lists and forms are inserted into the database.

// To insert a list, look at the following code
 var type = _unitOfWork.DbContext.Model.GetEntityTypes().FirstOrDefault(x=>x.ClrType.Name == model.ModelName);
 if(type == null)
  {
      throw new BusinessException(PublicError.NotFoundModelName, model.ModelName);
  }
  List<UdfListTemplate> templates = new List<UdfListTemplate>();
  var sortId = 10;
  foreach(var p in type.GetProperties())
  {
      //var f = p.FieldInfo;
      templates.Add(new UdfListTemplate
      {
          ModelGuid = model.ModelGuid,
          ModelName = model.ModelName,
          SysId = model.SysId,
          FieldName = p.Name,
          ControlType = GetDefaultType(p.ClrType),
          SortId = sortId,
          Width = 140,
          IsEncrypte = 0,
          IsFixed = 0,
          IsHidden = 0,
          IsSearch = 1,
          IsSort = 1,
          IsSum = 0}); sortId +=10;
  }
  // Insert a batch, fast (can query the previous batch insert article)
  await _unitOfWork.DbContext.BulkInsertAsync<UdfListTemplate>(templates);
Copy the code

Define the front – end children’s shoes access interface

 [HttpGet("{modelGuid}")]
 [AllowAnonymous]
   public Task<GetModelDefineResult> GetModelDefine(string modelGuid)
   {
       return _modelService.GetModelDefine(modelGuid);          
   }
Copy the code

We’re done, we’re testing, and we’re done!

Touch the fish. You can deliver the front end shoes.

3. Design of front children’s shoes

I’m the front end. Say that day, originally want to give product economy a sudden attack, did not think of the pot king’s pot or hit my head, ah, this unlucky child ~~~

To show how much I care about this feature, I’ll start with an ES6 class, just to kick things off.

3.1 class design

Generally for the interface of this kind of change of class, usually our front-end principle is to take as you go, design wool class!

For example, the back-end A\B interface returns the following format:

//A
{
 "data": {
    "a":123."b":"aaaaaabbbb"}}//B
{
   "list": ["a"."b"]."saa":"aaa"
}
Copy the code

So I basically get the data from the API, and I use it, assuming that data is the return value from the API

 const a = data.data.a
 const b = data.data.b
 const c = data.list[0]
 const d = data.saa
Copy the code

Good ~~~, if something goes wrong, BB back end, why don’t you return XXX? You can’t be null!

This design class, a little idle! Copy some of them

// Module information definition
class UdfModelInfo {
  constructor(modelGuid, modelName, sysId, name, businessPk, functionOperate, formColNum, listShowSelect, listShowPage, listShowNo, listShowTree, udf1, udf2, udf3) {
    this.modelGuid = modelGuid
    this.modelName = modelName
    this.sysId = sysId
    this.name = name
    this.businessPk = businessPk
    this.functionOperate = functionOperate
    this.formColNum = formColNum
    this.listShowSelect = listShowSelect
    this.listShowPage = listShowPage
    this.listShowNo = listShowNo
    this.listShowTree = listShowTree
    this.udf1 = udf1
    this.udf2 = udf2
    this.udf3 = udf3
  }
}

// Module/list/form definition
export default class UdfModel {
  constructor(model, listTemplate, formTemplate) {
    this.model = newUdfModelInfo(... model)this.listTemplate = newUdfListTemplate(... listTemplate)this.formTemplate = newUdfFormTemplate(... formTemplate)this.createDate = new Date()}}export {
  UdfListTemplate,
  UdfFormTemplate,
  UdfModelInfo,
}
Copy the code

3.2 Designing A Store

Vuex is used here to store configuration information on each request. We plan to save data to VUEX every 10 minutes, if more than 10 minutes, we will re-request the backend API.

Map is used to store data by modelGuid because it is unique.

const state = {
  udf: new Map(),}Copy the code

I’m going to add 2 mutations to operate the UDF

const mutations = {
  SET_UDF_MODEL: (state, key, data) = > {
    const udfModel = new UdfModel(data.model, data.listTemplate, data.formTemplate)
    state.udf.set(key, udfModel)
  },
  CLEAR_CACHE: (state) = > {
    state.udf.clear()
  },
}
Copy the code

According to the VUEX specification, we need to add asynchronous Actions instead. In this case, we use the stored time to determine if the value exceeds 10 minutes. If it does, we get the configuration information from HTTP and update it.

const actions = {
  setUdfModel({ commit }, guid) {
    if (state.udf.has(guid)) {
      const val = state.udf.get(guid)
      if (val && Math.abs(((new Date()).getTime() - val.createDate.getTime())) > 1000 * 60 * 10) {
        return}}const http = new Http()
    http.fetch({
      url: `/Tools/GetModelDefine/${guid}`.method: 'get',
    }).then(data= > {
      if (data && 'model' in data) {
        commit('SET_UDF_MODEL', guid, data)
      }
    })
  },
  clearCache({ commit }) {
    commit('CLEAR_CACHE')}},Copy the code

All right, so I’m going to export these variables.

export default {
  namespaced: true,
  state,
  mutations,
  actions,
}

Copy the code

3.3 Clearing the Cache

Because VUex does not have persistent storage, the user presses F5 to clear all the cache. In order to make frequent login user experience more pleasant, we actively clear the cache when logging in.

Add a reference to mapActions in the component of the logged in user.

import { mapActions } from 'vuex'
Copy the code

Introduce the cleanup cache method in the component method:

methods: { ... mapActions({clearUdfCache: 'udf/clearCache',}})Copy the code

Then, when the component is created, it is called.

 created() {
    this.clearUdfCache()
}
Copy the code

3.4 Loading Data

As mentioned earlier, our common operation methods are already extracted into the Mixus class, so we load the data when we define the component’s creation methods.

Since the same public component is used to complete the operation of adding, deleting, changing and checking all modules, according to the optimization strategy of Vue, after switching routes, the public component is not destroyed, but reused, so its Created hook method is only called once.

To enable the new configuration to be invoked after switching routes, we use the method of monitoring routes to load data.

watch: {
    $route: function(to, from) {
      // todo
      // console.log('watch', to)
      let guid = ' '
      if (to.meta && 'guid' in to.meta) {
        guid = to.meta.guid
      } else {
        let arr = to.path.split('/').slice(0.3)
        arr = arr.map(item= > item ? item[0].toUpperCase() + item.substring(1) : ' ')
        guid = arr.join(' ')}console.log('guid=', guid)
      this.$store.dispatch('udf/setUdfModel', guid)
    },
  },
Copy the code

After a series of operations, the configuration data can be loaded very well!

4 summary

Laying down every engineer is not what I want to see, we want to help the novice more quickly to save time and focus on more complex requirements logic.

So don’t worry, the above dialogue is just a joke, software engineer is the system development indispensable talent, of course, we should also start more brains, let the tedious repetition away from the human! This is also one of the sacred responsibilities of software engineers