生活随笔
收集整理的這篇文章主要介紹了
vue-day03-vue组件化开发
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 組件
- 組件注冊
- Vue 調試工具
- Vue組件之間傳值
- 父組件向子組件傳值
- 子組件向父組件傳值
- 兄弟之間的傳遞
- 組件插槽
- 購物車案例
- 1. 實現組件化布局
- 2、實現 標題和結算功能組件
- 3. 實現列表組件刪除功能
- 4. 實現組件更新數據功能 上
- 5. 實現組件更新數據功能 下
組件
組件注冊
全局注冊
- Vue.component(‘組件名稱’, { }) 第1個參數是標簽名稱,第2個參數是一個選項對象
- 全局組件注冊后,任何vue實例都可以用
組件基礎用
<div id="example"> <my-component></my-component>
</div>
<script>Vue.component('my-component', {template: '<div>A custom component!</div>'})new Vue({el: '#example'})</script>
組件注意事項
- 組件參數的data值必須是函數同時這個函數要求返回一個對象
- 組件模板必須是單個根元素
- 組件模板的內容可以是模板字符串
<div id="app"> <button-counter></button-counter><button-counter></button-counter><button-counter></button-counter><hello-world></hello-world></div><script type="text/javascript">Vue.component('HelloWorld', {data: function(){return {msg: 'HelloWorld'}},template: '<div>{{msg}}</div>'});Vue.component('button-counter', {data: function(){return {count: 0}},template: `<div><button @click="handle">點擊了{{count}}次</button><button>測試123</button># 6 在字符串模板中可以使用駝峰的方式使用組件 <HelloWorld></HelloWorld></div>`,methods: {handle: function(){this.count += 2;}}})var vm = new Vue({el: '#app',data: {}});</script>
局部注冊
/*
局部組件注冊
局部組件只能在注冊他的父組件中使用
*/
<div id="app"><my-component></my-component></div><script>var Child = {template: '<div>A custom component!</div>'}new Vue({components: {'my-component': Child}})</script>
Vue 調試工具
Vue組件之間傳值
父組件向子組件傳值
- 父組件發送的形式是以屬性的形式綁定值到子組件身上。
- 然后子組件用屬性props接收
- 在props中使用駝峰形式,模板中需要使用短橫線的形式字符串形式的模板中沒有這個限制
<div id="app"><div>{{pmsg}}
</div><menu-item title='來自父組件的值'></menu-item><menu-item :title='ptitle' content='hello'></menu-item></div><script type="text/javascript">Vue.component('menu-item', {props: ['title', 'content'],data: function() {return {msg: '子組件本身的數據'}},template: '<div>{{msg + "----" + title + "-----" + content}}</div>'});var vm = new Vue({el: '#app',data: {pmsg: '父組件中內容',ptitle: '動態綁定屬性'}});</script>
如果父組件向子組件中傳值,不用v-bind或者是:進行pp綁定,傳進去的都是字符串。
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Document
</title>
</head>
<body><div id="app"><div>{{pmsg}}
</div><menu-item :pstr='pstr' :pnum='12' pboo='true' :parr='parr' :pobj='pobj'></menu-item></div><script type="text/javascript" src="js/vue.js"></script><script type="text/javascript">Vue.component('menu-item', {props: ['pstr','pnum','pboo','parr','pobj'],template: `<div><div>{{pstr}}</div><div>{{12 + pnum}}</div><div>{{typeof pboo}}</div><ul><li :key='index' v-for='(item,index) in parr'>{{item}}</li></ul><span>{{pobj.name}}</span><span>{{pobj.age}}</span></div></div>`});var vm = new Vue({el: '#app',data: {pmsg: '父組件中內容',pstr: 'hello',parr: ['apple','orange','banana'],pobj: {name: 'lisi',age: 12}}});</script>
</body>
</html>
子組件向父組件傳值
/*
子組件向父組件傳值-基本用法
props傳遞數據原則:單向數據流
*/
- 子組件用$emit()觸發事件
- $emit() 第一個參數為 自定義的事件名稱 第二個參數為需要傳遞的數據
- 父組件用v-on 監聽子組件的事件
<div id="app"><div :style='{fontSize: fontSize + "px"}'>{{pmsg}}
</div> <menu-item :parr='parr' @enlarge-text='handle($event)'></menu-item></div><script type="text/javascript" src="js/vue.js"></script><script type="text/javascript">Vue.component('menu-item', {props: ['parr'],template: `<div><ul><li :key='index' v-for='(item,index) in parr'>{{item}}</li></ul>### 1、子組件用$emit()觸發事件### 第一個參數為 自定義的事件名稱 第二個參數為需要傳遞的數據 <button @click='$emit("enlarge-text", 5)'>擴大父組件中字體大小</button><button @click='$emit("enlarge-text", 10)'>擴大父組件中字體大小</button></div>`});var vm = new Vue({el: '#app',data: {pmsg: '父組件中內容',parr: ['apple','orange','banana'],fontSize: 10},methods: {handle: function(val){this.fontSize += val;}}});</script>
兄弟之間的傳遞
- 兄弟之間傳遞數據需要借助于事件中心,通過事件中心傳遞數據
- 提供事件中心 var hub = new Vue()
- 傳遞數據方,通過一個事件觸發hub.$emit(方法名,傳遞的數據)
- 接收數據方,通過mounted(){} 鉤子中 觸發hub.$on()方法名
- 銷毀事件 通過hub.$off()方法名銷毀之后無法進行傳遞數據
<div id="app"><div>父組件
</div><div><button @click='handle'>銷毀事件
</button></div><test-tom></test-tom><test-jerry></test-jerry></div><script type="text/javascript" src="js/vue.js"></script><script type="text/javascript">var hub = new Vue();Vue.component('test-tom', {data: function(){return {num: 0}},template: `<div><div>TOM:{{num}}</div><div><button @click='handle'>點擊</button></div></div>`,methods: {handle: function(){hub.$emit('jerry-event', 2);}},mounted: function() {hub.$on('tom-event', (val) => {this.num += val;});}});Vue.component('test-jerry', {data: function(){return {num: 0}},template: `<div><div>JERRY:{{num}}</div><div><button @click='handle'>點擊</button></div></div>`,methods: {handle: function(){hub.$emit('tom-event', 1);}},mounted: function() {hub.$on('jerry-event', (val) => {this.num += val;});}});var vm = new Vue({el: '#app',data: {},methods: {handle: function(){hub.$off('tom-event');hub.$off('jerry-event');}}});</script>
組件插槽
vue中slot理解,以及應用場景
Props傳值可以,但是無法傳遞dom節點,類似這種:
- 組件的最大特性就是復用性,而用好插槽能大大提高組件的可復用能力
匿名插槽
<div id="app"> <alert-box>有bug發生
</alert-box><alert-box>有一個警告
</alert-box><alert-box></alert-box></div><script type="text/javascript">Vue.component('alert-box', {template: `<div><strong>ERROR:</strong># 當組件渲染的時候,這個 <slot> 元素將會被替換為“組件標簽中嵌套的內容”。# 插槽內可以包含任何模板代碼,包括 HTML<slot>默認內容</slot></div>`});var vm = new Vue({el: '#app',data: {}});</script>
</body>
</html>
具名插槽
- 具有名字的插槽
- 使用 中的 “name” 屬性綁定元素
<div id="app"><base-layout><!-- 2、 通過slot屬性來指定, 這個slot的值必須和下面slot組件得name值對應上如果沒有匹配到 則放到匿名的插槽中 --> <p slot='header'>標題信息</p><p>主要內容1</p><p>主要內容2</p><p slot='footer'>底部信息信息</p></base-layout><base-layout><!-- 注意點:template臨時的包裹標簽最終不會渲染到頁面上 --> <template slot='header'><p>標題信息1</p><p>標題信息2</p></template><p>主要內容1</p><p>主要內容2</p><template slot='footer'><p>底部信息信息1</p><p>底部信息信息2</p></template></base-layout></div><script type="text/javascript" src="js/vue.js"></script><script type="text/javascript">/*具名插槽*/Vue.component('base-layout', {template: `<div><header>### 1、 使用 <slot> 中的 "name" 屬性綁定元素 指定當前插槽的名字<slot name='header'></slot></header><main><slot></slot></main><footer>### 注意點: ### 具名插槽的渲染順序,完全取決于模板,而不是取決于父組件中元素的順序<slot name='footer'></slot></footer></div>`});var vm = new Vue({el: '#app',data: {}});</script>
</body>
</html>
作用域插槽
- 父組件對子組件加工處理
- 既可以復用子組件的slot,又可以使slot內容不一致
<div id="app"> <fruit-list :list='list'> <template slot-scope='slotProps'><strong v-if='slotProps.info.id==3' class="current">{{slotProps.info.name}}
</strong><span v-else>{{slotProps.info.name}}
</span></template></fruit-list></div><script type="text/javascript" src="js/vue.js"></script><script type="text/javascript">Vue.component('fruit-list', {props: ['list'],template: `<div><li :key='item.id' v-for='item in list'>### 3、 在子組件模板中,<slot>元素上有一個類似props傳遞數據給組件的寫法msg="xxx",### 插槽可以提供一個默認內容,如果如果父組件沒有為這個插槽提供了內容,會顯示默認的內容。如果父組件為這個插槽提供了內容,則默認的內容會被替換掉<slot :info='item'>{{item.name}}</slot></li></div>`});var vm = new Vue({el: '#app',data: {list: [{id: 1,name: 'apple'},{id: 2,name: 'orange'},{id: 3,name: 'banana'}]}});</script>
</body>
</html>
購物車案例
1. 實現組件化布局
<div id="app"><div class="container"> <my-cart></my-cart></div></div><script type="text/javascript" src="js/vue.js"></script><script type="text/javascript"># 1、 把靜態頁面轉換成組件化模式# 1.1 標題組件 var CartTitle = {template: `<div class="title">我的商品</div>`}# 1.2 商品列表組件 var CartList = {# 注意點 : 組件模板必須是單個根元素 template: `<div><div class="item"><img src="img/a.jpg"/><div class="name"></div><div class="change"><a href="">-</a><input type="text" class="num" /><a href="">+</a></div><div class="del">×</div></div><div class="item"><img src="img/b.jpg"/><div class="name"></div><div class="change"><a href="">-</a><input type="text" class="num" /><a href="">+</a></div><div class="del">×</div></div><div class="item"><img src="img/c.jpg"/><div class="name"></div><div class="change"><a href="">-</a><input type="text" class="num" /><a href="">+</a></div><div class="del">×</div></div><div class="item"><img src="img/d.jpg"/><div class="name"></div><div class="change"><a href="">-</a><input type="text" class="num" /><a href="">+</a></div><div class="del">×</div></div><div class="item"><img src="img/e.jpg"/><div class="name"></div><div class="change"><a href="">-</a><input type="text" class="num" /><a href="">+</a></div><div class="del">×</div></div></div>`}# 1.3 商品結算組件 var CartTotal = {template: `<div class="total"><span>總價:123</span><button>結算</button></div>`}## 1.4 定義一個全局組件 my-cartVue.component('my-cart',{## 1.6 引入子組件 template: `<div class='cart'><cart-title></cart-title><cart-list></cart-list><cart-total></cart-total></div>`,# 1.5 注冊子組件 components: {'cart-title': CartTitle,'cart-list': CartList,'cart-total': CartTotal}});var vm = new Vue({el: '#app',data: {}});</script>
2、實現 標題和結算功能組件
- 標題組件實現動態渲染
- 從父組件把標題數據傳遞過來 即 父向子組件傳值
- 把傳遞過來的數據渲染到頁面上
- 結算功能組件
- 從父組件把商品列表list 數據傳遞過來 即 父向子組件傳值
- 把傳遞過來的數據計算最終價格渲染到頁面上
<div id="app"><div class="container"><my-cart></my-cart></div></div><script type="text/javascript" src="js/vue.js"></script><script type="text/javascript"># 2.2 標題組件 子組件通過props形式接收父組件傳遞過來的uname數據var CartTitle = {props: ['uname'],template: `<div class="title">{{uname}}的商品</div>`}# 2.3 商品結算組件 子組件通過props形式接收父組件傳遞過來的list數據 var CartTotal = {props: ['list'],template: `<div class="total"><span>總價:{{total}}</span><button>結算</button></div>`,computed: {# 2.4 計算商品的總價 并渲染到頁面上 total: function() {var t = 0;this.list.forEach(item => {t += item.price * item.num;});return t;}}}Vue.component('my-cart',{data: function() {return {uname: '張三',list: [{id: 1,name: 'TCL彩電',price: 1000,num: 1,img: 'img/a.jpg'},{id: 2,name: '機頂盒',price: 1000,num: 1,img: 'img/b.jpg'},{id: 3,name: '海爾冰箱',price: 1000,num: 1,img: 'img/c.jpg'},{id: 4,name: '小米手機',price: 1000,num: 1,img: 'img/d.jpg'},{id: 5,name: 'PPTV電視',price: 1000,num: 2,img: 'img/e.jpg'}]}},# 2.1 父組件向子組件以屬性傳遞的形式 傳遞數據# 向 標題組件傳遞 uname 屬性 向 商品結算組件傳遞 list 屬性 template: `<div class='cart'><cart-title :uname='uname'></cart-title><cart-list></cart-list><cart-total :list='list'></cart-total></div>`,components: {'cart-title': CartTitle,'cart-list': CartList,'cart-total': CartTotal}});var vm = new Vue({el: '#app',data: {}});</script>
3. 實現列表組件刪除功能
- 從父組件把商品列表list 數據傳遞過來 即 父向子組件傳值
- 把傳遞過來的數據渲染到頁面上
- 點擊刪除按鈕的時候刪除對應的數據
- 給按鈕添加點擊事件把需要刪除的id傳遞過來
- 子組件中不推薦操作父組件的數據有可能多個子組件使用父組件的數據 我們需要把數據傳遞給父組件讓父組件操作數據
- 父組件刪除對應的數據
<div id="app"><div class="container"><my-cart></my-cart></div></div><script type="text/javascript" src="js/vue.js"></script><script type="text/javascript">var CartTitle = {props: ['uname'],template: `<div class="title">{{uname}}的商品</div>`}# 3.2 把列表數據動態渲染到頁面上 var CartList = {props: ['list'],template: `<div><div :key='item.id' v-for='item in list' class="item"><img :src="item.img"/><div class="name">{{item.name}}</div><div class="change"><a href="">-</a><input type="text" class="num" /><a href="">+</a></div># 3.3 給按鈕添加點擊事件把需要刪除的id傳遞過來<div class="del" @click='del(item.id)'>×</div></div></div>`,methods: {del: function(id){# 3.4 子組件中不推薦操作父組件的數據有可能多個子組件使用父組件的數據 # 我們需要把數據傳遞給父組件 讓父組件操作數據 this.$emit('cart-del', id);}}}var CartTotal = {props: ['list'],template: `<div class="total"><span>總價:{{total}}</span><button>結算</button></div>`,computed: {total: function() {var t = 0;this.list.forEach(item => {t += item.price * item.num;});return t;}}}Vue.component('my-cart',{data: function() {return {uname: '張三',list: [{id: 1,name: 'TCL彩電',price: 1000,num: 1,img: 'img/a.jpg'},{id: 2,name: '機頂盒',price: 1000,num: 1,img: 'img/b.jpg'},{id: 3,name: '海爾冰箱',price: 1000,num: 1,img: 'img/c.jpg'},{id: 4,name: '小米手機',price: 1000,num: 1,img: 'img/d.jpg'},{id: 5,name: 'PPTV電視',price: 1000,num: 2,img: 'img/e.jpg'}]}},# 3.1 從父組件把商品列表list 數據傳遞過來 即 父向子組件傳值 template: `<div class='cart'><cart-title :uname='uname'></cart-title># 3.5 父組件通過事件綁定 接收子組件傳遞過來的數據 <cart-list :list='list' @cart-del='delCart($event)'></cart-list><cart-total :list='list'></cart-total></div>`,components: {'cart-title': CartTitle,'cart-list': CartList,'cart-total': CartTotal},methods: {# 3.6 根據id刪除list中對應的數據 delCart: function(id) {var index = this.list.findIndex(item=>{return item.id == id;});this.list.splice(index, 1);}}});var vm = new Vue({el: '#app',data: {}});</script>
</body>
</html>
4. 實現組件更新數據功能 上
- 將輸入框中的默認數據動態渲染出來
- 輸入框失去焦點的時候 更改商品的數量
- 子組件中不推薦操作數據 把這些數據傳遞給父組件 讓父組件處理這些數據
- 父組件中接收子組件傳遞過來的數據并處理
<div id="app"><div class="container"><my-cart></my-cart></div></div><script type="text/javascript" src="js/vue.js"></script><script type="text/javascript">var CartTitle = {props: ['uname'],template: `<div class="title">{{uname}}的商品</div>`}var CartList = {props: ['list'],template: `<div><div :key='item.id' v-for='item in list' class="item"><img :src="item.img"/><div class="name">{{item.name}}</div><div class="change"><a href="">-</a># 1. 將輸入框中的默認數據動態渲染出來# 2. 輸入框失去焦點的時候 更改商品的數量 需要將當前商品的id 傳遞過來<input type="text" class="num" :value='item.num' @blur='changeNum(item.id, $event)'/><a href="">+</a></div><div class="del" @click='del(item.id)'>×</div></div></div>`,methods: {changeNum: function(id, event){# 3 子組件中不推薦操作數據 因為別的組件可能也引用了這些數據# 把這些數據傳遞給父組件 讓父組件處理這些數據this.$emit('change-num', {id: id,num: event.target.value});},del: function(id){this.$emit('cart-del', id);}}}var CartTotal = {props: ['list'],template: `<div class="total"><span>總價:{{total}}</span><button>結算</button></div>`,computed: {total: function() {var t = 0;this.list.forEach(item => {t += item.price * item.num;});return t;}}}Vue.component('my-cart',{data: function() {return {uname: '張三',list: [{id: 1,name: 'TCL彩電',price: 1000,num: 1,img: 'img/a.jpg'}]},template: `<div class='cart'><cart-title :uname='uname'></cart-title># 4 父組件中接收子組件傳遞過來的數據 <cart-list :list='list' @change-num='changeNum($event)' @cart-del='delCart($event)'></cart-list><cart-total :list='list'></cart-total></div>`,components: {'cart-title': CartTitle,'cart-list': CartList,'cart-total': CartTotal},methods: {changeNum: function(val) {this.list.some(item=>{if(item.id == val.id) {item.num = val.num;return true;}});},delCart: function(id) {var index = this.list.findIndex(item=>{return item.id == id;});this.list.splice(index, 1);}}});var vm = new Vue({el: '#app',data: {}});</script>
5. 實現組件更新數據功能 下
- 子組件通過一個標識符來標記對用的用戶點擊 + - 或者輸入框輸入的內容
- 父組件拿到標識符更新對應的組件
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Document
</title><style type="text/css">.container {}.container .cart {width: 300px;margin: auto;}.container .title {background-color: lightblue;height: 40px;line-height: 40px;text-align: center; }.container .total {background-color: #FFCE46;height: 50px;line-height: 50px;text-align: right;}.container .total button {margin: 0 10px;background-color: #DC4C40;height: 35px;width: 80px;border: 0;}.container .total span {color: red;font-weight: bold;}.container .item {height: 55px;line-height: 55px;position: relative;border-top: 1px solid #ADD8E6;}.container .item img {width: 45px;height: 45px;margin: 5px;}.container .item .name {position: absolute;width: 90px;top: 0;left: 55px;font-size: 16px;}.container .item .change {width: 100px;position: absolute;top: 0;right: 50px;}.container .item .change a {font-size: 20px;width: 30px;text-decoration:none;background-color: lightgray;vertical-align: middle;}.container .item .change .num {width: 40px;height: 25px;}.container .item .del {position: absolute;top: 0;right: 0px;width: 40px;text-align: center;font-size: 40px;cursor: pointer;color: red;}.container .item .del:hover {background-color: orange;}</style>
</head>
<body><div id="app"><div class="container"><my-cart></my-cart></div></div><script type="text/javascript" src="js/vue.js"></script><script type="text/javascript">var CartTitle = {props: ['uname'],template: `<div class="title">{{uname}}的商品</div>`}var CartList = {props: ['list'],template: `<div><div :key='item.id' v-for='item in list' class="item"><img :src="item.img"/><div class="name">{{item.name}}</div><div class="change"># 1. + - 按鈕綁定事件 <a href="" @click.prevent='sub(item.id)'>-</a><input type="text" class="num" :value='item.num' @blur='changeNum(item.id, $event)'/><a href="" @click.prevent='add(item.id)'>+</a></div><div class="del" @click='del(item.id)'>×</div></div></div>`,methods: {changeNum: function(id, event){this.$emit('change-num', {id: id,type: 'change',num: event.target.value});},sub: function(id){# 2 數量的增加和減少通過父組件來計算 每次都是加1 和 減1 不需要傳遞數量 父組件需要一個類型來判斷 是 加一 還是減1 以及是輸入框輸入的數據 我們通過type 標識符來標記 不同的操作 this.$emit('change-num', {id: id,type: 'sub'});},add: function(id){# 2 數量的增加和減少通過父組件來計算 每次都是加1 和 減1 不需要傳遞數量 父組件需要一個類型來判斷 是 加一 還是減1 以及是輸入框輸入的數據 我們通過type 標識符來標記 不同的操作this.$emit('change-num', {id: id,type: 'add'});},del: function(id){this.$emit('cart-del', id);}}}var CartTotal = {props: ['list'],template: `<div class="total"><span>總價:{{total}}</span><button>結算</button></div>`,computed: {total: function() {var t = 0;this.list.forEach(item => {t += item.price * item.num;});return t;}}}Vue.component('my-cart',{data: function() {return {uname: '張三',list: [{id: 1,name: 'TCL彩電',price: 1000,num: 1,img: 'img/a.jpg'},{id: 2,name: '機頂盒',price: 1000,num: 1,img: 'img/b.jpg'},{id: 3,name: '海爾冰箱',price: 1000,num: 1,img: 'img/c.jpg'},{id: 4,name: '小米手機',price: 1000,num: 1,img: 'img/d.jpg'},{id: 5,name: 'PPTV電視',price: 1000,num: 2,img: 'img/e.jpg'}]}},template: `<div class='cart'><cart-title :uname='uname'></cart-title> # 3 父組件通過事件監聽 接收子組件的數據 <cart-list :list='list' @change-num='changeNum($event)' @cart-del='delCart($event)'></cart-list><cart-total :list='list'></cart-total></div>`,components: {'cart-title': CartTitle,'cart-list': CartList,'cart-total': CartTotal},methods: {changeNum: function(val) {#4 分為三種情況:輸入框變更、加號變更、減號變更if(val.type=='change') {this.list.some(item=>{if(item.id == val.id) {item.num = val.num;return true;}});}else if(val.type=='sub'){this.list.some(item=>{if(item.id == val.id) {item.num -= 1;return true;}});}else if(val.type=='add'){this.list.some(item=>{if(item.id == val.id) {item.num += 1;return true;}});}}}});var vm = new Vue({el: '#app',data: {}});</script>
</body>
</html>
總結
以上是生活随笔為你收集整理的vue-day03-vue组件化开发的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。