父子组件传值之(子传父)

当我们在需要把子页面的数据传递给父页面时,就需要用到子传父通信。

下面是要把封装好的验证码组件放到父组件里面使用,由于是子组件里面生成的验证码,所以这里要把子组件的值传递到父组件里面去,用于校验判断。

下面是细节步骤:

1. 首先我们是要把子组件data里面的checkCode传递到父组件里

  watch:{  
    checkCode(newvalue,oldvalue){
      this.$emit("send",newvalue,oldvalue)
    }
  },

// 这里用watch监听checkCode值,一旦变化了就通过this.$emit()提交数据,
// 也可以在mounted函数里,通过this.$emit()传递过去,看实际的需求。
// 第一个参数是自定义的事件,注意这里的事件必须要与在父组件给子组件注册的事件保持一致。
// 后面第二个第三个参数就是需要传递过去的值,这里可以传递过去很多值,
// 在父组件里接受就可以了。

2. 在父组件里找到引用子组件的地方。

<Input v-model="formValidate.authCode" placeholder="请输入验证码" clearable>
   <Icon custom="iconfont icon-dunpai" slot="prefix" />
   <span slot="append">
      <securityCode @send="incident" slot="suffix"></securityCode>
   </span>
</Input>

注意:  这里   <securityCode @send="incident" slot="suffix"></securityCode>定义的事件必须要与子组件里面提交的事件一直  this.$emit("send",newvalue,oldvalue)。

3. 最后在事件的方法里就可以接受传递的参数了。

incident(newvalue){
  this.identifyingCode = newvalue
},

注意:这里的newvalue形参值要与子组件提交的形参值保持一致,无论后面传递的有多少个参数,接受时的参数名必须要一致。       this.$emit("send",newvalue,oldvalue)

最后就可以在父组件里使用子组件的值了。

子组件完整页面:

<style lang="less" scoped>
</style>

<template>
  <div>
    <!-- 画布用于展示验证码 -->
    <canvas class="codeCanvas" ref="checkCode" @click="getCode"></canvas>
  </div>
</template>

<script>
export default {
  name:"securityCode",
  data(){
    return {
      inputCode: '',  // 输入的值
      checkCode: '',  // 图片验证码的值
      // canvas各种设置
      cvs: {
        w: 74, // 给出默认宽度  宽度会在图片绘制时根据长度更改
        h: 30,  // 高 与input保持一致
        fontSize: 22,   // 字体大小
        // 字符串生成范围
        str: '1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNM',  
        len: 4, // 字符串长度 
        line: 3 // 噪音线个数
      }
    }
  },
  mounted(){
    this.getCode();
  },
  watch:{
    checkCode(newvalue,oldvalue){
      this.$emit("send",newvalue,oldvalue)
    }
  },
  methods:{
    onClick(name){
      this.status = name
    },
 
    getCode(){
      // vue的话可直接用$refs取值,不用vue的话可绑定id然后通过document处理
      let domCvs = this.$refs.checkCode;
      this.drawCode(domCvs);
    },
 
    // 随机整数生成器,范围[0, max)
    rInt(max) {
        return Math.floor(Math.random() * 100000 % max);
    },
 
    // 生成随机字符串
    rCode() {
        let code = '';
        let len = this.cvs.len;
        let strLen = this.cvs.str.length;
        for(let i = 0; i < len; i ++) {
            code += this.cvs.str.charAt(this.rInt(strLen));
        }
        this.checkCode = code;
        return code;
    },
 
 
    // 生成随机颜色 rgba格式
    rColor() {
        let a = ((Math.random()*5 + 5) / 10).toFixed(2);
        return `rgba(${this.rInt(256)}, ${this.rInt(256)}, ${this.rInt(256)}, ${a})`
    },
 
 
 
    // 验证码图片绘制
    drawCode(domCvs) {
        let _this = this;
        // 随机字符串
        let checkCode = this.rCode();
        // 宽设置
        this.cvs.w = 1 + this.cvs.fontSize * this.cvs.len;
 
        // 判断是否支持canvas
        if(domCvs !== null && domCvs.getContext && domCvs.getContext('2d')){
            // 设置显示区域大小
            domCvs.style.width = _this.cvs.w;
            // 设置画板宽高
            domCvs.setAttribute('width', _this.cvs.w);
            domCvs.setAttribute('height', _this.cvs.h);
            // 画笔
            let pen = domCvs.getContext('2d');
            // 背景: 颜色  区域
            pen.fillStyle = '#eee';
            pen.fillRect(0, 0, _this.cvs.w, _this.cvs.h);
            // 水平线位置
            pen.textBaseline = 'middle';   // top middle bottom
            // 内容
            for(let i = 0; i < _this.cvs.len; i ++) {
                pen.fillStyle = _this.rColor(); // 随机颜色
                pen.font = `bold ${_this.cvs.fontSize}px 微软雅黑`; // 字体设置
                // 字符绘制: (字符, X坐标, Y坐标)
                pen.fillText(checkCode.charAt(i), 10 + _this.cvs.fontSize * i, 15 + _this.rInt(10));   
            }
            // 噪音线
            for(let i = 0; i < _this.cvs.line; i ++) {
                // 起点
                pen.moveTo(_this.rInt(_this.cvs.w) / 2, _this.rInt(_this.cvs.h));
                // 终点
                pen.lineTo(_this.rInt(_this.cvs.w), _this.rInt(_this.cvs.h));
                // 颜色
                pen.strokeStyle = _this.rColor();
                // 粗细
                pen.lineWidth = '2';
                // 绘制
                pen.stroke();
            }
 
        } else {
            this.$message.error('不支持验证码格式,请升级或更换浏览器重试');
        }
    },
  }
}
</script>

