vue 类型字段除了用select框_vue与jsx碰撞的火花

最进在写一个vue项目,刚开始考虑是不是用jsx和vue结合来搞,减少代码量,项目中一些公用的组件,用jsx语法重新包裹,这样方便很多,而且使用jsx语法更加的灵活,然后把公用组件注入到根组件里去,每个页面可以直接引用,这样,组件的功能性和扩展性就很强,感觉是一种很爽的vue开发方式,然后就这样做了,以下就介绍一下基本流程。

之前,推荐阅读一篇介绍,首先 vue 中默认是不支持 JSX 的,我们需要在项目中安装一些 npm 包 babel-plugin-transform-vue-jsx,babel-plugin-jsx-v-model

https://github.com/vuejs/jsx#installation​github.com

然后在 .babelrc 文件中加入,如果没有这个文件,需要在项目的根路径创建这个文件

7211da220bbc553e0691e6c05921a435.png

我们可以定义一个comp的文件,用来存放公共组件,然后进行组件注入全局。截图如下。

9da2b9f171b5f02ec32867d713dd3539.png

这样页面可以直接使用这些组件,不需要每个页面都引入一遍啦。

那么,在vue中组件里面怎么用jsx实现呢?

这就需要我们对vue是怎么渲染函数和组件的,推荐阅读官方文章:

渲染函数 & JSX — Vue.js​cn.vuejs.org
80cfdc3c3481b901ce58bd00c3100455.png

文章上需要注意的一点是:

601d89a689d06df31dd8f26858764cb4.png

然后,我们试着写一个很简单的jsx的组件:比如,我们重新包裹一个树组件:

import Vue from 'vue'
import Component from 'vue-class-component'
import { Tree } from 'ant-design-vue'

@Component({})
export default class PMTree extends Vue {
  getJSX () {
    let config = {
      props: {
        treeData: this.$attrs.treeData
      }
    }
    return this.$createElement(Tree, config)
  }
  render () {
    return this.getJSX()
  }
}

注意这里的this.$createElement,其实vue对组件的识别就是一个这个函数的调用。

如果你需要监听一些函数,或者传一些属性进来,比如这个jsx组件:我们对select重新包裹,这样更方便统一调样式或者处理逻辑:

import Vue from 'vue'
import Component from 'vue-class-component'
import { Select } from 'ant-design-vue'

@Component({
  props: {
    belong: String,
    selectOptions: Array,
    size: String,
    placeholder: String,
  }
})
export default class PMButton extends Vue {
  getJSX () {
   
    let { $attrs, $props, $listeners } = this
    let { change } = $listeners
    let { selectOptions, placeholder, belong } = $props

    return  (
              // 这里这样写是为了change的时候拿到dom元素处理逻辑,也可以写成on-change={change}
              <Select on-change={(e,$event)=>change(e,$event)} {...{props}} placeholder={placeholder} style={{width: '100px'}}>
                {
                  selectOptions.map((item,index) =>
                    <Select.Option key={index} value={item.id || item } >
                      {item.name}
                    </Select.Option>
                  )
                }
              </Select>
            )
  }
  render () {
    return this.getJSX()
  }
}

我们既可以传进来$props,$attrs,$listeners。。。因为是继承Vue实例,所以,这些值都可以从this中拿到,然后我们用render函数return这一段jsx的代码,就可以被编译。

页面中使用:举个例子

 <PMSelect
      style="width: 215px"
      defaultShowFirst={true}
      on-change={$listeners.change}
      {...{props: {selectOptions: periodList}}}
/>

这就是基本的一个流程,减少了很多代码,而且如果对react熟悉的话,很容易喜欢上这种开发方式。

下面记录一个问题:每个列表的一列都有这个下拉组件,但是如果我点击了某个选项,会跟前一列的值做一个对比,如果与之前的值不同的话,select背景会变色,这个就需要我们监听这个change事件,然后去修改对应的select框的样式,我们只能取配置文件里面修改这个样式,这样才不会跟其他的select互相影响,代码如下:

注意这里的h函数,将h作为createElement的别名是 Vue 生态系统中的一个通用惯例,实际上也是 JSX 所要求的。从 Vue 的 Babel 插件的3.4.0 版本开始,我们会在以 ES2015 语法声明的含有 JSX 的任何方法和 getter 中 (不是函数或箭头函数中) 自动注入const h = this.$createElement,这样你就可以去掉(h)参数了。对于更早版本的插件,如果h在当前作用域中不可用,应用会抛错。

表头的配置文件:
const queryString = require('query-string')
import {stateDescShow} from '../../../service'
import getSelectJsx from './selectConfig'

