vue组件通信
- 父子组件通过属性传递数据
- 父传子
<Cart :name="name" :cart="cart"></Cart> // 子组件 <div> 购物车 </div> export default { name: 'Cart', props:['name',"cart"], data () { return { } }, methods: { } } // 校验 props:{ name:{ type:String, required:true }, cart:{ type:Array } },
-
子通知父改变:$emit 实现子组件向父组件通信。
// $emit 绑定一个自定义事件event vm.$emit( event, arg ) // 子组件监听自定义事件titleChanged <template> <header> <h1 @click="changeTitle"></h1>//绑定一个点击事件 </header> </template> <script> export default { name: 'app-header', data() { return { title:"Vue.js Demo" } }, methods:{ changeTitle() { this.$emit("titleChanged","子向父组件传值");//自定义事件 传递值“子向父组件传值” } } } </script> // 父组件响应titleChanged事件 <template> <div id="app"> <app-header v-on:titleChanged="updateTitle" ></app-header>//与子组件titleChanged自定义事件保持一致,updateTitle($event)接受传递过来的文字 <h2></h2> </div> </template> <script> import Header from "./components/Header" export default { name: 'App', data(){ return{ title:"传递的是一个值" } }, methods:{ updateTitle(e){ //声明这个函数 this.title = e; } }, components:{ "app-header":Header, } } </script>
- 父传子
- 两个任意组件传递
-
使用总线机制传递,vue每个实例都有订阅/发布模式的实现,使用$on和$emit来使用
// main.js Vue.prototype.$bus = new Vue // App.vue 父组件 addCart(i){ const good = this.goods[i] this.$bus.$emit('addCart',good) } // Cart.vue 子组件 created() { // 监听一下父组件添加商品事件 this.$bus.$on("addCart", good => { const ret = this.cart.find(v => v.text == good.text); if (ret) { ret.count += 1; } else { this.cart.push({ ...good, active: true, count: 1 }); } }); },
- 原理:发布和订阅模式=>实现Bus类
class Bus{ constructor(){ // { // eventName1:[fn1,fn2], // eventName2:[fn3,fn4], // } this.callbacks = {} } $on(name,fn){ this.callbacks[name] = this.callbacks[name] || [] this.callbacks[name].push(fn) } $emit(name,args){ if(this.callbacks[name]){ // 存在 遍历所有callback this.callbacks[name].forEach(cb=> cb(args)) } } } // 挂载到vue原型上 Vue.prototype.$bus = new Bus()
- 使用
// 触发 eventBus(){ this.$bus.$emit('event-bus','测试eventBus') } // 监听 this.$bus.$on("event-bus",msg=>{ this.msg = '接收event-bus消息:'+ msg })
-
- 状态管理最佳实践 vuex
- 在vue.config.js中配置mock数据=>cli 3中的
//这里是全局配置可以覆盖webpack配置 module.exports = { configureWebpack: { devServer: { // 这里是中间件,相当于接口 before(app) { // koa写法 app.get('/api/goods', function(req,res){ res.json({ code:0, list: [ { id: 1, text: "华为P30", price: 1000 }, { id: 2, text: "OPPO Rena 10X", price: 1000 } ] }) }) } }, } } // 在app.vue中使用接口获取数据 async created() { // 创建钩子,组件创建完成执行一次 setTimeout(() => { this.showName = true; }, 1000); // 查询产品列表 try { const response = await axios.get("/api/goods"); // console.log(response); this.goods = response.data.list; } catch (error) { // 错误处理 } // 不用await // axios.get("/api/goods").then(resp => { // this.goods = response.data.list; // }).catch(err => { // // 错误处理 // }) },
- 数据持久化localStorage+vue监听器=>setItem/getItem
// cart.vue data() { return { cart: JSON.parse(localStorage.getItem("cart")) || [] }; }, watch: { cart: { handler(n, o) { localStorage.setItem("cart", JSON.stringify(n)); }, deep: true } }
-
computed
//可以对data进行复杂的逻辑运算,数据变化才会执行,优于watch <tr> <td></td> <td colspan='2'>/ 8</td> <td colspan='2'></td> </tr>
computed:{ total(){ let num = 0 this.cart.forEach(v=>{ if(v.active){ num+= v.price*v.count } }) return num //.... //return this.cart.reduce((sum,v)=>{ // if(v.active){ // return sum + v.price*v.count // } // },0) }, count(){ return this.cart.length }, activeCount(){ return this.cart.filter(v=>v.active).length } },