浅记Vue中JSX的使用 nice

摘要:JSX是一种Javascript的语法扩展,JSX = Javascript + XML,即在Javascript里面写XML,因为JSX的这个特性,所以它既具备了Javascript的灵活性,同时又兼具html的语义化和直观性。

本文营养来自->在 Vue 中如何使用 JSX,就这么简单!【建议收藏】

探索BG:项目中有个自定义表格以及表单加载和显示,考虑到使用JSX

在Vue中使用JSX,需要使用Babel插件

创建项目并配置Babel

vue create vue-jsx
#选择vue2

安装依赖

npm install @vue/babel-preset-jsx @vue/babel-helper-vue-jsx-merge-props
# or
yarn add @vue/babel-preset-jsx @vue/babel-helper-vue-jsx-merge-props

配置.babelrc(babel.config.js)

module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset',
    [
      '@vue/babel-preset-jsx',
      {
      'injectH: false
      }
    ]
  ]
}

配置了babel.config.js后,我们把正常引用的组件如HelloWorld.vue 改为HelloWorld.js,并且删除文件中关于template和style,以及script标签


项目中不是采取配置babel的方式,而是采用vue组件创建的方式,如下

步骤一、通过install函数 Vue.component注入组件
在这里插入图片描述
步骤二、Vue.use初始化自定义组件
在这里插入图片描述
步骤三、要使用的组件页面中直接引用


JSX基本用法

1、纯文本、动态内容、标签使用、自定义组件、样式和class

import myComponent from './myComponent'
import './HelloWorld.css'

// 创建一个组件button
const ButtonCounter = {
  name: "button-counter",
  props: ["count"],
  methods: {
    onClick() {
      this.$emit("change", this.count + 1);
    }
  },
  render() {
    return (
      <button onClick={this.onClick}>数量 {this.count}+</button>
    );
  }
};
export default {
  name: 'HelloWorld',
  components: {
    myComponent 
  },
  data () {
    return {
      text:'hello 纸没了飞机',
      inputText:'我吃了',
      count: 0
    }
  },
  props: {
    msg: String
  },
  watch: {},
  methods: {
    onChange(val) {
      this.count = val;
      alert(this.count)
    }
  },
  render() {
    // const {text,inputText,count} = this //通过解构,下方return片段中就不需要this
    return (
    <div>
     <h3>内容</h3>
     {/* 纯文本 */}
     <p>hello, I am Gopal</p>
     {/* 动态内容 */}
     <p>{ this.text }</p>
     <p>hello { this.msg }</p>
     {/* 输入框 */}
     <input/>
     {/* 自定义组件 */}
     <myComponent/>
     <ButtonCounter
        style={{ marginTop: "10px" }}
        count={this.count}
        type="button"
        onChange={this.onChange}
      />
    </div>
    );
  }
}

2、条件渲染

jsx本身也是个条件表达式,不再需要使用v-if指令

(1) 使用if/else

const element = (name) => {
  if (name) {
    return <h1>Hello, { name }</h1>
  } else {
    return <h1>Hello, Stranger</h1>
  }
}

等效于:

const element = (name) => <h1>Hello, { name || 'Stranger' }</h1>

(2)使用三目运算符

const element = (name) => <h1>Hello, { name || 'Stranger' }</h1>

等效于:

const element = (name) => <h1>Hello, { name || 'Stranger' }</h1>

3、列表渲染

const list = [
  {id: 1,name: '张三'},
  {id: 2,name: '李四'}
]
const element = list.map(item => {
  return <div>{ item.name }</div>
})

4、标签属性绑定

属性绑定也是使用花括号,不需要使用v-bind指令

const href = 'https://devui.design/'
const element = <a href={href}> Design </a>

5、class类名绑定

直接使用JS模板字符串:

const element = <div className={`devui-accordion-item-title ${ disabled ? 'disabled' : ''}`}></div>

也可以使用数组:

const element = <div class = {['devui-accordion-item-title', disabled && 'disabled']}></div>

6、style样式绑定

使用双花括号:

const width = '100px'
const element = <button style={{with, fontSize: '16px'}}></button>

7、事件绑定

绑定事件使用单花括号,注意事件名前加on前缀,如click事件要写成onClick, mouseenter事件携程onMouseenter

const confirm = () => {}

<button onClick={confirm}>确定</button>

如果需要携带参数,要使用箭头函数包裹:

