Closed viettranme closed 7 years ago
Your template needs to be syntax valid HTML, so escape chars like < or > in attribute values.
<ajax-url> is just a placeholder for this example. It will be an actual URL.
The problem is that content loaded from this URL contains javascript code, and it causes Vue error.
Then you need to provide a repro. You didn't explain what the code is doing clearly.
Hello Evan,
My sample index.html file as following:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="https://code.jquery.com/jquery-3.2.0.min.js"></script>
<script type="text/javascript" src="https://vuejs.org/js/vue.js"></script>
</head>
<body>
<div id="app">
Hello <span v-text="item.NAME"></span>
<async-example></async-example>
</div>
<script type="text/javascript">
$(function() {
Vue.component('async-example', function (resolve, reject) {
$.ajax({
url: 'async.html',
method: 'GET',
dataType: 'html'
}).done(function(data) {
resolve({
template: data
})
});
})
new Vue({
el: '#app',
data: {
item: {NAME: 'VueJS'},
},
})
});
</script>
</body>
</html>
The file async.html:
<div>
<h1>Hello</h1>
<script type='text/javascript'>
console.log('Hello')
</script>
</div>
I got the following error on Chrome's console:
[Vue warn]: Error compiling template:
<div>
<h1>Hello</h1>
<script type='text/javascript'>
console.log('Hello')
</script>
</div>
- Templates should only be responsible for mapping the state to the UI. Avoid placing tags with side-effects in your templates, such as <script>, as they will not be parsed.
(found in <AsyncExample>)
Regards, Viet
The warning is pretty clear - you should not embed scripts in templates because of how templates work in Vue. You can however programmatically create <script>
tags in the component's created hook.
Suppose that we in a situation that: (1) we don't have control over the remote contents; (2) the remote contents may contain script tags; (3) we just want to load remote contents and show them as widgets inside the '#app' div element.
Can we achieve the above purpose with Vue?
@viettranme if the remote content is not Vue template (i.e. no bindings, no directives), then you can just use innerHTML
. Although it needs to be trusted content to avoid XSS.
I have moved the remote content loading part to the mounted() callback and things work now.
Thanks Evan.
I am migrating some legacy apps to Vuejs and I came across a form like this:
<script src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="{{ key }}"
data-description="A Flask Charge"
data-amount="500"
data-locale="auto"></script>
</form>
It's an example from this guide: https://stripe.com/docs/checkout/flask
Vue breaks this form, yes with nice a nice warning which I am grateful for :) but it would nice if there was a way to ask Vue to skip over some tags for us.
However, I'll try the workaround suggested above.
@zero-master @viettranme
You can add script tags using jquery or document.createElement
Here is a workaround which I use.
let stripScriptTag = $('<script>');
stripScriptTag.attr('class', 'stripe-button');
stripScriptTag.attr('src', 'https://checkout.stripe.com/checkout.js');
stripScriptTag.attr('data-key', 'pk_test_xxxxxxxxxxxxxxx');
stripScriptTag.attr('data-amount', '1999');
stripScriptTag.attr('data-name', 'Stripe Demo');
stripScriptTag.attr('data-description', 'Online course about integrating Stripe');
stripScriptTag.attr('data-image', 'https://stripe.com/img/documentation/checkout/marketplace.png');
stripScriptTag.attr('data-locale', 'auto');
stripScriptTag.attr('data-currency', 'usd');
$('#formStrip').html(stripScriptTag);
@zero-master @viettranme
Another option is to detach element with script before vue initialization and then reattach it after vue init. It will be helpful if you have two or more inline scripts which depends on each other.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="https://code.jquery.com/jquery-3.2.0.min.js"></script>
<script type="text/javascript" src="https://vuejs.org/js/vue.js"></script>
</head>
<body>
<div id="app">
Hello <span v-text="item.NAME"></span>
<div id="problem-script">
<script type="text/javascript" src="problem.js"></script>
</div>
</div>
<script type="text/javascript">
let script = $('#problem-script').children().detach();
new Vue({
el: '#app',
data: {
item: {NAME: 'VueJS'},
},
});
$('#problem-script').append(script);
</script>
</body>
</html>
What problem does this feature solve?
My sample app structure look like
The issue is that Vue throws an error as the asyn content loaded from 'ajax-url' contains 'script' tag. Is there any way to let Vue skip parsing/binding the '.middle' part?
What does the proposed API look like?
Support a special directive like 'v-skip'