Looking at this simple hello world html page
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<title>Hello World</title>
</head>
<body>
<div id="app">
Message is {{ message }}
</div>
<script>
new Vue({
el: "#app",
data: {
message: "Hello World!"
}
})
</script>
</body>
</html>
When served as a static page it will show the Message is Hello World!
text on the page. If I add a render
function to the Vue declaration
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<title>Hello World</title>
</head>
<body>
<div id="app">
Message is {{ message }}
</div>
<script>
new Vue({
el: "#app",
data: {
message: "Hello World!"
},
render: function (h) {
return h("p", "Rendered " + this.message);
}
})
</script>
</body>
</html>
It will show Rendered Hello World!
inside a <p>
element, erasing whatever was present inside the <div>
element. Now my question is, what if I want the render function to perform the default rendering under certain conditions, ie. show the Message is Hello World!
text? Something like
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<title>Hello World</title>
</head>
<body>
<div id="app">
Message is {{ message }}
</div>
<script>
new Vue({
el: "#app",
data: {
message: "Hello World!"
},
render: function (h) {
if (this.message === "Hello World!") {
/* do something to make the render function fallback to default rendering? */
} else {
return h("p", "Rendered " + this.message);
}
}
})
</script>
</body>
</html>
I'm aware that I can achieve this kind of effects in different ways , I'm just wondering if it's possible to tell Vue to revert back to the default fallback rendering mechanism inside the render function, or not?
====== EDIT ======
Just to clarify some more, I'm NOT looking for solutions like this
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<title>Hello World</title>
</head>
<body>
<div id="app">
Message is {{ message }}
</div>
<script>
new Vue({
el: "#app",
data: {
message: "Hello World!"
},
render: function (h) {
if (this.message === "Hello World!") {
return h("p", "Message is " + this.message);
} else {
return h("p", "Rendered " + this.message);
}
}
})
</script>
</body>
</html>
I'm wondering if somehow you can halt the render function without returning any rendered content and make Vue to show the default rendering like there's no render function declared at all.
You could compile the template string yourself. It can be accessed by instance property $el.innerHTML
. Then you could call Vue.compile
to compile the template string.
More about compile: https://v2.vuejs.org/v2/api/#Vue-compile
Somethink like this:
if (this.message === 'Hello World!') {
return Vue.compile(this.$el.outerHTML).render.call(this, h)
/* do something to make the render function fallback to default rendering? */
}
I put together something for a vue 2 app I'm working on by investigating how Vue internally handles rendering
Used https://github.com/vuejs/vue/blob/dev/src/core/instance/render.js as reference
created () {
const baseRender = this.$options.render;
this.$options.render = function (h) {
if (this.SOME_LOADING_CONDITION_FOR_EXAMPLE === 0) {
return h("h1", "Loading...")
}
return baseRender.call(this._renderProxy, h)
}
}
Note: Even though it is calling vm.$options.render
, the component doesn't need to have a custom render function for this to work, it works with components with a template
I developed a replacement by modifying this.$.render
on the fly then calling $forceUpdate()
(is necessary to call this otherwise it will be stuck on the initial replacement value)
async created() {
const renderBackup = this.$.render;
this.$.render = function () {
return h("div", {key: Symbol()}, "Loading component")
}
try {
await someAsyncOperation();
this.$.render = renderBackup;
this.$forceUpdate();
} catch (error) {
this.$.render = function () {
return h("div", {key: Symbol()}, "Problem loading component")
}
this.$forceUpdate();
throw error;
}
}
$forceUpdate
and replacing the function, you can also use a data property and check for the loading state inside the render function to return different elements. I tested it and it works.Unhandled error during execution of scheduler flush. This is likely a Vue internals bug
Unhandled error during execution of scheduler flush. This is likely a Vue internals bug
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.