Vue 2.x折腾记 - (20) JSX在业务中的具体实践以及跟React书写的差异化

栏目: 编程语言 · 发布时间: 6年前

内容简介:写JSX很自然,毕竟是自家倡导的Vue的jsx,能够支持部分vue独有的特性,比如拿到其他的写法上和react差不多,具体一些我已经特性如下:

写JSX很自然,毕竟是自家倡导的

  • 类名需要做 classname
  • props 的传递可以直接 {...props}
  • 节点的传递,通过 {props.children} 渲染
  • 支持空节点包括同级节点, <><child/><child2/></>
  • 支持花括号直接遍历数组生成节点, {list.map(item=>(<a {...item.props}/>)}
  • 函数式组件支持非常好

Vue

Vue的jsx,能够支持部分vue独有的特性,比如拿到 computed , 指令及自定义事件;

其他的写法上和react差不多,具体一些我已经特性如下:

  • 类名依旧可以直接class,其他对象和数组的支持跟react大同小异
  • props 的快速传递需要包括到 attrs
    • 若是要快速传递所有父级 props , {...{attrs:this.$attrs}}
      • $attrs 会汇总除了class和style之外的所有props
  • 节点的传递可以通过 slots ,比如最常见的具名 <div>{this.$slots.default}</div>
    • 传递变量( scope-slots ),父用 this.$scopedSlots.default 这类来传递一个对象
  • 同级节点不支持,必须最外层有包裹层
  • 不支持花括号内直接遍历(我用的时候会报错),单独抽离出一个函数式组件
  • 函数式组件支持模板和js两种写法,简单的用法基本和react一致

代码体现

Demo1: 自定义事件

结合第二个栗子就能串起来

<script>
import png_default_scan_avatar from '@assets/cert/face_cert/scan_avatar.png';
import CertFooter from '../components/CertFooter';
export default {
  components: {
    CertFooter
  },
  name: 'face_cert',
  methods: {
    nextStep(isClick) {
      if (isClick) {
        console.log('11');
      }
      // 下一步验证
      // this.$router.push({ name: 'cert_step4' });
    }
  },
  render() {
    const DefaultScanAvatar = () => {
      return (
        <div class="default-scan-avatar">
          <div class="default-scan-avatar__desrc">请正对手机,确保光线充足</div>
          <img class="default-scan-avatar__img" src={png_default_scan_avatar} />
        </div>
      );
    };
    return (
      <div class="face-cert-page">
        <DefaultScanAvatar />
        <cert-footer text={'开始刷脸'} disabled={false} on-button-click={e => this.nextStep(e)} />
      </div>
    );
  }
};
</script>

<style lang="scss" scoped>
.face-cert-page {
  background-color: #fff;
  height: 100%;
  .default-scan-avatar {
    margin-top: 54px;
    margin-bottom: 148px;
    &__desrc {
      font-size: 36px;
      color: #333;
      text-align: center;
      margin-bottom: 127px;
    }
    &__img {
      display: block;
      height: 350px;
      width: 350px;
      margin: 0 auto;
    }
  }

  .cert-footer {
    .next-wrapper {
      width: 626px;
      margin: 0 auto;
    }
  }
}
</style>

复制代码

Demo2: {...props}及slot的体现

<script>
export default {
  name: 'CertFooter',
  methods: {
    btnClick() {
      // 点击了按钮
      this.$emit('button-click', true);
    }
  },
  render() {
    return (
      <div class="cert-footer">
        <div class="cert-footer__btn" onClick={this.btnClick}>
          <ns-button {...{ attrs: this.$attrs }} />
        </div>
        <safe-tips />
        {this.$slots.default}
      </div>
    );
  }
};
</script>

<style lang="scss" scoped>
.cert-footer {
  width: 100%;
  &__btn {
    width: 626px;
    margin: 0 auto;
  }
}
</style>

复制代码

Demo3: 常规用法

<script>
export default {
  props: {
    cardinfo: {
      type: Object,
      default: function() {
        return {
          title: '银行名字',
          type: '卡类型',
          cardnumber: ['3432', '*****', '*****', '4232']
        };
      }
    },
    defaultCard: {
      type: Boolean,
      default: false
    }
  },
  render() {
    const { cardinfo } = this.$props;

    const CardNumber = ({ props }) => {
      return props.list.map((item, index) => {
        return (
          <div class="bankcard__card--number-field" key={index}>
            {item}
          </div>
        );
      });
    };
    return (
      <div class="bankcard">
        <div class="bankcard__title">
          {cardinfo.title}
          {this.defaultCard ? (
            <div class={['bankcard__btn', 'bankcard__btn--disabled']}>默认</div>
          ) : (
            <div class={['bankcard__btn', 'bankcard__btn--setDefaultCard']} onClick={() => this.$emit('change', true)}>
              设为默认
            </div>
          )}
        </div>
        <div class="bankcard__card--type">{cardinfo.type}</div>
        <div class="bankcard__card--number">
          <CardNumber list={cardinfo.cardnumber} />
        </div>
      </div>
    );
  }
};
</script>

<style lang="scss" scoped>
.bankcard {
  margin: 30px 0;
  background-color: #fff;
  box-shadow: 1px 1px 7px rgba(79, 123, 234, 0.31);
  width: 100%;
  border-radius: 5px;
  padding: 56px 44px;
  .bankcard__title {
    font-size: 36px;
    color: #333;
    @include flex(row, space-between, center);
  }
  .bankcard__btn {
    font-size: 14px;
    color: #333;
    padding: 5px 10px;
    border-radius: 5px;
    cursor: pointer;
    &--disabled {
      background-color: rgba(211, 208, 208, 0.66);
      color: #989393;
    }
    &--setDefaultCard {
      border: 1px solid #989393;
      &:active {
        color: #4f7aea;
        border: 1px solid #4f7aea;
      }
    }
  }
  .bankcard__card--type {
    padding-top: 11px;
    font-size: 25px;
    color: #666;
  }
  .bankcard__card--number {
    margin-top: 50px;
    @include flex(row, flex-start, center);
    cursor: pointer;
    font-size: 36px;
    .bankcard__card--number-field {
      height: 30px;
      line-height: 30px;
      &:not(:first-child) {
        margin-left: 50px;
      }
    }
  }
}
</style>

复制代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Web Security, Privacy and Commerce, 2nd Edition

Web Security, Privacy and Commerce, 2nd Edition

Simson Garfinkel / O'Reilly Media / 2002-01-15 / USD 44.95

Since the first edition of this classic reference was published, World Wide Web use has exploded and e-commerce has become a daily part of business and personal life. As Web use has grown, so have ......一起来看看 《Web Security, Privacy and Commerce, 2nd Edition》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器