Vuejs + onClick 不适用于安装后加载的动态元素
Vuejs + onClick doesn't work on dynamic element loaded after mounted
我被这个问题困住了。当我点击某个元素时,它会将一个项目推送到一个数组中,然后我将这个数组显示在 table 中。我想添加一个操作来删除 table 中的任何行,例如:
Table
我的代码:
<div id="pos">
<div class="container-fluid" style="font-size: 0.8em;">
<div class="row grid-columns">
<div class="col-md-6 col">
<table class="table">
<thead>
<tr>
<th>#</th>
<th>Descripcion</th>
<th>Stock</th>
<th>Precio uni</th>
<th>Precio alt</th>
<th>Cant</th>
<th>Subtotal</th>
<th>Acciones</th>
</tr>
</thead>
<tbody>
<pos-products
:products="products"
v-on:remove-product="removeProduct"
>
</pos-products>
<!-- <tr v-for="item in products" :key="item.id">
<th scope="row">${item.id}</th>
<td>${ item.descripcion }</td>
<td>${ item.stock }</td>
<td>${ item.precio } $</td>
<td>${ item.precio_alt } $</td>
<td>
<v-minusplusfield :value="1" :min="1" :max="100" v-model="item.cant"></v-minusplusfield>
</td>
<td>${ getSubtotal(item) }</td>
<td><a href="#" @click="removeItem(item)"> Borrar </a></td>
</tr> -->
</tbody>
</table>
</div>
<div class="col-md-6 col">
<div>
<div id="grid-header" class="p-2 border-b ">
<input class="form-control" name="searchString" placeholder="Buscar producto" type="text" v-model="searchString" />
</div>
</div>
<div style="background-color:#fff">
<div class="col-md-3" v-for="item in searchResults">
<a
href="#"
class="list-group-item"
:key="item.id"
@click="loadItem(item)"
>
<img src="//images03.nicepage.com/a1389d7bc73adea1e1c1fb7e/af4ca43bd20b5a5fab9f188a/pexels-photo-3373725.jpeg" alt="" class="u-expanded-width u-image u-image-default u-image-1" width="25" height="30">
<h6 class="u-text u-text-default u-text-1">${item.descripcion}</h6>
<h4 class="u-text u-text-default u-text-2">${item.precio}$ / ${item.precio_alt}$</h4>
</a>
</div>
</div>
</div>
</div>
</div>
Vue代码:
const app = new Vue({
el: "#pos",
delimiters: ["${", "}"],
data () {
return {
products: [],
total: 0,
client: "",
user: "",
paymentDetail: [],
errors: {},
garantia: false,
saveButton: false,
seller: "",
searchString: "",
searchTypingTimeout: "",
searchResults: [],
}
},
methods: {
getSubtotal: function (item) {
return parseInt(item.cant) * parseFloat(item.precio);
},
loadItem: function (item) {
this.products.push({
id: item.id,
descripcion: item.descripcion,
stock: item.stock,
precio: item.precio,
precio_alt: item.precio_alt,
cant: 1,
});
},
removeItem: () => {
products = products.filter((el) => el !== item);
},
searchProducts: function (value) {
axios
.post("/v2/producto/search", {
query: value
})
.then((response) => {
if (!response.status == 200 || response.data.error) {
console.log('error')
const errorMessage = response.data.error
? response.data.error
: "Ha ocurrido un error";
console.log("mensaje: " + errorMessage);
this.$swal({
icon: "error",
title: "Oops...",
text: errorMessage,
});
return;
}
this.searchResults = response.data.data;
})
.catch((error) => {
console.log("catch error", error);
});
},
},
mounted() {
var csrf = document
.querySelector('meta[name="csrf-token"]')
.getAttribute("content");
this.products = [];
},
computed: {},
watch: {
total(val) {
this.total = parseFloat(val);
},
searchString(val) {
if (this.searchTypingTimeout) clearTimeout(this.searchTypingTimeout);
this.searchTypingTimeout = setTimeout(
() => this.searchProducts(this.searchString),
850
);
},
},
});
我知道了:
vue.js?3de6:634 [Vue warn]: Property or method "removeItem" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.
尝试像这样使用经典函数:
removeItem(item){
const index = this.items.findIndex(x => x.id === item.id)
this.items.splice(index, 1)
},
我在这里用 jsonplaceholder.typicode.com api
加载了数据
new Vue({
el: '#app',
data: () => ({
items: []
}),
async mounted(){
await axios.get('https://jsonplaceholder.typicode.com/posts')
.then(res => {
this.items = res.data
})
},
methods: {
removeItem(item){
const index = this.items.findIndex(x => x.id === item.id)
this.items.splice(index, 1)
},
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.27.2/axios.min.js" integrity="sha512-odNmoc1XJy5x1TMVMdC7EMs3IVdItLPlCeL5vSUPN2llYKMJ2eByTTAIiiuqLg+GdNr9hF6z81p27DArRFKT7A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<div id="app">
<h1>List </h1>
<ul>
<li v-for="item of items" :key="item.id">
<a @click="removeItem(item)">{{item.id}} - {{item.title}}</a>
</li>
</ul>
</div>
我被这个问题困住了。当我点击某个元素时,它会将一个项目推送到一个数组中,然后我将这个数组显示在 table 中。我想添加一个操作来删除 table 中的任何行,例如: Table
我的代码:
<div id="pos">
<div class="container-fluid" style="font-size: 0.8em;">
<div class="row grid-columns">
<div class="col-md-6 col">
<table class="table">
<thead>
<tr>
<th>#</th>
<th>Descripcion</th>
<th>Stock</th>
<th>Precio uni</th>
<th>Precio alt</th>
<th>Cant</th>
<th>Subtotal</th>
<th>Acciones</th>
</tr>
</thead>
<tbody>
<pos-products
:products="products"
v-on:remove-product="removeProduct"
>
</pos-products>
<!-- <tr v-for="item in products" :key="item.id">
<th scope="row">${item.id}</th>
<td>${ item.descripcion }</td>
<td>${ item.stock }</td>
<td>${ item.precio } $</td>
<td>${ item.precio_alt } $</td>
<td>
<v-minusplusfield :value="1" :min="1" :max="100" v-model="item.cant"></v-minusplusfield>
</td>
<td>${ getSubtotal(item) }</td>
<td><a href="#" @click="removeItem(item)"> Borrar </a></td>
</tr> -->
</tbody>
</table>
</div>
<div class="col-md-6 col">
<div>
<div id="grid-header" class="p-2 border-b ">
<input class="form-control" name="searchString" placeholder="Buscar producto" type="text" v-model="searchString" />
</div>
</div>
<div style="background-color:#fff">
<div class="col-md-3" v-for="item in searchResults">
<a
href="#"
class="list-group-item"
:key="item.id"
@click="loadItem(item)"
>
<img src="//images03.nicepage.com/a1389d7bc73adea1e1c1fb7e/af4ca43bd20b5a5fab9f188a/pexels-photo-3373725.jpeg" alt="" class="u-expanded-width u-image u-image-default u-image-1" width="25" height="30">
<h6 class="u-text u-text-default u-text-1">${item.descripcion}</h6>
<h4 class="u-text u-text-default u-text-2">${item.precio}$ / ${item.precio_alt}$</h4>
</a>
</div>
</div>
</div>
</div>
</div>
Vue代码:
const app = new Vue({
el: "#pos",
delimiters: ["${", "}"],
data () {
return {
products: [],
total: 0,
client: "",
user: "",
paymentDetail: [],
errors: {},
garantia: false,
saveButton: false,
seller: "",
searchString: "",
searchTypingTimeout: "",
searchResults: [],
}
},
methods: {
getSubtotal: function (item) {
return parseInt(item.cant) * parseFloat(item.precio);
},
loadItem: function (item) {
this.products.push({
id: item.id,
descripcion: item.descripcion,
stock: item.stock,
precio: item.precio,
precio_alt: item.precio_alt,
cant: 1,
});
},
removeItem: () => {
products = products.filter((el) => el !== item);
},
searchProducts: function (value) {
axios
.post("/v2/producto/search", {
query: value
})
.then((response) => {
if (!response.status == 200 || response.data.error) {
console.log('error')
const errorMessage = response.data.error
? response.data.error
: "Ha ocurrido un error";
console.log("mensaje: " + errorMessage);
this.$swal({
icon: "error",
title: "Oops...",
text: errorMessage,
});
return;
}
this.searchResults = response.data.data;
})
.catch((error) => {
console.log("catch error", error);
});
},
},
mounted() {
var csrf = document
.querySelector('meta[name="csrf-token"]')
.getAttribute("content");
this.products = [];
},
computed: {},
watch: {
total(val) {
this.total = parseFloat(val);
},
searchString(val) {
if (this.searchTypingTimeout) clearTimeout(this.searchTypingTimeout);
this.searchTypingTimeout = setTimeout(
() => this.searchProducts(this.searchString),
850
);
},
},
});
我知道了:
vue.js?3de6:634 [Vue warn]: Property or method "removeItem" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.
尝试像这样使用经典函数:
removeItem(item){
const index = this.items.findIndex(x => x.id === item.id)
this.items.splice(index, 1)
},
我在这里用 jsonplaceholder.typicode.com api
加载了数据new Vue({
el: '#app',
data: () => ({
items: []
}),
async mounted(){
await axios.get('https://jsonplaceholder.typicode.com/posts')
.then(res => {
this.items = res.data
})
},
methods: {
removeItem(item){
const index = this.items.findIndex(x => x.id === item.id)
this.items.splice(index, 1)
},
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.27.2/axios.min.js" integrity="sha512-odNmoc1XJy5x1TMVMdC7EMs3IVdItLPlCeL5vSUPN2llYKMJ2eByTTAIiiuqLg+GdNr9hF6z81p27DArRFKT7A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<div id="app">
<h1>List </h1>
<ul>
<li v-for="item of items" :key="item.id">
<a @click="removeItem(item)">{{item.id}} - {{item.title}}</a>
</li>
</ul>
</div>