4

In the last article, we introduced how to dynamically create spreadsheet components in Vue by setting runtimeCompiler to true. If you want to know the specific content, please click to view Use VUE components to create SpreadJS custom cells (1) .

But in actual scenarios, we may only need to dynamically create VUE components, and the template content of the components does not need to be dynamically loaded. Faced with this situation, autoComplete is a typical usage scenario.

autoComplete gives us the freedom to convert any incoming input into elements with tags \<input\>, \<textarea\> and contenteditable attributes. Upon completion of the keyboard input, the plugin starts searching for matching entries and displays a list of values to choose from. By entering more characters, the user can filter the list for a better match.

In the front-end spreadsheet , we can directly use it to make selections on content, such as entering a tag for an article or entering an email address from an address book. ; autocomplete can also be used to populate relevant information, such as entering a city name and getting a zip code. Now if we want to implement this function in the pure front-end table, we can solidify the dynamically created Component, import and mount it as needed.

This simplifies what we mentioned in the previous article, and needs to open the runtimeCompiler to achieve it.

Next, we will introduce the specific method for you:

  1. Component that encapsulates the AutoComplete component
  <div>
    <el-autocomplete
      :style="cellStyle"
      popper-class="my-autocomplete"
      v-model="text"
      :fetch-suggestions="querySearch"
      placeholder="请输入内容"
      :popper-append-to-body="false"
      value-key="name"
      @select="handleSelect"
    >
      <i
        class="el-icon-edit el-input__icon"
        slot="suffix"
        @click="handleIconClick"
      >
      </i>
      <template slot-scope="{ item }">
        <div class="name">{{ item.name }}</div>
        <span class="addr">{{ item.phone }}</span>
      </template>
    </el-autocomplete>
  </div>
</template>
  <script>

import DataService from '../static/dataService'

export default {
    props: ['text','cellStyle'],
    mounted() {
        this.items = DataService.getEmployeesData();
    },
    methods: {
        querySearch(queryString, cb) {
            var items = this.items;
            var results = queryString ? items.filter(this.createFilter(queryString)) : items;
            // 无法设置动态内容的位置,可以动态添加gcUIElement
            // setTimeout(() => {
            //   let popDiv = document.getElementsByClassName("my-autocomplete")[0];
            //   if(popDiv){
            //     popDiv.setAttribute("gcUIElement", "gcEditingInput");
            //   }
            // }, 500);
            // 调用 callback 返回建议列表的数据
            cb(results);
        },
        createFilter(queryString) {
            return (restaurant) => {
            return (restaurant.name.toLowerCase().indexOf(queryString.toLowerCase()) === 0);
            };
        },
        handleSelect(item) {
            console.log(item);
        },
        handleIconClick(ev) {
            console.log(ev);
        }
    }
}
</script>

A few points to note

  • The component provides the text (or value) attribute, which is used for the value that needs to be edited in the corresponding cell. If the component is not two-way bound with the model, the text needs to be actively updated after the operation.
  • Provide cellStyle, user CellType, control the size of the component according to the cell size
  • If the component has injected DOM elements that are not inside the template div, you need to add the gcUIElement attribute. The reason is detailed in the previous article.

2. autoComplete mounts components directly, no additional dynamic declarations are required

import AutoComplete from '../components/AutoComplete'

AutoComplateCellType.prototype.activateEditor = function (editorContext, cellStyle, cellRect, context) {
    let width = cellRect.width > 180 ? cellRect.width : 180;
    if (editorContext) {
       // create component constructor
       const AutoCompleteCtor = Vue.extend(AutoComplete);
        this.vm = new AutoCompleteCtor({
        propsData: {
          cellStyle: {width: width+"px"}
        }
      }).$mount(editorContext.firstChild);
    }
};

The rest of the code remains unchanged, so not only does the runtimeCompiler not need, but the maintainability of the code is also improved.

This series of two articles introduces in detail the use of two different methods to solve the problem that due to the framework life cycle and custom cell rendering logic, it is currently impossible to directly use the components under the framework through the template method under the framework page. . And we used Vue to solve this problem smoothly, and optimized it in the second way, which effectively improved the maintainability of the code.

In the future, we will also bring you more interesting content from other perspectives~ If you are interested in pure front-end spreadsheet SpreadJS , you can actually experience it.


葡萄城技术团队
2.7k 声望29.3k 粉丝

葡萄城是专业的软件开发技术和低代码平台提供商,聚焦软件开发技术,以“赋能开发者”为使命,致力于通过表格控件、低代码和BI等各类软件开发工具和服务,一站式满足开发者需求,帮助企业提升开发效率并创新开发模式。