<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><span class="glyphicon glyphicon-th-list"></span> MVVM</h3>
</div>
<div class="panel-body">
<!-- vm -->
<div id="vm">
<h3>{{ title }}</h3>
<ol>
<li v-for="todo in todos">
<dl>
<dt contenteditable="true" v-on:blur="update(todo, 'name', $event)">{{ todo.name }}</dt>
<dd contenteditable="true" v-on:blur="update(todo, 'description', $event)">{{ todo.description }}</dd>
<dd><a href="#0" v-on:click="remove(t)">Delete</a></dd>
</dl>
</li>
</ol>
</div>
<!-- vm -->
</div>
</div>
</div>
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><span class="glyphicon glyphicon-plus"></span> Add New Todo</h3>
</div>
<div class="panel-body">
<!-- vmAdd -->
<form id="vmAdd" action="#0">
<div class="form-group">
<label>Name:</label>
<input type="text" v-model="name" class="form-control" placeholder="Enter name">
</div>
<div class="form-group">
<label>Description:</label>
<input type="text" v-model="description" class="form-control" placeholder="Enter description">
</div>
<button type="submit" class="btn btn-default" v-on:click.prevent="submit">Add</button>
</form>
<!-- vmAdd -->
</div>
</div>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.13/dist/vue.js"></script>
<script>
// 集成API
//https://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000/00147576011615487c65971b3bd4acfa8ee94baaab3dbf7000
var bus = new Vue()
var vm = new Vue({
el: '#vm',
data: {
title: 'TODO List',
todos: [],
},
mounted: function() {
// bus.$on('todo', function(todo) {
// console.log(todo);
// this.todos.push(todo);
// }.bind(this))
},
created: function() {
this.init();
},
methods: {
init: function() {
this.todos = [{
name: "kavan",
description: "foo"
},
{
name: "lili",
description: "bar"
}
]
},
create: function(todo) {
this.todos.push(todo)
},
update: function(todo, prop, event) {
todo[prop] = event.target.innerText
}
}
});
var vmAdd = new Vue({
el: '#vmAdd',
data: {
name: '',
description: ''
},
methods: {
submit: function() {
vm.create(this.$data)
// bus.$emit('todo', this.$data)
this.name = '';
this.description = '';
}
}
});
</script>
</body>
</html>
這是老的問題題目(兩個vue實例間傳遞數(shù)據(jù)問題, 怎么解除數(shù)據(jù)綁定?), 發(fā)現(xiàn)根本不是這原因于是更改了問題題目!
傳對象時不能指向同一個對象的引用, 否則在另外一個組建中修改這個對象原組建的view也會因為vue實例中model的修改而發(fā)生變化, 目前我的解決方法是"克隆一個新對象"即在內(nèi)存中新生成一個全新對象, 并把引用傳給要通信的組件,JSON.parse(JSON.stringify(anObject)).即首先把對象轉(zhuǎn)化成JSON字符串再把字符串轉(zhuǎn)化成對象, 就相當(dāng)于克隆了一個對象anObject. 這樣這個問題就能得到解決!
事情的起因是想寫了個mvvm模擬model更新DOM也同步更新的Demo, 碰到一個不可描述的問題冥想許久不得要領(lǐng),于是來提問!
首先,發(fā)現(xiàn)不可以發(fā)動圖,而這個問題作為新手表述不會全面,所以請復(fù)制代碼放入html文件中打開網(wǎng)頁, 然后在add表單中添加2個todo事件, 發(fā)現(xiàn)兩個實例之間的數(shù)據(jù)是動態(tài)綁定, 這不是我想要的.
其實有更好的寫法, 但是我認(rèn)為這個問題的解決會加深對vue框架的理解,所以:
我嘗試過把vmAdd中submit方法中的初始化name和description用setTimeout包裹沒用, 用非父子組件間的數(shù)據(jù)傳遞(空實例, 代碼注釋了沒有刪除)也沒用, 有哪位有耐心的大神打開代碼幫看看要怎么解決, 雖然有其他方法比如只用一個vm實例可以解決, 或者不要在vmAdd中的表單上用v-model. 但是, 目前這種情況有沒有解決的方法, 話說每個vue實例都是一個組件, vue api不應(yīng)該一直跟蹤數(shù)據(jù)的? 求解決, 謝謝
先附一段解決后的完整代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><span class="glyphicon glyphicon-th-list"></span> MVVM</h3>
</div>
<div class="panel-body">
<!-- vm -->
<div id="vm">
<h3>{{ title }}</h3>
<ol>
<li v-for="todo in todos">
<dl>
<dt contenteditable="true" v-on:blur="update(todo, 'name', $event)">{{ todo.name }}</dt>
<dd contenteditable="true" v-on:blur="update(todo, 'description', $event)">{{ todo.description }}</dd>
<dd><a href="#0" v-on:click="remove(t)">Delete</a></dd>
</dl>
</li>
</ol>
</div>
<!-- vm -->
</div>
</div>
</div>
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><span class="glyphicon glyphicon-plus"></span> Add New Todo</h3>
</div>
<div class="panel-body">
<!-- vmAdd -->
<form id="vmAdd" action="#0">
<div class="form-group">
<label>Name:</label>
<input type="text" v-model="name" class="form-control" placeholder="Enter name">
</div>
<div class="form-group">
<label>Description:</label>
<input type="text" v-model="description" class="form-control" placeholder="Enter description">
</div>
<button type="submit" class="btn btn-default" v-on:click.prevent="submit">Add</button>
</form>
<!-- vmAdd -->
</div>
</div>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.13/dist/vue.js"></script>
<script>
// 集成API
//https://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000/00147576011615487c65971b3bd4acfa8ee94baaab3dbf7000
var bus = new Vue()
var vm = new Vue({
el: '#vm',
data: {
title: 'TODO List',
todos: [],
},
mounted: function() {
// bus.$on('todo', function(todo) {
// console.log(todo);
// this.todos.push(todo);
// }.bind(this))
},
created: function() {
this.init();
},
methods: {
init: function() {
this.todos = [{
name: "kavan",
description: "foo"
},
{
name: "lili",
description: "bar"
}
]
},
create: function(todo) {
const todo_new = { ...todo }
console.log(todo_new)
this.todos.push(todo_new)
},
update: function(todo, prop, event) {
todo[prop] = event.target.innerText
}
}
});
var vmAdd = new Vue({
el: '#vmAdd',
data: {
name: '',
description: ''
},
methods: {
submit: function() {
console.log(vm)
vm.create(this.$data)
this.name = '';
this.description = '';
}
}
});
</script>
</body>
</html>
先吐槽一下你的代碼,為什么要用兩個 vue 實例……,其實用一個更簡潔一點。
然后是你上面的問題
我的改動是這個地方
create: function(todo) {
const todo_new = { ...todo } // 復(fù)制值
console.log(todo_new)
this.todos.push(todo_new)
},
這里其實是一個 js 基礎(chǔ)問題,關(guān)于對象的引用,其實是引用的對象的一個指針。例如下面
var obj = { name: 'lw' }
var obj_new = obj
// 這里 obj 和 obj_new 他們都保存的是指向同一個對象的一個指針,而不是對象的值
// 例如下面這樣
obj_new.name = 'xm'
// 你會發(fā)現(xiàn) obj.name 的值也會變?yōu)?xm 而不是原來的 lw
然后你的問題就明了了,你傳遞給 vm 的對象,把 vmAdd 對值的跟蹤處理(get,set)也一起傳入。這樣的話,其實你傳入的這個值和 vmAdd 中的 data 指向的對象是同一個。
所以解決方法就是把這個對象深度復(fù)制一下,然后傳入對象的值而不是傳入對象的一個引用。
解決方法:
methods: {
submit: function () {
// 重點在這里 為什么自己去拼數(shù)據(jù)? 因為你一開始傳過去的是一個對象,傳遞的是引用,就是你后面再多次ADD過去的都是一個對象,東西都是一樣的。
// 再然后你馬上又清空了,導(dǎo)致沒有產(chǎn)生預(yù)期的效果,
vm.create({ name: this.name, description: this.description });
this.name = '';
this.description = '';
}
}
題外話:
北大青鳥APTECH成立于1999年。依托北京大學(xué)優(yōu)質(zhì)雄厚的教育資源和背景,秉承“教育改變生活”的發(fā)展理念,致力于培養(yǎng)中國IT技能型緊缺人才,是大數(shù)據(jù)專業(yè)的國家
北大青鳥中博軟件學(xué)院創(chuàng)立于2003年,作為華東區(qū)著名互聯(lián)網(wǎng)學(xué)院和江蘇省首批服務(wù)外包人才培訓(xùn)基地,中博成功培育了近30000名軟件工程師走向高薪崗位,合作企業(yè)超4
中公教育集團(tuán)創(chuàng)建于1999年,經(jīng)過二十年潛心發(fā)展,已由一家北大畢業(yè)生自主創(chuàng)業(yè)的信息技術(shù)與教育服務(wù)機(jī)構(gòu),發(fā)展為教育服務(wù)業(yè)的綜合性企業(yè)集團(tuán),成為集合面授教學(xué)培訓(xùn)、網(wǎng)
達(dá)內(nèi)教育集團(tuán)成立于2002年,是一家由留學(xué)海歸創(chuàng)辦的高端職業(yè)教育培訓(xùn)機(jī)構(gòu),是中國一站式人才培養(yǎng)平臺、一站式人才輸送平臺。2014年4月3日在美國成功上市,融資1
曾工作于聯(lián)想擔(dān)任系統(tǒng)開發(fā)工程師,曾在博彥科技股份有限公司擔(dān)任項目經(jīng)理從事移動互聯(lián)網(wǎng)管理及研發(fā)工作,曾創(chuàng)辦藍(lán)懿科技有限責(zé)任公司從事總經(jīng)理職務(wù)負(fù)責(zé)iOS教學(xué)及管理工作。
浪潮集團(tuán)項目經(jīng)理。精通Java與.NET 技術(shù), 熟練的跨平臺面向?qū)ο箝_發(fā)經(jīng)驗,技術(shù)功底深厚。 授課風(fēng)格 授課風(fēng)格清新自然、條理清晰、主次分明、重點難點突出、引人入勝。
精通HTML5和CSS3;Javascript及主流js庫,具有快速界面開發(fā)的能力,對瀏覽器兼容性、前端性能優(yōu)化等有深入理解。精通網(wǎng)頁制作和網(wǎng)頁游戲開發(fā)。
具有10 年的Java 企業(yè)應(yīng)用開發(fā)經(jīng)驗。曾經(jīng)歷任德國Software AG 技術(shù)顧問,美國Dachieve 系統(tǒng)架構(gòu)師,美國AngelEngineers Inc. 系統(tǒng)架構(gòu)師。