let getJsx = (h, item, type) => {
  let {sequenceNbr} = item
  if (sequenceNbr === '0') {
    return <span>{item[type] || '/'} </span>
  }
  return <span class="disabled-color">{item[type] || '/'}</span>
}

export default function (h, context) { // context在引用这个表头的时候由页面传入
  return [
    {
      title: '所属部门',
      customRender: item => {
        return getJsx(h, item, 'depName')
      }
    },
    {
      title: '姓名',
       customRender: item => {
        return getJsx(h, item, 'name')
      }
    },
    {
      title: '职位',
      customRender: item => {
        return getJsx(h, item, 'positionName')
      }
    },
    {
      title: '职级',
      customRender: item => {
        return getJsx(h, item, 'jobLevel')
      }
    },
    {
      title: '自评等级',
      customRender: item => {
        return getJsx(h, item, 'selfRating')
      }

    },
    {
      title: '上评等级',
      customRender: item => {
        return getJsx(h, item, 'directLeaderRating')
      }
    },
    {
      title: '校准后等级',
      width: '130px',
      customRender: row => {
        return getSelectJsx(h, row, context)
      }
    },
    {
      title: '当前阶段',
      customRender: row => {
        return (
          <span>{stateDescShow(row)}</span>
        )
      }
    }
    
  ]
}

表头使用:

efd078740a7d74ac58395ecef910867b.png

注意,把this.$createElement, this两个参数传进去

select的配置文件:

注意点: context从哪里来,怎么监听的change事件,怎么处理的原生dom,有的也可以用nativeOn监听事件,但是这里试了不行,on可以监听到 ,change事件的一个参数为value,第二个为event对象,可以拿到dom节点做操作,这样每个select点击都会被监听,然后判断处理值

import PMSelect from '../../../comp/PMSelect'
import { getDeptCalibrate, getCompanyCheck } from '../../../service/index'

// select是否显示
let getSelectJsx = (h, row, context) => {
  const {
    hasCalibrateAuth, // 是否有校准权限
    getDeptcheckRight, // 是否到了部门校准阶段

    ifSystermManager, // 是否是管理员
    performEditShow //  详情是否到了150的校准阶段
  } = context
  let {sequenceNbr, performanceId} = row

  
  let conf = config(context.ratingList, context, row)

  if (sequenceNbr === '0') { // 表格列有数据
    if (performanceId) { // 参与考评
      if ((hasCalibrateAuth && getDeptcheckRight) || (ifSystermManager && performEditShow.state === 150)) {  // 有校准权限
        return h(PMSelect, { ...conf }, row)
      } else {
        // 判断部门校准这个有没有值
        if ((!row.directLeaderRating && !row.calibrateRating) || !row.calibrateRating) return <span>/</span>
        if (row.calibrateRating) {
          if (row.calibrateRating === row.directLeaderRating) {
            return <span>{row.calibrateRating}</span>
          } else {
            return <div class='callibrate_bg_color'>{row.calibrateRating}</div>
          }
        }
      }
    } else {
      return <span>/</span>
    }
  }
  return <span class="disabled-color">/</span>
}

function config (list, ctx, row) {
  return {
    props: {
      selectOptions: list
    },
    attrs: {
      defaultShowList: row.calibrateRating, // 测试回调值
      defaultShowListFlag: true,
      
    },
    on: {
      change (e, $event) {
        // console.log('e,event', e, $event)
        const { performanceId, directLeaderRating } = row
        const {
        hasCalibrateAuth,
        getDeptcheckRight,
        ifSystermManager,
        performEditShow,
        currentDeptTabId
      } = ctx
    
          let $elem = $event.context.$el.firstChild
          if (e !== directLeaderRating) {
            $elem.style.backgroundColor = 'rgba(255,125,65,0.10)'
            $elem.style.border = '1px solid #FFCBB3'
            $elem.firstChild.firstChild.style.color = '#FF7D41'
          } else {
            $elem.style.backgroundColor = ''
            $elem.style.border = '1px solid #DDDFE4'
            $elem.firstChild.firstChild.style.color = '#2D3040'
          }
        
        if (hasCalibrateAuth && getDeptcheckRight) {  // 对个人进行校准
          getDeptCalibrate({
            rating: e,
            performanceId: Number(performanceId),
            deptId: currentDeptTabId.split('-')[1]
          }).then(res => {
            if (res.meta.code === 0) {
              ctx.$message.success('调整成功', 1)
            } else {
              ctx.$message.error('调整失败', 1)
            }
          })
        }
       
  }
}

export default getSelectJsx

结果是:我改了某一个select,值有变化,就会变色:

0df8bc16a923c7bd97fcd643c2fef89a.png

所以,vue的jsx写法在处理很多问题的时候还是很方便的,希望我们使用的越来越顺手。

感谢阅读。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值