有用的vue3 JSX&TSX使用说明。

7,203 阅读3分钟

本文更新于2021-08-03 基于vite 2.4.4&vue 3.1.5,除了装个插件,不需要额外配置即可使用。 不太适合template还没有上手的好兄弟萌。适合对vue3.0有一点了解的好兄弟萌。

纪念一下老环境:vite 2.0.0-beta.5当时还是用react的方法来配的。

配置

// vite.config.js
...
import vueJsx from '@vitejs/plugin-vue-jsx' // 要安装@vitejs/plugin-vue-jsx
export default defineConfig({
  plugins: [...vueJsx({})], // 在这里加上
  ...
})

本文将使用jsx/tsx实现template的一些指令及功能,参考了jsx-next/README。但是绝对不是单纯的复制粘贴了事!

常用写法

import { defineComponent } from 'vue'
export default defineComponent({ render() { return <div>Test</div> }})
//如果要写多行
import { defineComponent } from 'vue'

export default defineComponent({
     render(){
        const Fragment =(
            <>
            <div>
                <p>这样方便多了</p>
                <p>this good!</p>
            </div>
            </>)
         return Fragment
     }
    })

函数式写法

const App = () => <div>Vue 3.0</div>;
export default App;

一些语法注意点:

  1. 标签必须严格闭合,否则无法编译通过,如:<input type="text" name="" id="">这样是不行的,一定要:<input type="text" name="" id=""/>
  2. 函数式写法组件无法更新DOM!!
  3. 在jsx中如果不是非要双向绑定,那么可以不用ref。

vue常用指令TSX/JSX的实现。

v-bind

绑定标签属性。

注意点

  1. 属性的写法上和 HTML 存在区别,在写 JSX 的时候,所有的属性都是驼峰式的写法.如:className. 有些属性名不能直接绑定,如:for、class。for-> className for-> htmlFor
  2. data-* 和 aria-* 两类属性是和 HTML 一致的 data系列是指自定义数据。 aria系列是指一般是为不方便的人士提供的功能。
  3. ide/编辑器的智能提示做的好,别担心。

例1

// 绑定span的title。
// 在jsx中没有必要要用ref,我就是说明一下可以这么用。
import { ref } from "vue"
export default ()=>{
    const msg=ref('小火汁😂')  
    return(
      <span title={msg.value}>
        走成华大道(鼠标停一哈看提示)
      </span>
    )
  }

例2

const placeholderText = "email";
const App = () => <input type="email" placeholder={placeholderText} />;

v-show

const App =  defineComponent(  {
    data() {
      return { visible: true };
    },
    render() {
      return <input v-show={this.visible}  type="text" placeholder="7777"/>;
    },
  });
  export default App

v-model

注意:如果想要使用参数,可以用一个参数, 但是如果用了两个参数,第二个参数需要为字符串!以作为参数名。 官方readme

<input v-model={val} />
<input v-model={[val, ["modifier"]]} />
<A v-model={[val, "argument", ["modifier"]]} />
//会变编译成:
h(A, {
  argument: val,
  argumentModifiers: {
    modifier: true,
  },
  "onUpdate:argument": ($event) => (val = $event),
});

v-models 传递多个参数

注意: 你应该传递一个二维数组给 v-models。

<A v-models={[[foo], [bar, "bar"]]} />
<A
  v-models={[    [foo, "foo"],
    [bar, "bar"],
  ]}
/>
<A
  v-models={[
    [foo, ["modifier"]],
    [bar, "bar", ["modifier"]],
  ]}
/>
//会变编译成:
h(A, {
  modelValue: foo,
  modelModifiers: {
    modifier: true,
  },
  "onUpdate:modelValue": ($event) => (foo = $event),
  bar: bar,
  barModifiers: {
    modifier: true,
  },
  "onUpdate:bar": ($event) => (bar = $event),
});

自定义指令

const App = {
  directives: { custom: customDirective },
  setup() {
    return () => <a v-custom={[val, "arg", ["a", "b"]]} />;
  },
};

v-for

export default defineComponent({
setup(props) {
  const goods = ref(["贝斯特橱柜","民思达电动车"])
  const msg = ref("商品出售:")
  return ()=>(
    <div>
      {
        goods.value.map(
          i=>{
            return <div>{i}</div>
          }
        )
      }
    </div>
    )
  }
})

v-if

三目运算符就可以实现差不多的功能

export default function(){
  const show=ref(true)
  return (
    <div>
      {show.value?"有人":"没有人"}
    </div>
  )
}

纯代码就这?这很不js啊,还有更好的办法吗? 因为JSX里是对象,不能是语句。。。

// 也没有多好吧....
export default function(){
  const show=ref(true)
  let msg;
  if (show.value){
     msg = <span>有人</span>
  }else{
    msg = <span>没有人</span>
  }
  return (
    <div>
      {msg}
    </div>
  )
}

v-on

这一类其实就是各种事件的绑定!

import { defineComponent, ref } from 'vue'
//有状态的路由~
export default defineComponent({
  setup(popps) {
    const msg = ref("正常小火👨‍🦱")
    const click=()=>{
      msg.value= "精神小火🏃‍♂️"
      console.log("变了啊!")
    }
  
    return()=> (
      <div onClick={click}>
        {msg.value}
      </div>
    )
  }
})

插槽

注意: 在 jsx/tsx 中,应该使用 v-slots 代替 v-slot

const A = (props, { slots }) => (
  <>
    <h1>{ slots.default ? slots.default() : 'foo' }</h1>
    <h2>{ slots.bar?.() }</h2>
  </>
);

const App = {
  setup() {
    const slots = {
      bar: () => <span>B</span>,
    };
    return () => (
      <A v-slots={slots}>
        <div>A</div>
      </A>
    );
  },
};

// or

const App = {
  setup() {
    const slots = {
      default: () => <div>A</div>,
      bar: () => <span>B</span>,
    };
    return () => <A v-slots={slots} />;
  },
};

// or
const App = {
  setup() {
    return () => (
      <>
        <A>
          {{
            default: () => <div>A</div>,
            bar: () => <span>B</span>,
          }}
        </A>
        <B>{() => "foo"}</B>
      </>
    );
  },
};

之前vue3.0刚出来,配老环境不容易呀----本文持续更新。