JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://unpkg.com/vue"></script>
<div id="app"></div>
<script type="text/x-template" id="phoneList-template">
<div id="app">
<table class="table table-hover" id="vuePhoneList">
<thead>
<tr>
<th width="25%">Телефон</th>
<th width="50%">Имя
<th><a href="#" class="glyph pull-right" v-bind:class="{'hover-opacity': phoneListLoaded}" v-on:click.prevent="refreshList"><span class="glyphicon glyphicon-refresh text-success"></span></a></th>
</tr>
</thead>
<tbody v-if="phoneListLoaded">
<tr v-for="elem in phoneList" key="elem.phone">
<td>{{ elem.phone }}</td>
<td>{{ elem.name }}</td>
<td><a href="#" class="glyph pull-right" v-bind:class="{'hover-opacity': !elem.removing}" v-on:click.prevent="removePhone(elem)"><span class="glyphicon glyphicon-remove-sign text-danger"></span></a></td>
</tr>
</tbody>
</table>
<confirm :shown="confirmShown" header="Удалить номер?" :text="confirmText" @confirm="removePhoneConfirm" @close="closeConfirm" ></confirm>
</div>
</script>
<script type="text/x-template" id="confirm-template">
<div class="modal fade" tabindex="-1" role="dialog" id="vueConfirm">
<div class="modal-dialog modal-sm" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" v-on:click="dismiss" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title">{{ header }}</h4>
</div>
<div class="modal-body">
{{ text }}
</div>
<div class="modal-footer">
<button type="button"...
CSS
.hover-opacity {
opacity: 0.2;
}
.hover-opacity:hover {
opacity: 0.5;
}
.hover-opacity:active {
opacity: 1;
}
.glyph {
float: right;
font-size: 21px;
line-height: 1;
text-shadow: 0 1px 0 #fff;
}
Babel + JSX
const extAPI = {
phones: [{
phone: '123456789',
name: 'Иван'
}, {
phone: '234567891',
name: 'Петр'
}, {
phone: '345678912',
name: 'Сидор'
}],
getPhoneList () {
return new Promise( (resolve, reject) =>
setTimeout( () => {
resolve(extAPI.phones)
}, 200)
)
},
deletePhone (phone) {
return new Promise ((resolve, reject) => {
setTimeout( () => {
let idx = extAPI.phones.findIndex(elm => elm.phone === phone)
if (idx !== -1)
extAPI.phones.splice(idx, 1)
resolve(extAPI.phones)
}, 200)
})
}
}
Vue.extAPI = window.extAPI = extAPI
let phoneListInstance = new Vue({
el: '#app',
template: "#phoneList-template",
data () {
return {
phoneList: [],
phoneListLoaded: false,
phoneListLoading: false,
currPhone: null,
confirmShown: false
}
},
beforeMount () {
this.refreshList()
},
computed: {
confirmText () {
if (this.currPhone)
return `Удалить номер ${this.currPhone.phone}?`
else
return ''
}
},
methods: {
refreshList () {
this.phoneListLoaded = false;
this.phoneListLoading = true;
extAPI.getPhoneList().then( (r) => {
this.phoneList = r
this.phoneListLoaded = true;
this.phoneListLoading = false;
})
},
removePhone (elem) {
this.currPhone = elem
Vue.set(this.currPhone, 'removing', true)
this.showConfirm()
},
removePhoneConfirm () {
if (this.currPhone) {
extAPI.deletePhone(this.currPhone.phone)
.then( (r) => {
this.phoneList = r
})
}
},
showConfirm () {
this.confirmShown = true
},
closeConfirm() {
this.confirmShown = false
if (this.currPhone) {
Vue.set(this.currPhone, 'removing', false)
}
},
...