我只往sieteItems 里push 了一次。為啥 watch 執(zhí)行了兩次呢?
怎么可以知道是哪兒導(dǎo)致觸發(fā)的?
組件 A里的
下面是組件B里的
<template>
<div class="grid resizable" ref="draggable" @contextmenu.prevent.stop v-bind:style="{ left: grid.position.x + 'px', top: grid.position.y + 'px',width:grid.position.w+'px',height:grid.position.h+'px'}">
<h4 v-if="!grid.isRoot" :class="handle">{{grid.gridName}}</h4>
<div :class="{'contentBox':true, 'isRoot':grid.isRoot}" @contextmenu.prevent.stop="show">
<siteItem class="siteItemWrap" v-for="item in grid.siteItems" :item.sync="item" :key="item.siteId" @deleteItem="deleteItem" @moveItem="moveItem"></siteItem>
<gridItem v-for="grid in grid.gridItems" :grid.sync="grid" :key="grid.gridId" @resizGrid="resizGrid" @moveGrid="moveGrid"></gridItem>
<div v-show="contextmenu.isShowContextmenu" v-bind:style="{ left: contextmenu.x + 'px', top: contextmenu.y + 'px'}" class="contextmenu">
<el-button @click="addItem" :plain="true" type="info" icon="plus">新增網(wǎng)址</el-button>
<br>
<el-button @click="addGrid" :plain="true" type="info" icon="plus">新建格子</el-button>
</li>
</div>
</div>
</div>
</template>
<script type="text/javascript">
import siteItem from './siteItem';
export default {
props: {
grid: {
type: Object,
default: {
gridId: '',
gridName: '格子一',
position: { x: '0', y: '0', w: '100', h: '100' },
siteItems: [{
siteId: '5',
site: 'http://www.zhihu.com',
name: '知乎',
position: { x: '10', y: '20' }
}],
gridItems: [{
gridId: '',
gridName: '格子一',
position: { x: '0', y: '0' },
siteItems: [],
gridItems: []
},
{
gridId: '',
gridName: '格子一',
position: { x: '0', y: '0' },
siteItems: [],
gridItems: []
}
]
}
}
},
data() {
return {
contextmenu: {
isShowContextmenu: false,
x: 0,
y: 0
},
draggable: null
}
},
computed: {
handle: function() {
return 'handle' + this.grid.gridId;
}
},
watch: {
'grid.siteItems' () {
var self = this;
console.log(this)
//self.minPos();
}
},
methods: {
minPos() {
var self = this;
function setPos() {
var x, y;
$(self.draggable).children('.contentBox').children('.siteItemWrap,.grid').each(function(index, ele) {
ele = $(ele);
var disX = ele.position().left + ele.width();
var disY = ele.position().top + ele.height();
if (x == undefined) {
x = disX;
y = disY;
} else {
if (disX > x) {
x = disX;
}
if (disY > y) {
y = disY;
}
}
})
return { x, y: y + 30 };
}
if (!self.grid.isRoot) {
self.$nextTick(function() {
var minPos = setPos();
$(self.draggable).resizable("option", "minHeight", minPos.y);
$(self.draggable).resizable("option", "minWidth", minPos.x);
})
}
},
show(ev) {
var rect = ev.target.getBoundingClientRect();
this.contextmenu.x = ev.clientX - rect.left;
this.contextmenu.y = ev.clientY - rect.top;
this.$bus.$emit('isShowContextmenu', this.contextmenu);
},
addGrid() {
var self = this;
self.$bus.$emit('addGrid', self.grid, self.contextmenu);
},
moveGrid(grid) {
var self = this;
console.log(789)
self.minPos();
self.$bus.$emit('moveGrid', self.grid);
},
editGrid(grid) {
var self = this;
self.$bus.$emit('editGrid', self.grid);
},
deleteGrid() {
var self = this;
self.$bus.$emit('deleteGrid', self.grid);
},
addItem() {
var self = this;
self.$bus.$emit('addItem', self.grid, self.contextmenu);
},
deleteItem(item) {
var self = this;
self.$bus.$emit('deleteItem', self.grid, item);
},
moveItem(item) {
var self = this;
self.minPos();
self.$bus.$emit('moveItem', item)
},
resizGrid() {
var self = this;
self.minPos();
}
},
updated() {},
mounted() {
var self = this;
self.draggable = self.$refs.draggable;
self.$nextTick(function() {
if (!self.grid.isRoot) {
$(self.draggable).draggable({
handle: '.' + self.handle,
containment: "parent",
stop: function(event, ui) {
$(self.draggable).css('zIndex', self.$bus.zIndex++);
self.grid.position.x = ui.position.left;
self.grid.position.y = ui.position.top;
self.$emit('moveGrid', self.grid);
event.stopPropagation()
}
})
$(self.draggable).resizable({
stop: function(event, ui) {
self.grid.position.w = ui.size.width;
self.grid.position.h = ui.size.height;
self.$emit('resizGrid');
console.log('grid')
},
autoHide: true,
containment: "parent"
/*,
helper: "ui-resizable-helper"*/
})
self.minPos();
}
$(self.draggable).children('.contentBox').droppable({
greedy: true,
accept: '.siteItemWrap',
drop: function(event, ui) {
console.log(ui)
//ui.position.left < 0 || ui.position.top < 0||ui.position.left> ui.draggable.parent().width() ||ui.position.top> ui.draggable.parent().height()
if (ui.draggable.parent().get(0)!== this) {
ui.draggable.get(0).out = true;
var left = ui.offset.left - $(this).offset().left;
var top = ui.offset.top - $(this).offset().top;
var oVue = ui.draggable.get(0).oVue;
var grid = oVue.grid;
var item = oVue.item;
oVue.deleteItem();
item.position.x = left;
item.position.y = top;
self.$bus.$emit('addItemFromOther', self.grid, item);
}else{
console.log(1)
}
}
});
})
},
created() {
//alert('created grid')
},
name: 'gridItem',
components: { siteItem }
}
</script>
<template>
<div class="stage">
<gridItem class="rootGrid" :grid.sync="rootGrid" @click.native="close"></gridItem>
<el-dialog @contextmenu.native.prevent.stop :title="siteOption=='add'?'新增書簽':'編輯書簽'" :visible.sync="dialogFormVisible" size="tiny" :modal="false">
<el-form :label-position="'right'" label-width="80px" :model="form">
<el-form-item label="網(wǎng)址">
<el-input v-model="form.site" auto-complete="off" placeholder="請輸入網(wǎng)址"></el-input>
</el-form-item>
<el-form-item label="名稱">
<el-input v-model="form.name" auto-complete="off" placeholder="請輸入名稱"></el-input>
</el-form-item>
<el-form-item label="格子">
<el-select v-model="form.grid" placeholder="請選擇格子">
<el-option label="區(qū)域一" value="shanghai"></el-option>
<el-option label="區(qū)域二" value="beijing"></el-option>
</el-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button v-if="siteOption=='add'" type="primary" @click="submitAddForm">確 定</el-button>
<el-button v-if="siteOption=='edit'" type="primary" @click="submitEditForm(form)">確 定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import qs from 'qs';
import gridItem from './gridItem';
export default {
data() {
return {
rootGrid: {
gridId: '1',
gridName: '格子1',
position: { x: '0', y: '0' ,w:'500',h:'500'},
isRoot:true,
siteItems: [{
siteId: '5',
site: 'http://www.zhihu.com',
name: '知乎',
position: { x: '10', y: '20' },
isShowEdit:false
}
],
gridItems: [{
gridId: '1-1',
gridName: '格子1-1',
position: { x: '10', y: '10',w:'200',h:'100' },
siteItems: [],
gridItems: []
},
{
gridId: '1-2',
gridName: '格子1-2',
position: { x: '20', y: '20',w:'500',h:'500' },
siteItems: [{
siteId: '51',
site: 'http://www.zhihu.com',
name: '知乎1',
position: { x: '10', y: '20' },
isShowEdit:false
}],
gridItems: [
{
gridId: '1-2-1',
gridName: '格子1-2-1',
position: { x: '50', y: '50' ,w:'300',h:'100'},
siteItems: [{
siteId: '523',
site: 'http://www.zhihu.com',
name: '知乎1',
position: { x: '10', y: '20' },
isShowEdit:false
}],
gridItems: []
}
]
},
{
gridId: '1-3',
gridName: '格子1-3',
position: { x: '50', y: '50' },
siteItems: [{
siteId: '52',
site: 'http://www.zhihu.com',
name: '知乎1',
position: { x: '10', y: '20',w:'300',h:'100' },
isShowEdit:false
}],
gridItems: []
}
]
},
siteOption: "add",
currentGrid:{},
currentContextmenu:{},
currentItem:{},
dialogFormVisible: false,
form: {
siteId: '5',
site: '',
name: '',
grid: '',
position: { x: '10', y: '20' }
}
}
},
beforeUpdate() {
//alert('beforeUpdated hello')
},
updated() {
//alert('updated hello111')
},
methods: {
moveItem(item) {
var self = this;
self.currentItem = item;
},
deleteItem(grid, item) {
var self = this;
self.$axios.post('/mock/items/submitDelete', qs.stringify(item))
.then(function(response) {
self.$message({
type: 'success',
message: '刪除成功'
});
var index = grid.siteItems.indexOf(item);
grid.siteItems.splice(index, 1);
})
.catch(function(error) {
console.log(error);
});
},
close(ev) {
this.currentItem.isShowEdit = false;
this.currentContextmenu.isShowContextmenu = false;
},
addGrid() {
this.gridItems.push({
gridId: '',
gridName: '格子一',
gridSites: []
})
},
editGrid() {
},
deleteGrid() {
},
submitAddForm() {
var self = this;
console.log(self.form,self.currentContextmenu,Object.assign({}, self.form),11)
self.$axios.post('/mock/items/submitAdd', qs.stringify(Object.assign({}, self.form)))
.then(function(response) {
self.$message({
type: 'success',
message: '新增成功'
});
debugger;
self.currentGrid.siteItems.push(response.data);
self.dialogFormVisible = false;
})
.catch(function(error) {
console.log(error);
});
},
submitEditForm(data, isPos) {
var self = this;
self.$axios.post('/mock/items/submitEdit', qs.stringify(data))
.then(function(response) {
if (!isPos) {
self.$message({
type: 'success',
message: '修改成功'
});
}
Object.assign(self.currentItem, JSON.parse(JSON.stringify(data)));
self.dialogFormVisible = false;
})
.catch(function(error) {
console.log(error);
});
},
init() {
var self = this;
self.$axios.get('/mock/items/all')
.then(function(response) {
console.log(response);
//response.data;
})
.catch(function(error) {
console.log(error);
});
}
},
created() {
//alert('created hello')
var self = this;
self.init();
self.$bus.$on('isShowEdit', function (item) {
self.currentItem.isShowEdit = false;
self.currentContextmenu.isShowContextmenu = false;
self.currentItem = item;
self.currentItem.isShowEdit = true;
})
self.$bus.$on('isShowContextmenu', function (contextmenu) {
self.currentItem.isShowEdit = false;
self.currentContextmenu.isShowContextmenu = false;
self.currentContextmenu = contextmenu;
self.currentContextmenu.isShowContextmenu = true;
})
self.$bus.$on('addItem', function (grid,contextmenu) {
self.currentGrid = grid;
self.currentContextmenu = contextmenu;
self.siteOption = "add";
self.form.siteId = '',
self.form.site = '',
self.form.name = '',
self.form.grid = '',
self.form.position = contextmenu;
self.dialogFormVisible = true;
})
self.$bus.$on('addItemFromOther', function (grid,item) { //新增從其他格子里移動進(jìn)來的
console.log(222)
self.currentGrid = grid;
self.$axios.post('/mock/items/submitAdd', qs.stringify(Object.assign({},item)))
.then(function(response) {
self.$message({
type: 'success',
message: '移動成功'
});
self.currentGrid.siteItems.push(response.data);
})
.catch(function(error) {
console.log(error);
});
})
self.$bus.$on('editItem', function (item) {
self.currentItem = item;
self.siteOption = "edit";
Object.assign(self.form, JSON.parse(JSON.stringify(item)));
self.dialogFormVisible = true;
})
self.$bus.$on('deleteItem', function (grid, item) {
console.log(33)
self.deleteItem(grid, item);
})
},
mounted() {
//alert('mounted hello')
},
components: { gridItem }
}
</script>
大體效果如下
等會= =、
既然你講currentGrid和grid是同一個東西,那么如果值發(fā)生變化
self.currentGrid = grid會觸發(fā)。你可以先注釋掉一個看看。
你的siteItem.vue組件中
<el-popover popper-class="edit" ref="popover{{siteId}}"
placement="right" v-model="item.isShowEdit" trigger="manual">
<ul class="showEdit">
<li @click="edit">編輯</li>
<li @click="open">打開</li>
<li @click="deleteItem">刪除</li>
</ul>
</el-popover>
<el-button class="siteItem " type="text" size="large" v-popover:popover{{siteId}}>
{{name}}
</el-button>
初步判定是v-model="item.isShowEdit"導(dǎo)致的。
查調(diào)用棧,第二次觸發(fā)的時候有一次isShowEdit的修改,至于這個值得變化是怎么引起的(可能跟element-ui的popover組件有關(guān)),你再自己看看。
把上方的代碼塊注了就沒事了,解決辦法你再研究研究。
北大青鳥APTECH成立于1999年。依托北京大學(xué)優(yōu)質(zhì)雄厚的教育資源和背景,秉承“教育改變生活”的發(fā)展理念,致力于培養(yǎng)中國IT技能型緊缺人才,是大數(shù)據(jù)專業(yè)的國家
達(dá)內(nèi)教育集團(tuán)成立于2002年,是一家由留學(xué)海歸創(chuàng)辦的高端職業(yè)教育培訓(xùn)機(jī)構(gòu),是中國一站式人才培養(yǎng)平臺、一站式人才輸送平臺。2014年4月3日在美國成功上市,融資1
北大課工場是北京大學(xué)校辦產(chǎn)業(yè)為響應(yīng)國家深化產(chǎn)教融合/校企合作的政策,積極推進(jìn)“中國制造2025”,實(shí)現(xiàn)中華民族偉大復(fù)興的升級產(chǎn)業(yè)鏈。利用北京大學(xué)優(yōu)質(zhì)教育資源及背
博為峰,中國職業(yè)人才培訓(xùn)領(lǐng)域的先行者
曾工作于聯(lián)想擔(dān)任系統(tǒng)開發(fā)工程師,曾在博彥科技股份有限公司擔(dān)任項(xiàng)目經(jīng)理從事移動互聯(lián)網(wǎng)管理及研發(fā)工作,曾創(chuàng)辦藍(lán)懿科技有限責(zé)任公司從事總經(jīng)理職務(wù)負(fù)責(zé)iOS教學(xué)及管理工作。
浪潮集團(tuán)項(xiàng)目經(jīng)理。精通Java與.NET 技術(shù), 熟練的跨平臺面向?qū)ο箝_發(fā)經(jīng)驗(yàn),技術(shù)功底深厚。 授課風(fēng)格 授課風(fēng)格清新自然、條理清晰、主次分明、重點(diǎn)難點(diǎn)突出、引人入勝。
精通HTML5和CSS3;Javascript及主流js庫,具有快速界面開發(fā)的能力,對瀏覽器兼容性、前端性能優(yōu)化等有深入理解。精通網(wǎng)頁制作和網(wǎng)頁游戲開發(fā)。
具有10 年的Java 企業(yè)應(yīng)用開發(fā)經(jīng)驗(yàn)。曾經(jīng)歷任德國Software AG 技術(shù)顧問,美國Dachieve 系統(tǒng)架構(gòu)師,美國AngelEngineers Inc. 系統(tǒng)架構(gòu)師。