Javascript 如何在使用Vue提交表单时禁用window.onbeforeunload?

Javascript 如何在使用Vue提交表单时禁用window.onbeforeunload?,javascript,laravel,vue.js,vuejs2,Javascript,Laravel,Vue.js,Vuejs2,我有一个名为countdowntimer.vue的组件,它显然只是一个倒计时器,我将它用于在线考试页面,我想在窗口对象上应用一个onbeforeunload事件,但我也希望计时器在完成后自动提交,而不会被该窗口事件中断,我尝试将代码放入vuejs组件中,但它没有响应,或者它不允许我在不中断的情况下提交,或者它根本不起作用,让任何事件在不中断的情况下离开页面 下面是倒计时计时器的代码: <template> <div> <div v-if="f

我有一个名为countdowntimer.vue的组件,它显然只是一个倒计时器,我将它用于在线考试页面,我想在窗口对象上应用一个
onbeforeunload
事件,但我也希望计时器在完成后自动提交,而不会被该窗口事件中断,我尝试将代码放入vuejs组件中,但它没有响应,或者它不允许我在不中断的情况下提交,或者它根本不起作用,让任何事件在不中断的情况下离开页面

下面是倒计时计时器的代码:

<template>
    <div>
        <div v-if="finished" v-text="expiredText"></div>

        <div v-else>
            <span>{{ remaining.minutes }} Minutes, </span>
            <span>{{ remaining.seconds }} Seconds</span>
            left...
        </div>
    </div>
</template>

<script>
    import moment from 'moment';
    export default {
        props: {
            until: { default: 600000},
            expiredText: { default: 'TIME IS UP' }
        },
        data () {
            return { limiter: this.until * 10000};
        },
        created () {
            this.refreshEverySecond();
            document.addEventListener('beforeunload', this.redirect());
        },
        computed: {
            finished () {
                return this.remaining.total <= 0;
            },
            remaining () {
                let remaining = moment.duration(this.limiter);
                if (remaining <= 0) this.$emit('finished');
                return {
                    total: remaining,
                    minutes: remaining.minutes(),
                    seconds: remaining.seconds()
                };
            },
        },
        methods: {
            refreshEverySecond () {
                let interval = setInterval(() => this.limiter = this.limiter - 1000, 1000);
                this.$on('finished', () => clearInterval(interval));
                this.$on('finished', () => this.timeUp());
            },

            timeUp() {
                const form = document.querySelector('[data-form-submit]');
                const radios = document.querySelectorAll('input[type=radio]');
                radios.forEach(radio => radio.style.display = 'none');
                form.submit(function(e) {
                    console.log(e);
                });
            },
            redirect () {
                // if(this.$on('finished')) {
                    // console.log(this.finished)
                    // window.onbeforeunload = function() {
                    //     return "Do you really want to leave our brilliant application?";
                    // };
                // }
                // console.log(this.finished())
                // return;
            }
        },
    }
</script>

{{剩余的.minutes}}}分钟,
{{剩余的.seconds}}}秒
左边
从“力矩”中导入力矩;
导出默认值{
道具:{
直到:{default:600000},
expiredText:{default:'时间到了'}
},
数据(){
返回{limiter:this.until*10000};
},
创建(){
这个。刷新每秒钟();
document.addEventListener('beforeunload',this.redirect());
},
计算:{
完成(){
返回此.remaining.total clearInterval(interval));
this.on('finished',()=>this.timeUp());
},
timeUp(){
const form=document.querySelector(“[data form submit]”);
const radios=document.querySelectorAll('input[type=radio]');
radios.forEach(radio=>radio.style.display='none');
表格提交(功能(e){
控制台日志(e);
});
},
重定向(){
//如果(此.$on('finished')){
//console.log(this.finished)
//window.onbeforeunload=函数(){
//return“您真的想离开我们出色的应用程序吗?”;
// };
// }
//console.log(this.finished())
//返回;
}
},
}
我曾尝试将该方法设置为计算属性,并使用不同的if语句作为观察者,但它并没有像我上面提到的那样工作

这是我正在使用的刀片模板

@extends('layouts.app')

