类别过滤器无限循环警告 Vue JS
Category Filter Infinite Loop Warning Vue JS
我有一个应用程序可以根据程序和类型过滤事件。应用程序按预期运行,但我收到错误消息“您可能在组件渲染函数中有一个无限更新循环”。我认为问题可能出在我的 noEvents computed 属性 但我不确定如何解决。
// List of events
const events = [{
month: 'January',
monthEvents: [{
type: 'Type 1',
program: 'Program 2',
visible: true
},
{
type: 'Type 2',
program: 'Program 1',
visible: true
},
{
type: 'Type 2',
program: 'Program 2',
visible: true
},
{
type: 'Type 1',
program: 'Program 4',
visible: true
}
]
},
{
month: 'February',
monthEvents: [{
type: 'Type 4',
program: 'Program 2',
visible: true
},
{
type: 'Type 2',
program: 'Program 1',
visible: true
},
{
type: 'Type 3',
program: 'Program 3',
visible: true
},
{
type: 'Type 3',
program: 'Program 4',
visible: true
}
]
}
]
new Vue({
el: '#app',
data: {
monthCounter: 0,
allEvents: events,
filteredTypes: [],
filteredPrograms: []
},
methods: {
increaseMonthCounter: function () {
// Increases the month counter by 1
this.filteredTypes = [];
this.filteredPrograms = [];
this.monthCounter++;
if (this.monthCounter > this.allEvents.length - 1) {
this.monthCounter = 0;
}
},
decreaseMonthCounter: function () {
// Decreases the month counter by 1
this.filteredTypes = [];
this.filteredPrograms = [];
this.monthCounter--;
if (this.monthCounter == -1) {
this.monthCounter = this.allEvents.length - 1;
}
},
filterEvents: function (event) {
//Loops through each event and checks multiple conditions to display or hide event.
// If there is nothing filtered show all events
if (this.filteredTypes.length === 0 && this.filteredPrograms.length === 0) {
event.visible = true;
return true;
}
// If a type is selected and no program is selected show all types
if (this.filteredTypes.includes(event.type) && this.filteredPrograms.length === 0) {
event.visible = true;
return true;
} else {
event.visible = false;
}
// If a program is selected and no type is selected show all programs
if (this.filteredPrograms.includes(event.program) && this.filteredTypes.length === 0) {
event.visible = true;
return true;
} else {
event.visible = false;
}
// If selection matches events type and program show event
if (this.filteredPrograms.includes(event.program) && this.filteredTypes.includes(event.type)) {
event.visible = true;
return true;
} else {
event.visible = false;
}
}
},
computed: {
currentMonth: function () {
//Gets the currrent month
return events[this.monthCounter].month;
},
availableMonthEvents: function () {
// Gets the current month's events
return events[this.monthCounter].monthEvents;
},
noEvents: function () {
// Checks if there are no events available
for (let i = 0; i < this.availableMonthEvents.length; i++){
if (this.availableMonthEvents[i].visible == true) {
return false;
}
}
return true;
},
availableTypes: function () {
// List out the available types and strips out the duplicates
const availableTypes = [];
events[this.monthCounter].monthEvents.forEach((item) => {
if (!availableTypes.includes(item.type)) {
availableTypes.push(item.type);
}
});
return availableTypes;
},
availablePrograms: function () {
// List out the available programs and strips out the duplicates
const availablePrograms = [];
events[this.monthCounter].monthEvents.forEach((item) => {
if (!availablePrograms.includes(item.program)) {
availablePrograms.push(item.program);
}
});
return availablePrograms;
}
}
});
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
<title>Hello, world!</title>
</head>
<body>
<div class="container my-5">
<div id="app">
<h3>{{currentMonth}}</h3>
<strong>Types:</strong>
<div class="form-check form-check-inline" v-for="type in availableTypes">
<input class="form-check-input" type="checkbox" id="inlineCheckbox1" :value="type" v-model="filteredTypes">
<label class="form-check-label" for="inlineCheckbox1">{{type}}</label>
</div>
<br>
<strong>Programs:</strong>
<div class="form-check form-check-inline" v-for="program in availablePrograms">
<input class="form-check-input" type="checkbox" id="inlineCheckbox1" :value="program" v-model="filteredPrograms">
<label class="form-check-label" for="inlineCheckbox1">{{program}}</label>
</div>
<p class="mt-3">
<button class="btn btn-danger" @click="decreaseMonthCounter()">Down</button>
<button class="btn btn-success" @click="increaseMonthCounter()">Up</button>
</p>
<ol class="mt-3" id="event-container">
<li class="event" v-if="filterEvents(event)" v-for="event in availableMonthEvents">
<strong>Type:</strong> {{event.type}} - <strong>Program:</strong> {{event.program}}
</li>
<li v-if="noEvents">
There are no events!
</li>
</ol>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="app.js"></script>
</body>
</html>
我认为问题可能出在您的 filterEvents
方法以及您如何在页面上呈现事件
v-if
和 v-for
等两个指令不应放在单个 html 元素上。
我认为 Vue 试图做的是:
尝试呈现事件 => 看到 v-if 指令 => 运行 filterEvents => 修改事件 => 尝试再次呈现事件(因为事件是数组的一部分,所以数组被认为已修改)= > ...
不要改变 v-if
检查中的任何数据。
可能的解决方案
实施 filteredEvents 计算 属性,这将 return 数组有条件地过滤。
这些文档可以提供帮助:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
我能够通过使用计算的属性过滤我的列表来解决我的问题。
// List of events
const events = [{
month: 'January',
monthEvents: [{
type: 'Type 1',
program: 'Program 2'
},
{
type: 'Type 2',
program: 'Program 1'
},
{
type: 'Type 2',
program: 'Program 2'
},
{
type: 'Type 1',
program: 'Program 4'
}
]
},
{
month: 'February',
monthEvents: [{
type: 'Type 4',
program: 'Program 2'
},
{
type: 'Type 2',
program: 'Program 1'
},
{
type: 'Type 3',
program: 'Program 3'
},
{
type: 'Type 3',
program: 'Program 4'
}
]
}
]
new Vue({
el: '#app',
data: {
monthCounter: 0,
allEvents: events,
filteredTypes: [],
filteredPrograms: []
},
methods: {
increaseMonthCounter: function () {
// Increases the month counter by 1
this.filteredTypes = [];
this.filteredPrograms = [];
this.monthCounter++;
if (this.monthCounter > this.allEvents.length - 1) {
this.monthCounter = 0;
}
},
decreaseMonthCounter: function () {
// Decreases the month counter by 1
this.filteredTypes = [];
this.filteredPrograms = [];
this.monthCounter--;
if (this.monthCounter == -1) {
this.monthCounter = this.allEvents.length - 1;
}
}
},
computed: {
currentMonth: function () {
//Gets the currrent month
return events[this.monthCounter].month;
},
availableMonthEvents: function () {
// Gets the current month's events
return events[this.monthCounter].monthEvents;
},
filteredEvents: function () {
let filteredEvents = this.availableMonthEvents.filter((item) => {
// If there is nothing filtered show all events
if (this.filteredTypes.length === 0 && this.filteredPrograms.length === 0) {
return true;
}
// If a type is selected and no program is selected show all types
if (this.filteredTypes.includes(item.type) && this.filteredPrograms.length === 0) {
return true;
}
// If a program is selected and no type is selected show all programs
if (this.filteredPrograms.includes(item.program) && this.filteredTypes.length === 0) {
return true;
}
// If selection matches events type and program show event
if (this.filteredPrograms.includes(item.program) && this.filteredTypes.includes(item.type)) {
return true;
}
});
return filteredEvents;
},
availableTypes: function () {
// List out the available types and strips out the duplicates
const availableTypes = [];
events[this.monthCounter].monthEvents.forEach((item) => {
if (!availableTypes.includes(item.type)) {
availableTypes.push(item.type);
}
});
return availableTypes;
},
availablePrograms: function () {
// List out the available programs and strips out the duplicates
const availablePrograms = [];
events[this.monthCounter].monthEvents.forEach((item) => {
if (!availablePrograms.includes(item.program)) {
availablePrograms.push(item.program);
}
});
return availablePrograms;
}
}
});
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
<title>Hello, world!</title>
</head>
<body>
<div class="container my-5">
<div id="app">
<h3>{{currentMonth}}</h3>
<strong>Types:</strong>
<div class="form-check form-check-inline" v-for="type in availableTypes">
<input class="form-check-input" type="checkbox" id="inlineCheckbox1" :value="type" v-model="filteredTypes">
<label class="form-check-label" for="inlineCheckbox1">{{type}}</label>
</div>
<br>
<strong>Programs:</strong>
<div class="form-check form-check-inline" v-for="program in availablePrograms">
<input class="form-check-input" type="checkbox" id="inlineCheckbox1" :value="program" v-model="filteredPrograms">
<label class="form-check-label" for="inlineCheckbox1">{{program}}</label>
</div>
<p class="mt-3">
<button class="btn btn-danger" @click="decreaseMonthCounter()">Down</button>
<button class="btn btn-success" @click="increaseMonthCounter()">Up</button>
</p>
<ol class="mt-3">
<li class="event" v-for="event in filteredEvents">
<strong>Type:</strong> {{event.type}} - <strong>Program:</strong> {{event.program}}
</li>
<li v-if="filteredEvents.length == 0">
There are no events!
</li>
</ol>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="app.js"></script>
</body>
</html>
我有一个应用程序可以根据程序和类型过滤事件。应用程序按预期运行,但我收到错误消息“您可能在组件渲染函数中有一个无限更新循环”。我认为问题可能出在我的 noEvents computed 属性 但我不确定如何解决。
// List of events
const events = [{
month: 'January',
monthEvents: [{
type: 'Type 1',
program: 'Program 2',
visible: true
},
{
type: 'Type 2',
program: 'Program 1',
visible: true
},
{
type: 'Type 2',
program: 'Program 2',
visible: true
},
{
type: 'Type 1',
program: 'Program 4',
visible: true
}
]
},
{
month: 'February',
monthEvents: [{
type: 'Type 4',
program: 'Program 2',
visible: true
},
{
type: 'Type 2',
program: 'Program 1',
visible: true
},
{
type: 'Type 3',
program: 'Program 3',
visible: true
},
{
type: 'Type 3',
program: 'Program 4',
visible: true
}
]
}
]
new Vue({
el: '#app',
data: {
monthCounter: 0,
allEvents: events,
filteredTypes: [],
filteredPrograms: []
},
methods: {
increaseMonthCounter: function () {
// Increases the month counter by 1
this.filteredTypes = [];
this.filteredPrograms = [];
this.monthCounter++;
if (this.monthCounter > this.allEvents.length - 1) {
this.monthCounter = 0;
}
},
decreaseMonthCounter: function () {
// Decreases the month counter by 1
this.filteredTypes = [];
this.filteredPrograms = [];
this.monthCounter--;
if (this.monthCounter == -1) {
this.monthCounter = this.allEvents.length - 1;
}
},
filterEvents: function (event) {
//Loops through each event and checks multiple conditions to display or hide event.
// If there is nothing filtered show all events
if (this.filteredTypes.length === 0 && this.filteredPrograms.length === 0) {
event.visible = true;
return true;
}
// If a type is selected and no program is selected show all types
if (this.filteredTypes.includes(event.type) && this.filteredPrograms.length === 0) {
event.visible = true;
return true;
} else {
event.visible = false;
}
// If a program is selected and no type is selected show all programs
if (this.filteredPrograms.includes(event.program) && this.filteredTypes.length === 0) {
event.visible = true;
return true;
} else {
event.visible = false;
}
// If selection matches events type and program show event
if (this.filteredPrograms.includes(event.program) && this.filteredTypes.includes(event.type)) {
event.visible = true;
return true;
} else {
event.visible = false;
}
}
},
computed: {
currentMonth: function () {
//Gets the currrent month
return events[this.monthCounter].month;
},
availableMonthEvents: function () {
// Gets the current month's events
return events[this.monthCounter].monthEvents;
},
noEvents: function () {
// Checks if there are no events available
for (let i = 0; i < this.availableMonthEvents.length; i++){
if (this.availableMonthEvents[i].visible == true) {
return false;
}
}
return true;
},
availableTypes: function () {
// List out the available types and strips out the duplicates
const availableTypes = [];
events[this.monthCounter].monthEvents.forEach((item) => {
if (!availableTypes.includes(item.type)) {
availableTypes.push(item.type);
}
});
return availableTypes;
},
availablePrograms: function () {
// List out the available programs and strips out the duplicates
const availablePrograms = [];
events[this.monthCounter].monthEvents.forEach((item) => {
if (!availablePrograms.includes(item.program)) {
availablePrograms.push(item.program);
}
});
return availablePrograms;
}
}
});
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
<title>Hello, world!</title>
</head>
<body>
<div class="container my-5">
<div id="app">
<h3>{{currentMonth}}</h3>
<strong>Types:</strong>
<div class="form-check form-check-inline" v-for="type in availableTypes">
<input class="form-check-input" type="checkbox" id="inlineCheckbox1" :value="type" v-model="filteredTypes">
<label class="form-check-label" for="inlineCheckbox1">{{type}}</label>
</div>
<br>
<strong>Programs:</strong>
<div class="form-check form-check-inline" v-for="program in availablePrograms">
<input class="form-check-input" type="checkbox" id="inlineCheckbox1" :value="program" v-model="filteredPrograms">
<label class="form-check-label" for="inlineCheckbox1">{{program}}</label>
</div>
<p class="mt-3">
<button class="btn btn-danger" @click="decreaseMonthCounter()">Down</button>
<button class="btn btn-success" @click="increaseMonthCounter()">Up</button>
</p>
<ol class="mt-3" id="event-container">
<li class="event" v-if="filterEvents(event)" v-for="event in availableMonthEvents">
<strong>Type:</strong> {{event.type}} - <strong>Program:</strong> {{event.program}}
</li>
<li v-if="noEvents">
There are no events!
</li>
</ol>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="app.js"></script>
</body>
</html>
我认为问题可能出在您的 filterEvents
方法以及您如何在页面上呈现事件
v-if
和 v-for
等两个指令不应放在单个 html 元素上。
我认为 Vue 试图做的是:
尝试呈现事件 => 看到 v-if 指令 => 运行 filterEvents => 修改事件 => 尝试再次呈现事件(因为事件是数组的一部分,所以数组被认为已修改)= > ...
不要改变 v-if
检查中的任何数据。
可能的解决方案
实施 filteredEvents 计算 属性,这将 return 数组有条件地过滤。
这些文档可以提供帮助:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
我能够通过使用计算的属性过滤我的列表来解决我的问题。
// List of events
const events = [{
month: 'January',
monthEvents: [{
type: 'Type 1',
program: 'Program 2'
},
{
type: 'Type 2',
program: 'Program 1'
},
{
type: 'Type 2',
program: 'Program 2'
},
{
type: 'Type 1',
program: 'Program 4'
}
]
},
{
month: 'February',
monthEvents: [{
type: 'Type 4',
program: 'Program 2'
},
{
type: 'Type 2',
program: 'Program 1'
},
{
type: 'Type 3',
program: 'Program 3'
},
{
type: 'Type 3',
program: 'Program 4'
}
]
}
]
new Vue({
el: '#app',
data: {
monthCounter: 0,
allEvents: events,
filteredTypes: [],
filteredPrograms: []
},
methods: {
increaseMonthCounter: function () {
// Increases the month counter by 1
this.filteredTypes = [];
this.filteredPrograms = [];
this.monthCounter++;
if (this.monthCounter > this.allEvents.length - 1) {
this.monthCounter = 0;
}
},
decreaseMonthCounter: function () {
// Decreases the month counter by 1
this.filteredTypes = [];
this.filteredPrograms = [];
this.monthCounter--;
if (this.monthCounter == -1) {
this.monthCounter = this.allEvents.length - 1;
}
}
},
computed: {
currentMonth: function () {
//Gets the currrent month
return events[this.monthCounter].month;
},
availableMonthEvents: function () {
// Gets the current month's events
return events[this.monthCounter].monthEvents;
},
filteredEvents: function () {
let filteredEvents = this.availableMonthEvents.filter((item) => {
// If there is nothing filtered show all events
if (this.filteredTypes.length === 0 && this.filteredPrograms.length === 0) {
return true;
}
// If a type is selected and no program is selected show all types
if (this.filteredTypes.includes(item.type) && this.filteredPrograms.length === 0) {
return true;
}
// If a program is selected and no type is selected show all programs
if (this.filteredPrograms.includes(item.program) && this.filteredTypes.length === 0) {
return true;
}
// If selection matches events type and program show event
if (this.filteredPrograms.includes(item.program) && this.filteredTypes.includes(item.type)) {
return true;
}
});
return filteredEvents;
},
availableTypes: function () {
// List out the available types and strips out the duplicates
const availableTypes = [];
events[this.monthCounter].monthEvents.forEach((item) => {
if (!availableTypes.includes(item.type)) {
availableTypes.push(item.type);
}
});
return availableTypes;
},
availablePrograms: function () {
// List out the available programs and strips out the duplicates
const availablePrograms = [];
events[this.monthCounter].monthEvents.forEach((item) => {
if (!availablePrograms.includes(item.program)) {
availablePrograms.push(item.program);
}
});
return availablePrograms;
}
}
});
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
<title>Hello, world!</title>
</head>
<body>
<div class="container my-5">
<div id="app">
<h3>{{currentMonth}}</h3>
<strong>Types:</strong>
<div class="form-check form-check-inline" v-for="type in availableTypes">
<input class="form-check-input" type="checkbox" id="inlineCheckbox1" :value="type" v-model="filteredTypes">
<label class="form-check-label" for="inlineCheckbox1">{{type}}</label>
</div>
<br>
<strong>Programs:</strong>
<div class="form-check form-check-inline" v-for="program in availablePrograms">
<input class="form-check-input" type="checkbox" id="inlineCheckbox1" :value="program" v-model="filteredPrograms">
<label class="form-check-label" for="inlineCheckbox1">{{program}}</label>
</div>
<p class="mt-3">
<button class="btn btn-danger" @click="decreaseMonthCounter()">Down</button>
<button class="btn btn-success" @click="increaseMonthCounter()">Up</button>
</p>
<ol class="mt-3">
<li class="event" v-for="event in filteredEvents">
<strong>Type:</strong> {{event.type}} - <strong>Program:</strong> {{event.program}}
</li>
<li v-if="filteredEvents.length == 0">
There are no events!
</li>
</ol>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="app.js"></script>
</body>
</html>