In some special scenarios, the timing of using the component cannot be determined, or the component we want to use cannot be determined in the template of Vue. In this case, it is necessary Mount components dynamically, or use runtime compilation to dynamically create components and mount them.
Today we will take you starting from the actual project to see how to dynamically mount components when actually solving customer problems, and show you a complete process of solving dynamic mounting problems.
When our spreadsheet control SpreadJS is running, there is such a function: When the user double-clicks the cell, an input box will be displayed for editing the content of the cell. The user can customize the form of the input box according to the specifications of the custom cell type and integrate any Form form input type according to the needs.
The creation and destruction of this input box is achieved by inheriting the corresponding method of the cell type, so there is a problem here - this dynamic creation method cannot be simply configured in the VUE template and then used directly. [Related recommendations: vuejs video tutorial]
Not long ago, a customer asked me: Is the custom cell of your control Support Vue components such as ElementUI's AutoComplete?
Due to the problem mentioned earlier:
# After pondering for a long time, I seriously replied to the customer: "The component operation life cycle is inconsistent and cannot be used", but He changed the topic again and said that this problem can be solved using universal components.
The problem was successfully solved.
But this helpless "can't be used" has also become a hurdle that I can't overcome in my midnight dreams these days.
Later, when I was looking at the Vue documentation one day, I thought that App is mounted to #app when it is running. , in theory, other components should also be able to be dynamically mounted to the required Dom, so the problem of creation timing is solved!
Let us continue to view the documentation. The global APIVue.extend(options) is created through extend. Vue instances can be mounted directly to DOM elements using the $mount method - which is exactly what we need.
<div id="mount-point"></div> // 创建构造器 var Profile = Vue.extend({ template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>', data: function () { return { firstName: 'Walter', lastName: 'White', alias: 'Heisenberg' } } }) // 创建 Profile 实例,并挂载到一个元素上。 new Profile().$mount('#mount-point')
Create AutoCompleteCellType according to the SpreadJS custom cell example and set it to the cell:
function AutoComplateCellType() { } AutoComplateCellType.prototype = new GC.Spread.Sheets.CellTypes.Base(); AutoComplateCellType.prototype.createEditorElement = function (context, cellWrapperElement) { // cellWrapperElement.setAttribute("gcUIElement", "gcEditingInput"); cellWrapperElement.style.overflow = 'visible' let editorContext = document.createElement("div") editorContext.setAttribute("gcUIElement", "gcEditingInput"); let editor = document.createElement("div"); // 自定义单元格中editorContext作为容器,需要在创建一个child用于挂载,不能直接挂载到editorContext上 editorContext.appendChild(editor); return editorContext; } AutoComplateCellType.prototype.activateEditor = function (editorContext, cellStyle, cellRect, context) { let width = cellRect.width > 180 ? cellRect.width : 180; if (editorContext) { // 创建构造器 var Profile = Vue.extend({ template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>', data: function () { return { firstName: 'Walter', lastName: 'White', alias: 'Heisenberg' } } }) // 创建 Profile 实例,并挂载到一个元素上。 new Profile().$mount(editorContext.firstChild); } };
Run, double-click to enter the editing state, but found an error
[Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.
According to the error message, we have two solutions at this time:
Turn on runtimeCompiler, add runtimeCompiler: true configuration to vue.config.js, and allow runtime compilation, so Templates can be generated dynamically to meet the needs of dynamic components
Compiling templates in advance is only dynamically mounted. The autocomplete components are determined. We can use this method
Create a new AutoComplete.vue component for dynamic mounting, so that compiled components can be mounted.
<template> <div> <p>{{ firstName }} {{ lastName }} aka {{ alias }}</p> </div> </template> <script> export default { data: function () { return { firstName: "Walter", lastName: "White", alias: "Heisenberg", }; }, }; </script> import AutoComplate from './AutoComplate.vue' AutoComplateCellType.prototype.activateEditor = function (editorContext, cellStyle, cellRect, context) { let width = cellRect.width > 180 ? cellRect.width : 180; if (editorContext) { // 创建构造器 var Profile = Vue.extend(AutoComplate); // 创建 Profile 实例,并挂载到一个元素上。 new Profile().$mount(editorContext.firstChild); } };
Double-click to enter the editing state and see the content in the component
Next step, for custom cells, you also need to set and get the edit in the component Content, then by adding props to the component, and at the same time directly obtaining all the props content on the VueComponent instance created when mounting, the corresponding operation can realize the data acquisition setting.
Update AutoComplate.vue, add props, and add input for editing
<template> <div> <p>{{ firstName }} {{ lastName }} aka {{ alias }}</p> <input type="text" v-model="value"> </div> </template> <script> export default { props:["value"], data: function () { return { firstName: "Walter", lastName: "White", alias: "Heisenberg", }; }, }; </script>
Store the VueComponent instance through this.vm, obtain and set the Value for the VUE component in the getEditorValue and setEditorValue methods. After editing, destroy the dynamically created component by calling the $destroy() method.
AutoComplateCellType.prototype.activateEditor = function (editorContext, cellStyle, cellRect, context) { let width = cellRect.width > 180 ? cellRect.width : 180; if (editorContext) { // 创建构造器 var Profile = Vue.extend(MyInput); // 创建 Profile 实例,并挂载到一个元素上。 this.vm = new Profile().$mount(editorContext.firstChild); } }; AutoComplateCellType.prototype.getEditorValue = function (editorContext) { // 设置组件默认值 if (this.vm) { return this.vm.value; } }; AutoComplateCellType.prototype.setEditorValue = function (editorContext, value) { // 获取组件编辑后的值 if (editorContext) { this.vm.value = value; } }; AutoComplateCellType.prototype.deactivateEditor = function (editorContext, context) { // 销毁组件 this.vm.$destroy(); this.vm = undefined; };
The whole process has been run through. All you need to do is replace the input with ElementUI's el-autocomplete in AutoComplate.vue and implement the corresponding method.
Let’s see the effect.
In fact, dynamic mounting is not a complicated operation. After understanding the Vue example, operating the instance through vm, and flexibly using dynamic mounting or runtime compiled components is not difficult.
In fact, all the solutions are in the Vue tutorial introductory tutorial, but the use of scaffolding and the use of various tools make us forget the original intention of Vue, and instead complicate simple problems.
Today’s sharing ends here, and we will bring you more serious and interesting content in the future~
More programming-related knowledge , please visit: Introduction to Programming! !
The above is the detailed content of Let you use Vue to solve the problem of 'dynamic mounting' that cannot be solved. For more information, please follow other related articles on the PHP Chinese website!