Vue开发小技巧

一、数据共享与绑定

1、子组件调用父组件数据:.sync

<comp :foo.sync="bar"></comp>

会被扩展为:

<comp :foo="bar" @update:foo="val => bar = val"></comp>

当子组件需要更新 foo 的值时,它需要显式地触发一个更新事件:

this.$emit('update:foo', newValue)

猛一看不明白,下边我么通过一个实例(弹窗的关闭事件)来说明这个代码到底是怎么运用的。

<template>
    <div class="details">
        <myComponent :show.sync='valueChild' style="padding: 30px 20px 30px 5px;border:1px solid #ddd;margin-bottom: 10px;"></myComponent>
        <button @click="changeValue">toggle</button>
    </div>
</template>
<script>
import Vue from 'vue'
Vue.component('myComponent', {
      template: `<div v-if="show">
                    <p>默认初始值是{{show}},所以是显示的</p>
                    <button @click.stop="closeDiv">关闭</button>
                 </div>`,
      props:['show'],
      methods: {
        closeDiv() {
          this.$emit('update:show', false); //触发 input 事件,并传入新值
        }
      }
})
export default{
    data(){
        return{
            valueChild:true,
        }
    },
    methods:{
        changeValue(){
            this.valueChild = !this.valueChild
        }
    }
}
</script>

2、父组件调用子组件函数$refs

当DOM渲染完成后,父组件可以通过 this.$refs[‘InspectionTable’]调用子组件的函数,但是子组件使用v-if的情况下不适用,需要子组件完成实例化即可调用。

// 父组件
<template>
	<div>
	   <inspection-table  ref="InspectionTable"/>
	</div>
</template>
import InspectionTable from './components/InspectionTable'
<script>
export default {
    components: {
        InspectionTable
    },
    methods: {
       ciick() {
            console.log("执行")
            const obj={}
            this.$refs['InspectionTable'].tableRowClick(obj)
        }
    }
}
</script>
// 子组件文件名inspectionTable
<template>
	<div>
	   子组件
	</div>
</template>
<script>
export default {
    methods: {
       tableRowClick(obj) {
            console.log(obj)
        }
    }
}
</script>

3、子组件调用父组件函数$emit

父组件通过@@to-detail=把函数传递给子组件,通过子组件 this.$emit(‘to-detail’, obj)触发父组件函数

// 父组件
<template>
	<div>
       <inspection-table  @to-detail="changeRightPanel" />
	</div>
</template>
import InspectionTable from './components/InspectionTable'
<script>
export default {
    components: {
        InspectionTable
    },
    methods: {
       changeRightPanel(obj) {
		    console.log(obj)
		}
    }
}
</script>
// 子组件文件名inspectionTable
<template>
	<div>
       <el-button class="back" type="primary" size="small" plain icon="el-icon-arrow-left" @click="click()">返回</el-button>
	</div>
</template>
<script>
export default {
    methods: {
       click() {
            const obj={}
		    this.$emit('to-detail', obj)
		}
    }
}
</script>

简单例子

<hello @pfn="parentFn"></hello>

<script>
  Vue.component('hello', {
    template: '<button @click="fn">按钮</button>',
    methods: {
      // 子组件:通过$emit调用
      fn() {
        this.$emit('pfn', '这是子组件传递给父组件的数据')
      }
    }
  })
  new Vue({
    methods: {
      // 父组件:提供方法
      parentFn(data) {
        console.log('父组件:', data)
      }
    }
  })
</script>

4、父与子和子与子的数据共享$on

子组件A:发送放使用$emit自定义事件把数据带过去。

<template>
  <div>
    <span>A组件-{{msg}}</span>
    <input type="button" value="把A组件数据传递给B" @click="send">
  </div>
</template>
<script>
  import eventBus from './eventBus';  //需要引入父组件eventBus,可以理解为引入父组件实例 
  export default{
    data(){
      return{
        msg:{
          a:'111',
          b:'222'
        }
      }
    },
    methods:{
      send(){
        eventBus.$emit('aevent',this.msg)  // 通过父组件去广播
      }
    }
  }
</script>

子组件B:接收方通过$on监听自定义事件的callback接收数据

<template>
  <div>
    <span>B组件,A传的数据为--{{msg}}</span>
  </div>
</template>
<script>
  import eventBus from './eventBus.vue'  //需要引入父组件eventBus,可以理解为引入父组件实例 
  export default {
    data(){
      return{
        msg:''
      }
    },
    mounted(){
      eventBus.$on('aevent',(val)=>{//监听事件aevent,回调函数要使用箭头函数。
        console.log(val);//打印结果;我是a组件的数据。
      })
    }
  }
</script>

父组件eventBus:

<template>  
  <div>
    <childa></childa>
    <br/>
    <childb></childb>
  </div>
