Javascript 错误:模板应该只负责将状态映射到 UI。避免在模板中放置带有副作用的标签,例如 <script>

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38119088/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 21:06:37  来源:igfitidea点击:

Error: Templates should only be responsible for mapping the state to the UI. Avoid placing tags with side-effects in your templates, such as <script>

javascriptdjangodjango-templatesvue.js

提问by Raj Subit

I am using Vuejs and I keep getting this warning in the console. Also no data is loaded because of this warning. I checked the code for unwanted tags but did not find any.

我正在使用 Vuejs,并且在控制台中不断收到此警告。由于此警告,也没有加载数据。我检查了不需要的标签的代码,但没有找到。

Is this because of the javascript code or I have something wrong in my html?

这是因为 javascript 代码还是我的 html 有问题?

Here is my code:

这是我的代码:

HTML

HTML

<div class="row">
    <div class="col-sm-12" style="margin-top: 20px;">
        <form class="form-inline" method="GET" action=".">
            <div class="col-sm-3" style="float: right;"><h4>Date:</h4>
                <input class="form-control" style="padding-bottom:0px;" type="text" id="datepicker" readonly="true" name="date" value="2016-06-30">
                <input type="submit" class="btn btn-primary btn-sm" value="Submit" >
            </div>

        </form>
        <div class="col-sm-2" style="float: right; margin-top:40px;">
            <button class="btn btn-info" type="button" id="csv_export">Click to Export</button>
        </div>
    </div>
    <div class="col-sm-12" style="margin:20px;">
        <table class="table table-sm table-striped table-bordered" id="absent-list">
            <thead>
                <tr>
                    <th>#</th>
                    <th style="text-align: center; font-size: 15px;">Full Name</th>
                    <th style="text-align: center; font-size: 15px;">Section</th>
                    <th style="text-align: center; font-size: 15px;">Person Called</th>
                    <th style="text-align: center; font-size: 15px;">Person Relation</th>
                    <th style="text-align: center; font-size: 15px;">Phone Number</th>
                    <th style="text-align: center; font-size: 15px;">Absent Reason</th>
                    <th style="text-align: center; font-size: 15px;">Remarks</th>
                    <th></th>
                </tr>
            </thead>
            <tbody>
                <tr v-show="loading" class="text-center">
                    <td colspan="7">
                        <i class="fa fa-spinner fa-spin fa-4x"></i>
                    </td>
                </tr>
                <tr v-for="record in absent_followback_records">

                    <td style="text-align: center; font-size: 15px;" scope="row"> {{$index + 1}}</td>
                    <td  style="text-align: center; font-size: 15px;">{{record.student_name}}</td>
                    <td  style="text-align: center; font-size: 15px;">{{record.student_section}}</td>
                    <td  style="text-align: center;">{{record.person_called}}</td>
                    <td  style="text-align: center;">{{record.person_relation}}</td>
                    <td  style="text-align: center;">{{record.phone_number}}</td>
                    <td  style="text-align: center;">{{record.absent_reason_name}}</td>
                    <td  style="text-align: center;">{{record.remarks}}</td>
                    <td  style="text-align: center;"><a href="#" v-on:click="editAbsentFollowbackRecord($index)" data-toggle="modal" data-target="#absent-followback-edit"> Edit </a></td>

                </tr>
            </tbody>
        </table>

    </div>
</div>

<script src="/static/js/jquery-ui.min.js"></script>
<script src="/static/js/jquery.plugin.min.js"></script> 
<script src="/static/js/jquery.datepick.min.js"></script>
<script src="https://cdn.jsdelivr.net/vue/latest/vue.js"></script>
<script src="/static/js/csrftoken.js"></script>
<script src="/static/js/jquery.TableCSVExport.js"></script>

<script type="text/javascript">

    var absentFollowbackListAPiUrl = "/student/api/absent/followback/list/11/";
    var absent_reason = jQuery.parseJSON('[{"model": "studentprofile.absentreason", "pk": 1, "fields": {"created": "2016-05-08T06:09:42.410Z", "modified": "2016-05-08T06:09:42.410Z", "reason_name": "sick"}}, {"model": "studentprofile.absentreason", "pk": 2, "fields": {"created": "2016-05-08T06:09:42.416Z", "modified": "2016-05-08T06:09:42.416Z", "reason_name": "arrived late"}}, {"model": "studentprofile.absentreason", "pk": 3, "fields": {"created": "2016-05-08T06:09:42.419Z", "modified": "2016-05-08T06:09:42.419Z", "reason_name": "work at home"}}, {"model": "studentprofile.absentreason", "pk": 4, "fields": {"created": "2016-05-08T06:09:42.423Z", "modified": "2016-05-08T06:09:42.423Z", "reason_name": "public holiday"}}]');
    var profile_value = false;

</script>
<script type="text/javascript" src="/static/js/student/student-followback.js"></script>

absent-followback.js file

缺席-followback.js 文件

$(function() {
    $( "#datepicker" ).datepick({dateFormat: 'yyyy-mm-dd'});
});

$('#csv_export').click(function (e) {
    e.preventDefault();
    $('#absent-list').TableCSVExport({
        delivery: 'download',
        filename: 'absent-list(' + $( "#datepicker" ).val() + ').csv'
    });
});