父组件完整页面:

<style lang="less" scoped>
// @import "//at.alicdn.com/t/font_2901774_k83z065422.css";
@import "//at.alicdn.com/t/font_2901774_3y46gmvnbhh.css";
*{
  margin: 0;
  padding: 0;
}
.main{
  overflow: auto; // 超出时 产生滚动条
}
.w{
  width: 960px;
  padding: 0 100px;
  margin: 0 auto;
}
.card{
 position:relative;
 top: 130px;
 left: 0px;
}
.steps{
  margin-top: 180px;
}
 /deep/ .ivu-tabs-nav .ivu-tabs-tab{
  padding:8px 70px;
}
/deep/ .ivu-tabs-tabpane {
  width: 100% !important;
}
/deep/ .ivu-input-prefix i, .ivu-input-suffix i{
  line-height: 30px;
  font-size: 18px;
}
/deep/ .ivu-input-group-append, .ivu-input-group-prepend{
  padding: 0px 0px;
  line-height: 0;
}
.icon_dp{
  position: absolute;
  top:8px;
  left: 8px;
  font-weight: 700;
  z-index: 3;
}
.span_code{
  font-size: 14px;
  color: #5ec3fc;
}
.icon_email{
  position: absolute;
  top:8px;
  left: 8px;
  font-size: 18px;
  z-index: 3;
}
.icon_xiao{
  position: relative;
  top: -3px;
  left: 0px;
  color: lime;
}
</style>

<template>
  <div class="mian">
    <Card class="w card" >
      <Tabs v-model="tabSet">
        <TabPane label="①账号验证" :disabled="disabled" name="账号验证">
          <Form ref="accountNumber" :label-width="180" :model="formValidate"  :rules="verify">
            <Row style="margin-top:20px;">
              <Col span="18">
                <FormItem prop="mailbox">
                  <Input prefix="md-phone-portrait" v-model="formValidate.mailbox" placeholder="请输入邮箱" clearable/>
                </FormItem>
              </Col>
            </Row>
            <Row>
              <Col span="18">
                <FormItem prop="authCode">
                  <Icon class="icon_dp" custom="iconfont icon-dunpai"  />
                  <Input v-model="formValidate.authCode" placeholder="请输入验证码" clearable>
                    <Icon custom="iconfont icon-dunpai" slot="prefix" />
                    <span slot="append">
                      <securityCode @send="incident" slot="suffix"></securityCode>
                    </span>
                  </Input>
                </FormItem>
              </Col>
            </Row>
            <Row>
              <Col span="18">
                <FormItem prop="sendVerificationCode">
                  <Icon class="icon_email" type="ios-mail" />
                  <Input placeholder="请输入短信验证码" v-model="formValidate.sendVerificationCode" clearable>
                    <Icon type="ios-mail" slot="prefix" />
                    <Button slot="append" class="span_code" :disabled="verificationCodeDisabled" @click="resendVerificationCode">{
   
   {noteCode}}</Button>
                  </Input>
                </FormItem>
              </Col>
            </Row>
            <Row>
              <Col span="18">
                <FormItem>
                  <Button type="primary" long @click="nextStep('accountNumber')">下一步</Button>
                </FormItem>
              </Col>
            </Row>
          </Form>
        </TabPane>
        <TabPane label="②重置密码" :disabled="disabled2" name="重置密码">
          <Form :label-width="180" :model="replacement" ref="form" :rules="examine">
            <Row style="margin-top:20px;">
              <Col span="18">
                <FormItem prop="password">
                  <Input v-model="replacement.password" prefix="ios-lock" password type="password" placeholder="请输入密码"></Input>
                </FormItem>
              </Col>
            </Row>
            <Row>
              <Col span="18">
                <FormItem prop="confirmPassword">
                  <Input v-model="replacement.confirmPassword" prefix="ios-lock" password type="password" placeholder="请确认密码"></Input>
                </FormItem>
              </Col>
            </Row>
            <Row>
              <Col span="18">
                <FormItem>
                  <Button style="width:47%;" type="primary" @click="nextStepAgain('form')">下一步</Button>
                  <Button style="width:47%;margin-left:20px;" @click="reset">重置</Button>                  
                </FormItem>
              </Col>
            </Row>
          </Form>
        </TabPane>
        <TabPane label="③完成设置" :disabled="disabled3" name="完成设置">
          <Form :label-width="180">
            <Row style="margin-top:20px;">
              <Col span="18">
                <FormItem>
                  <p style="margin-left:55px;">
                    <Icon custom="iconfont icon-iconweixiao" class="icon_xiao"/>
                    新登录密码重置成功,请重新登录!
                  </p>
                </FormItem>
              </Col>
            </Row>
            <Row style="margin-top:50px;">
              <Col span="18">
                <FormItem>
                  <Button type="primary" long @click="logAgain">重新登录</Button>
                </FormItem>
              </Col>
            </Row>            
          </Form>
        </TabPane>
      </Tabs>
    </Card>
  </div>
