vue3 中说 createApp
只能调用一次,可是我现在有两个场景需要手动挂载 组件的情况:
手动挂载弹窗,比如我手动挂载一个按钮组件:
const SubVue = Vue.extend(Button)
const ButtonInstance = new SubVue({
propsData: {
type: 'primary'
},
})
ButtonInstance.$slots = {
default: 'el-button',
}
ButtonInstance.$mount(this.$refs.container)
vue3 中不再支持 extend
, 因此我使用createApp
代替,可是第二次调用createApp
的返回值和第一次调用的返回值不同,第二次的返回值没有umount
方法,挂载后无法手动卸载应用。
有你一个表格,我使用render
函数自定义列内容,比如:
{
label: '调查情况',
// prop: 'iis',
prop: ({ row }) => {
const item = planOptions.find(item => item.value === row.iis)
return <span>{item?.label ?? ''}</span>
},
},
prop 传递一个 render 函数,实现列自定义。
前端在导出当前页数据的时候,为了能拿到 render 函数渲染后的数据,我就手动调用 careateApp 手动渲染 vNode, 然后获取 textContent, 在使用 textContent 填充表格,去导出,目的是为了拿到映射后的结果,用户能理解。
关键代码:
const vNode = item.prop({ row })
console.log(vNode)
// eslint-disable-next-line vue/one-component-per-file
const rowApp = createApp({
render() {
return h(vNode)
},
}).mount('#temp-row')
value = el.textContent
rowObj[item.label] = value
console.log(rowApp)
// rowApp.unmount() // rowApp 没有 umount 方法,无法卸载
为何我手动挂载 render 函数?
我想要拿到最后渲染输出,再导出到 excel 表格中,比如 接口返回 1 表示成功,表格的某一列需要显示成功,为了映射关系因包含在表格的自定义列的 render 函数里,我手动得挂载 render, 再去获取渲染后的 textContent , 就是用户能理解的数据,而不是 1.
rowApp 没有 umount 方法,无法卸载这个零时的 app, 使用 vue 的开发工具查看,能看到很多 App。
问题总结,一个 vue3 应用中无法多次调用createApp
,比如这样:
const app: App = createApp(App) // 一个任意组件
console.log('app')
console.log(app)
const rowApp = createApp({
setup(){
return ()=>h('p','row-app')
}
}).mount('#temp-row')
console.log('rowApp')
console.log(rowApp)
两次调用的返回值不同,第二次调用无法卸载 rowApp。
如何多次调用 createApp 或者如何变相实现我这两个需求?
在 Vue 3 中,createApp
函数确实可以多次调用以创建多个 Vue 应用实例,但每个实例都是独立的,并且每个实例都有自己的生命周期和挂载点。关于你提到的两个问题,我们可以分别探讨解决方案。
在 Vue 3 中,由于不再支持 Vue.extend
和 $mount
/$destroy
这样的实例方法,你需要通过不同的方式来手动挂载和卸载组件。一个常见的方法是使用 mount
和 unmountComponentAtVNode
(如果你使用的是 Vue 3 的 Composition API 插件,如 @vue/composition-api
在 Vue 2 中,或者类似的第三方库)。但在纯 Vue 3 中,你可以直接操作 DOM 来卸载组件。
这里是一个简单的示例,展示如何挂载和卸载一个组件:
// 创建一个根组件
const AppComponent = {
setup() {
return () => h('button', { type: 'primary' }, 'Click me');
}
};
// 挂载组件
const mountNode = document.getElementById('app');
const app = createApp(AppComponent).mount(mountNode);
// 卸载组件
function unmountComponent() {
// 直接移除 DOM 节点
mountNode.innerHTML = '';
// 如果需要,可以调用 app.unmount()(如果 Vue 3 提供了这样的方法,但在纯 Vue 3 中通常不这样做)
// 注意:Vue 3 默认没有 app.unmount(),但可以通过其他方式实现类似的功能
}
// 稍后,你可以调用 unmountComponent() 来卸载组件
注意:Vue 3 并没有直接提供一个 unmount
方法来卸载整个应用实例。通常,你可以通过移除挂载点(如上例所示)来卸载组件。
在你的场景二中,你试图通过 createApp
来渲染 JSX/VNode 并获取其文本内容。然而,这种方法并不是最高效或最直接的。你可以直接在 JavaScript 中渲染 JSX/VNode 并使用 DOM API 来获取文本内容,而无需挂载到 DOM 上。
例如,使用 renderToString
(如果你在使用 Vue 3 的服务器端渲染功能或类似的库)或者直接使用 h
函数和 DOM 操作:
import { h, renderToString } from 'vue';
// 假设 item.prop 是一个返回 VNode 的函数
const vNode = item.prop({ row });
// 如果你只是想获取渲染后的字符串(对于 SSR),可以使用 renderToString
// 注意:这需要你在服务器端或支持 SSR 的环境中
// const htmlString = renderToString(vNode);
// 如果你只是想获取文本内容,可以创建一个临时的 DOM 元素并渲染 VNode
const tempDiv = document.createElement('div');
render(vNode, tempDiv); // 注意:这里使用的是 render 而不是 createApp.mount
const textContent = tempDiv.textContent;
// 使用 textContent ...
// 然后清理 DOM
tempDiv.remove();
注意:在这个示例中,我使用了 render
函数而不是 createApp.mount
。render
函数用于将 VNode 渲染到 DOM 节点上,但它不会创建一个完整的 Vue 应用实例。这通常用于渲染静态内容或小型组件,而不需要 Vue 的响应式系统或生命周期钩子。
总结来说,Vue 3 允许你多次调用 createApp
,但每个应用实例都是独立的,并且你可能需要手动管理它们的挂载和卸载(通过操作 DOM 或其他方式)。对于 JSX/VNode 的渲染,考虑使用 render
函数而不是 createApp.mount
,除非你确实需要一个完整的 Vue 应用实例。
在子组件内有: 在父组件 点击按钮时候会滑动: 但是比如我在点击一次setSelIdx(20)之后,再点击,执行: setSelIdx(20) 子组件就不会更新再继续执行这个代码了:
问题内容: 我正在使用以下代码通过AJAX提交表单: 背景 我的PHP处理程序执行各种任务,然后发回响应。然后,我可以在成功或错误函数中执行某些操作。 我的问题 当用户双击表单的“提交”按钮时,将发生两次AJAX调用,这将导致我的PHP处理程序中的代码执行两次。 我的问题 如果用户双击提交,如何避免我的代码执行两次? 问题答案: 当AJAX调用再次出现时,请先禁用首次单击的“提交”按钮,然后重新启
最近发现vue3在在mode为function和module下有时候编译的结果不一样。 于是想调试一下vue3的编译过程,特别是插值表达式中变量被替换为诸如ctx.aa这种的过程。 折腾了好久,发现只能调试mode为function时候的过程,在vite或者vue-cli项目中调试mode为module,但是到模版的编译时候,只能看见openBlock函数和setupBlock函数,但是看不见re
问题内容: 我需要创建一个只能执行一次的函数,在第一次执行后,每次都不会执行。我从C++和Java知道可以完成此工作的静态变量,但我想知道是否有更优雅的方法来做到这一点? 问题答案: 如果用“将不执行”来表示“多次调用将不执行任何操作”,则可以创建一个闭包: 使用全局变量,其他代码可以重置“已执行”标志的值(无论您为它选择什么名称)。使用闭包时,其他代码都无法做到这一点,无论是偶然还是故意的。 正
Nietschze夸大了他所说的: 杀不死我们的,只会让我们更强大。 你最大的责任是对你的团队负责。你应该非常了解他们中的每个人。你应该激励你的团队,但不要让他们过劳。你通常应该告诉他们他们被激励的方式。如果他们觉得划算,他们会被很好的激励。每个工程中,或者在每个其他的工程里,试着同时用他们建议的以及你认为对他们好的方式去激励他们。激励他们的方法不是给他们更多工作,而是给他们一个新的技能或在团队里