var vm = new Vue({
        el: 'body',
        data: {
            absent_followback_records: [],
            followbackRecordIndex: 'off',
            absentReasonList: absent_reason,
            loading: false,
            currentData: {},
            profile: profile_value,
            listApiUrl: absentFollowbackListAPiUrl
        },
        methods: {
            populateData: function(api_url){
                var self = this;
                $.get(api_url, function(data){
                    self.absent_followback_records = data;
                    self.loading = false;
                });
            },
            getAbsentFollowbackRecord: function () {
                var self = this;
                self.loading = true;
                var date = $( "#datepicker" ).val();
                var api_url = self.listApiUrl + '?date=' + date;
                self.populateData(api_url);
            },
            getProfileAbsentFollowbackRecord: function (event) {
                var self = this;
                self.loading = true;
                var expanded = $(event.target).attr('aria-expanded');
                if (expanded == 'false'){
                    $(event.target).html('Hide Details');
                    var studentId = $(event.target).attr('studentId');
                    var api_url = self.listApiUrl + '?student_id=' + studentId;
                    self.populateData(api_url);
                }
                else{
                    $(event.target).html('Show Details');
                }
            },
            editAbsentFollowbackRecord: function (followbackRecordIndex) {
                var self = this;
                self.currentData = self.absent_followback_records[followbackRecordIndex];
                self.followbackRecordIndex = followbackRecordIndex;
            },
            updateAbsentFollowbackRecord: function (followbackRecordIndex){
                var self = this;
                var updateData = self.currentData;
                var absent_date = updateData.date;
                var student_id = updateData.student;
                var post_url = updateData.update_url;
                var person_called = updateData.person_called;
                var person_relation = updateData.person_relation;
                var phone_number = updateData.phone_number;
                var absent_reason = updateData.absent_reason;
                var remarks = updateData.remarks;
                if (person_called){
                    var data = {
                        student: parseInt(student_id),
                        date: absent_date,
                        person_called: person_called,
                        person_relation: person_relation,
                        phone_number: phone_number,
                        absent_reason: parseInt(absent_reason),
                        remarks: remarks
                    };
                    $('#updateAbsentFollowback').html('<i class="fa fa-spinner fa-spin"></i> Saving').attr('class', 'btn btn-primary disabled');
                    $.ajax({
                        url: post_url,
                        type: "PUT",
                        data: JSON.stringify(data),
                        dataType: 'json',
                        contentType: "application/json",
                        success: function(responseData) {
                            $('#updateAbsentFollowback').html('Save').attr('class', 'btn btn-success');
                            if (self.profile == true){
                                api_url = self.listApiUrl + '?student_id=' + student_id;
                                self.populateData(api_url);
                            }
                            else{
                                self.getAbsentFollowbackRecord();
                            }
                        },
                        error: function( xhr, status, errorThrown ) {
                        console.log(errorThrown);
                        }
                    });
                }
            }

        },
        ready() {
            if (this.profile != true){
                this.getAbsentFollowbackRecord();
            }
        }
    })

回答by Poode

You can use script tag in this way and it will work fine. I was facing the same problem when I used <script></script>tag without specifying its type. After using the type attribute Vue did not warn me for critical error:

您可以通过这种方式使用脚本标签,它会正常工作。当我使用<script></script>标签而不指定其类型时,我遇到了同样的问题。使用 type 属性后,Vue 没有警告我严重错误:

<script type="application/javascript"> 
    // your code
</script>

回答by gurghet

I think the answer is in you question title. Just get rid of all the <script>tags in the template, put them outside of the template.

我认为答案就在您的问题标题中。只需去掉<script>模板中的所有标签,将它们放在模板之外。

In this case you are using bodyas the template and you areputting scripts inside your template (body)

在这种情况下,你正在使用body的模板,你把你的脚本模板中(body

The easy solution is to change the el: 'body'to el: '#wrapper'and edit your html to

简单的解决方案是更改el: 'body'el: '#wrapper'并将您的 html 编辑为

<body>
<div id="wrapper">
...
</div>
<script ... >
<script ... >
</body>

回答by innominata

Make sure you have a closing tag on your root element. I just spent the last 6 hours systematically removing things and pulling my hair out. Turns out I had deleted my closing at some point and Vue was interpreting

确保您的根元素上有一个结束标记。在过去的 6 个小时里,我只是系统地去除东西并拔掉头发。结果我在某个时候删除了我的结束语,Vue 正在解释

回答by Rm558

a pair of mismatch tags (div, span) can cause this error.

一对不匹配的标签(div、span)会导致这个错误。

<div id="app">
    <div>{{ a }} </span>
</div>

回答by Hlib Liapota

It is because of script tag in your app scope. In my case it was because of google captcha that was in my scope. Google captcha iframe contains script tag

这是因为您的应用程序范围内的脚本标记。就我而言,这是因为谷歌验证码在我的范围内。谷歌验证码 iframe 包含脚本标签

回答by Erutan409

My suggestion is a little specific, as I'm using Vue JS v2 in conjunction with jQuery v3.

我的建议有点具体,因为我将 Vue JS v2 与 jQuery v3 结合使用。

I'm using jQuery to load the instance of my application with something simple like this:

我正在使用 jQuery 来加载我的应用程序的实例,就像这样简单:

$(() => {

  new Vue({
    name: 'MyApp',
    el: '#app' // which is my main HTML element for my entire page app
  });

});

So, this won't initiate until the entire document is loaded.

因此,在加载整个文档之前,这不会启动。

In my footer, I'm changing any offending script tags with this before the entire document is loaded, but after my closing main HTML tag:

在我的页脚中,在加载整个文档之前,但在关闭主 HTML 标记之后,我正在更改任何有问题的脚本标记:

$('main script:not([type="application/javascript"])').attr('type', 'application/javascript');

This did the trick for me without having to parse any output from offending tags and doing anything more extravagant.

这对我来说很有用,而不必解析来自违规标签的任何输出,也不必做任何更奢侈的事情。

This can be extrapolated out, using the native document selectors if you're not using jQuery, like my example.

如果您不使用 jQuery,则可以使用本机文档选择器推断出这一点,就像我的示例一样。