</template>

<script>
import securityCode from "./code/securityCode.vue"
export default {
  components:{
    securityCode
  },
  computed:{

  },
  data(){
    const validateCode = (rule, value, callback) =>{
      let errors = []
      if(value !== this.identifyingCode ){
        callback("验证码不正确请重新输入")
      }
      callback(errors)
    }

    const confirmNewPasswordValidate = (rule, value, callback) =>{
      let errors = []
      if(value !== this.replacement.password){
        callback("两次密码输入不一致")
      }
      callback(errors)
    }
    return {
      // ------重置密码------
      replacement:{
        password:"", // 密码
        confirmPassword:"", // 确认密码
      },
      examine:{
        password:[ {required: true, message: '请输入密码', trigger: 'blur'} ],
        confirmPassword:[ 
          {required: true, message: '请确认密码', trigger: 'blur'},
          {validator:confirmNewPasswordValidate,message:"两次密码输入不一致",trigger: 'blur'}
        ]
      },

      // ------账号验证------
      formValidate:{
        mailbox:"", //邮箱
        authCode:"",// 输入的验证码
        sendVerificationCode:"", // 发送验证码
      },
      verify:{
        mailbox:[ 
          { required: true, message:'请填写邮箱', trigger: 'blur' }, 
          { type: 'email', message: '邮箱格式不正确', trigger: 'blur' }
        ],
        authCode:[
          { required: true, message: '请填写验证码', trigger: 'blur' },
          { validator:validateCode, message:'验证码不正确请重新输入',trigger: 'blur' }
        ],
        sendVerificationCode:[
          { required: true, message:'请填写短信验证码', trigger: 'blur' },
        ]
      },

      sum:60,
      timer:"", 
      noteCode:"发送验证码", 
      verificationCodeDisabled:false, // 发送验证码是否禁用
      identifyingCode:"", // 图形验证码
      tabSet:"重置密码",
      disabled:false, // 账号验证
      disabled2:true,  // 重置密码
      disabled3:true, // 完成设置
    }
  },
  mounted(){
    this.tabSet = "账号验证"
    this.incident()
  },
  methods:{
    resendVerificationCode(){
      this.verificationCodeDisabled = true
      this.timer = setInterval(() => {
        this.noteCode =  this.sum+" 秒后发送"
        this.sum--
        if(this.sum < -1){
          clearInterval(this.timer)
          this.noteCode = "发送验证码"
          this.verificationCodeDisabled = false
          this.sum = 60
        }
      }, 1000)
    },

    incident(newvalue){
      this.identifyingCode = newvalue
    },

    nextStep(name){
      this.$refs[name].validate((valid)=>{
        if(valid){
          this.disabled = true
          this.disabled2 = false
          this.disabled3 = true
          this.tabSet = "重置密码"
          clearInterval(this.timer)
        }
      })
    },

    nextStepAgain(name){
      this.$refs[name].validate((valid)=>{
        if(valid){
          this.disabled = true
          this.disabled2 = true
          this.disabled3 = false
          this.tabSet = "完成设置"          
        }
      })
    },

    reset(){
      this.replacement.password = ""
      this.replacement.confirmPassword = ""
    },

    logAgain(){
      window.open("#/login")
    },
  }
}
</script>

效果图:

猜你喜欢

转载自blog.csdn.net/weixin_48674314/article/details/121055434