<button onClick={() => confirm('init')}>确定</button>

jsx中给事件增加修饰符需要借助withModifiers方法

import { withModifiers, defineComponent, ref } from 'vue'

const App = defineComponent({
  setup() {
    const count = ref(0);

    const inc = () => {
      count.value++;
    };

    return () => (
      <div onClick={ withModifiers(inc, ['self']) }>{ count.value }</div>
    );
  },
})

注意:Vue模板中ref变量是可以直接解构的,但是再jsx中不行,需要记得添加==.value==,比如上面的=={ count.value }==

8、v-model双向绑定

(1) 绑定modelValue

<yw-table v-model= {menuShow.value}></yw-table>

(2) 绑定自定义名称

比如绑定visible, JSX中不能直接使用v-model:visible的语法,需要传入一个数组[menuShow.value, ‘visible’], 数组的第二个参数就是要绑定的自定义名称

<yw-table v-model= [menuShow.value, 'visible']></yw-table>

9、插槽

插槽就是子组件中提供给父组件使用的一个占位符,插槽分为默认插槽,具名插槽和作用域插槽

(1) 使用默认插槽

使用element-ui的Dialog时,弹窗内容就是用了默认插槽,在JSX中使用默认插槽的用法与普通插槽的用法基本一致:

render(){
  return (
    <ElDialog title="标题" visible={true}>
      {/*这里是默认插槽*/}
      <div>弹窗内容</div>
    </ElDialog>  
  )
}

(2) 自定义默认插槽

在Vue实例this上有个属性slots,这个上面挂载了这个组件内部所有插槽,使用this.$slots.default就可以将默认插槽加入到组件内

export default {
  props: {
    visible: {
      type: Boolean,
      default: false
    }
  },
  rendere() {
    return (
      <div class="custom-dialog" vShow={this.visible}>
        { this.$slots.default }
      </div>
    )
  }
}

使用:

<myComponet visible={true} slot>我是自定义默认插槽</myComponet>

(3) 具名插槽

当一个组件需要多个插槽时,为了区分 就给插槽起名,如element-ui弹窗可以自定义底部按钮区内容,就是用了名为footer的插槽

render() {
  return (
    <ElDialog title="标题" visible={true}>
      <div>内容</div>
      <template slot="footer">
        <ElButton>确定</ElButton>
        <ElButton>取消</ElButton>
      </template>
    </ElDialog>
  )
}

(4) 自定义具名插槽

render() {
  return (
    <div class="custom-dialog" vShow={this.visible}>
      {this.$slots.default}
      {/*自定义具名插槽*/}
      <div class="custom-dialog_footer">{this.$slots.footer}</div>
    </div>
  )
}

使用:

<myComponent visible={true}>
  <template slot="footer">
    <ElButton>确定</ElButton>
    <ElButton>取消</ElButton>
  </template>
</myComponent>

(5) 作用域插槽

有时候插槽内容能够访问子组件中才有的数据时很有用的,这时就需要用到作用域插槽,在JSX中,因为没有v-slot指令,所以作用域插槽的使用方式与模板代码里面的方式不同了

比如在element-ui中,我们使用el-table时可以自定义表格单元格的内容,此时就用到作用域插槽

<myComponent
  visible={this.visible}
  {...{
    scopedSlots: {
      text: ({user}) => {
        // 这个user就是子组件传递来的数据,同理可拿到el-table的row,不过test得是default
        <div style="colot:blue;">common on!{user.name},这是作用域插槽</div>
      }
    }
  }}>
</myComponent>

(6) 自定义作用域插槽

子组件中通过{this.$scopedSlots.test({ user: {name: ‘纸飞机’}})} 指定插槽名称是test,并将user传递给父组件;父组件在书写子组件标签的时候,通过scopedSlots值指定插入的位置是test,并在回调函数获取到子组件传入user值

注意:作用域插槽是写在子组件标签中,类似属性 而不是像具名插槽放在标签内部

export default {
  name: 'slotComponent',
  data() {
    return {}
  },
  props: {
    visible: {
      type: Boolean,
      default: false
    },
    listData: {
      type: Array,
      default: function () {
        return []
      }
    }
  },
  render() {
    return (
      <div vShow={this.visible}>
        {/*自定义作用域插槽*/}
        <div class="item">
          {
            this.$scopedSlots.test({
              user: {name: '纸飞机'}
            })
          }
        </div>
      </div>
    )
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值