</template>
<script>
  import childa from './childa.vue';
  import childb from './childb.vue';
  export default{
    componets:{
      childa,
      childb
    },
    data(){
      return{
        msg:''
      }
    },
    created () {
      this.$on('aevent',(val)=> {   // 当然父组件也可以监听到
          console.log(val)
      })
  },
  }
</script>

5、vuex的数据共享和监听$store

store的定义,路径:src/store/modules/drainage-facilities/sluice-pump/storeFileName.js

const state = {
    userInfo:{
    	id:' ',
    	name:' '
	}
}
const mutations = {
    setUserInfo(state, data) {
        state.userInfo= data
    }
}
const actions = {

}
export default {
    namespaced: true,
    state,
    actions,
    mutations
}

vue页面使用,路径:src/views/drainage-facilities/sluice-pump/problem-circulation/components/PumpPopup.vue

<template>
  <div>
    <span>{{userInfo1.name}}</span>
    <imput v-model="userInfo2.name"></span>
  </div>
</template>
<script>
  import { mapState } from 'vuex'  //需要引入
  export default {
    data(){
      return{
        userInfo3:''
      }
    },
    computed: {
        ...mapState({  //第1种获取方法
            userInfo: state => state.storeFileName.userInfo 
        }),
        userInfo2:{ //第2种获取方法
	      get(){
	        	console.log('取值时调用')
	        	return this.$store.state.storeFileName.userInfo
		   },
		   set(value){
	          	console.log('值改变时调用')
	            this.$store.commit('setPhoneNumber',value)   //改变值,改变后--1,--2,---3都会调用,同一个内存地址
	   		}
	   }
     },
     watch: {
        'userInfo.name': function(val) {
            console.log('监控值改变时调用')-----1
        },
        'userInfo2.name': function(val) {
            console.log('监控值改变时调用')-----2
        },
        '$store.state.storeFileName.userInfo': function(val) {
            console.log('监控值改变时调用')-----3
        }
    },
    mounted(){
     	this.userInfo3=this.$store.state.storeFileName.userInfo
    }
  }
</script>

6、vuex的双向数据绑定$store set commit

我在vue项目使用store存储变量,在页面input进行属性的双向绑定时,报出Computed property “route” was assigned to but it has no setter的错误,查找很多原因,参考官方文件找到了 解决方法。要在computed中添加get和set两个方法。

<input type="text" v-model="phoneNumber">

computed:{
    phoneNumber:{
      get(){
        console.log('取值时调用')
        return this.$store.state.phoneNumber
	   },
      set(value){
       console.log('值改变时调用')
       this.$store.commit('setPhoneNumber',value)
   		}
    }
  }

state: {
    phoneNumber:'', 
  },
  mutations: {
    setPhoneNumber(state,val){
      state.phoneNumber=val
    }
}

7、检查组件是否绑定了事件

父组件

<ag-panel-box  @header-click="showPopup()"></ag-panel-box>

子组件ag-panel-box

export default {
    name: 'AgPanelBox',
    computed: {
        headerClick() {
            // 检查是否绑定了事件
            return Boolean(this.$listeners['header-click'])
        }
    },
}

8、组件的数据状态传递

父组件

<joint-duty-popup :visible.sync="dialogVisible" :row-data="dialogRowData" />

子组件

<template>
    <el-dialog title="签到信息" :visible.sync="dialogVisible">
        弹窗内容
        <div class="btn-list">
            <el-button size="mini" @click="cancelFun()">取消</el-button>
            <el-button type="primary" size="mini" @click="confirmFun()">确定</el-button>
        </div>
    </el-dialog>
</template>

<script>
export default {
    name: 'JointDutyPopup',
    components: {

    },
    props: {
        visible: {
            type: Boolean,
            default: true
        },
        rowData: {
            type: Object,
            default: () => {}
        }
    },
    data() {
        return {

        }
    },
    computed: {
        dialogVisible: {
            get() {
                return this.visible
            },
            set(val) {
                this.$emit('update:visible', val)
            }
        }
    },
    watch: {
        visible: {
            handler(val) {
                this.dialogVisible = val
                console.log(this.dialogVisible)
            },
            deep: true
        },
        rowData: { //  初始化
            handler(val) {
                console.log(val)
            },
            deep: true,
            immediate: true
        }
    },
    mounted() {

    },
    methods: {
        cancelFun() {
            this.dialogVisible = false
        },
        confirmFun() {
            // if (this.checkNodes.length === 0) {
            //     this.$message.error('未选择任何内容!')
            // } else {
            //     this.$emit('change', this.checkNodes)
            //     this.treeVisible = false
            // }
        }
    }

}
</script>

<style lang="scss" scoped>
.btn-list {
    width: 100%;
    margin-top: 10px;
    text-align: right;
}
</style>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GY程序源

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值