@section('content')
    <div class="container">
        <div class="row">
            <div class="col-md-6 col-md-offset-3">
                <form method="POST" onsubmit="clicked()" data-form-submit>
                    {{ csrf_field() }}
                    <div class="panel panel-danger">
                        <div class="panel-heading">
                            {{ $quiz->quiz_name }}
                        </div>
                        <div class="panel-body">
                            <ol>
                                @foreach($quiz->questions as $index => $question)
                                    <li><h4>{{ $question->title }} ? </h4></li>
                                    <ul>
                                        <div class="flex-align-baseline">
                                            <li>{{$question->option_1}}</li>
                                            <input type="radio" name="{{$index}}" value="{{ $question->option_1 }}">
                                            <hr>
                                        </div>
                                        <div class="flex-align-baseline">
                                            <li>{{$question->option_2}}</li>
                                            <input type="radio" name="{{$index}}" value="{{ $question->option_2 }}">
                                            <hr>
                                        </div>
                                        <div class="flex-align-baseline">
                                            <li>{{$question->option_3}}</li>
                                            <input type="radio" name="{{$index}}" value="{{ $question->option_3 }}">
                                            <hr>
                                        </div>
                                        <div class="flex-align-baseline">
                                            <li>{{$question->option_4}}</li>
                                            <input type="radio" name="{{$index}}" value="{{ $question->option_4 }}">
                                            <hr>
                                        </div>
                                    </ul>
                                    <hr>
                                @endforeach
                            </ol>
                            <input type="submit" class="btn btn-success" onclick="clicked()" value="Submit">
                        </div>
                    </div>
                </form>
            </div>
            <timer :until="{{ count($quiz->questions) }}" class="countdown col-md-3"></timer>
        </div>
    </div>

@endsection

<script>

let submitForm = false;
function clicked() {
    submitForm = true;
}
window.onbeforeunload = function(e) {
    if (submitForm) {
        return null;
    }
    return "Do you really want to leave our brilliant application?";
};
</script>
@extends('layouts.app'))
@节(“内容”)
{{csrf_field()}}
{{$quick->quick_name}
@foreach($quick->questions as$index=>$question)
  • {{$question->title}
    • {{$question->option_1}

    • {{$question->option_2}

    • {{$question->option_3}

    • {{$question->option_4}


    @endforeach @端部 让submitForm=false; 函数单击(){ submitForm=true; } window.onbeforeunload=函数(e){ if(提交格式){ 返回null; } return“您真的想离开我们出色的应用程序吗?”; };

  • 正如您所看到的,我在
    @endsection
    之外有一个脚本标记,我了解到您可能无法做到这一点,它不会连接到刀片模板本身的任何元素,我试图像在vue组件中那样抓取表单对象,但它返回null或未定义,我记不得了,您不能将事件侦听器附加到undefined,但如果我在浏览器的控制台中运行与预期相同的逻辑,则表单上的
    onsubmit=“
    事件不会到达底部的脚本标记,因为某种原因,
    submitForm
    变量的值不会更改,但奇怪的是,如果我手动单击submit按钮,它确实会触发函数
    clicked()
    ,因此我在这里非常困惑,我不知道我是否可以用vue实现这一点,如果不能,我不知道为什么
    onsubmit=“”
    事件不起作用,当然,我不能移动
    @部分中的脚本标记,因为vue会嘎嘎作响,如果您知道我应该如何处理这段代码,我将不胜感激。

    首先,您应该在卸载
    之前将方法引用传递给
    ,而不是调用该方法的结果。因此,请删除
    ()

    现在,启用/禁用处理程序的一个简单解决方案是只添加一个标志:

        data () {
            return {
                limiter: this.until * 10000
                preventSubmit: true
            };
        },
    
    并且,在您的方法中,更新/使用该标志:

        methods: {
            // ...
            timeUp() {
                this.preventSubmit = false; // ALLOW redirect now
    
                const form = document.querySelector('[data-form-submit]');
                const radios = document.querySelectorAll('input[type=radio]');
                radios.forEach(radio => radio.style.display = 'none');
                form.submit(function(e) {
                    console.log(e);
                });
            },
            redirect () {
                if (this.preventSubmit) {
                   // do your thing to prevent submit
                }
            }
        },
    
    可供替代的 或者,您可以删除侦听器:

    created () {
        this.refreshEverySecond();
        document.addEventListener('beforeunload', this.redirect); // not this.redirect()
    },
    
    以及:

    但我认为国旗的选择更安全

    created () { this.refreshEverySecond(); document.addEventListener('beforeunload', this.redirect); // not this.redirect() },

    methods: {
        // ...
        timeUp() {
            document.removeEventListener('beforeunload', this.redirect);
            // ...