📝背景
公司高级表单组件ProForm高阶组件都建立在jsx的运用配置上,项目在实践落地过程中积累了丰富的经验,也充分感受到了jsx语法的灵活便捷和可维护性强大,享受到了用其开发的乐趣,独乐乐不如众乐乐,为了帮助大家更好的运用jsx,开发提效,特此总结分享。
💎效果对比
以前
以往我们开发一个列表的增加、编辑、查看详情三个操作要准备3个form表单文件,表单中ui元素共性部分我们要复制三次,例如:
// addForm.vue
新增
import { reactive } from 'vue'
const form = reactive({
name: '',
region: '',
type: '',
})
...
// editForm.vue
编辑
import { reactive,inject } from 'vue'
const form = reactive({})
form=inject('detailData')
...
// detailForm.vue
关闭详情
import { reactive,inject } from 'vue'
const form = reactive({})
form=inject('detailData')
...
如果遇到改字段名的情况,如把活动名称的name改成activityName,对应的3个文件都得去修改,表单改动多的话还有可能存在有得文件改漏的情况。
现在
现在使用ProForm结合jsx配置,如下
// add.vue
新增
Import ActivityForm from './form.vue'
...
// edit.vue
编辑
Import ActivityForm from './form.vue'
...
// detail.vue
关闭详情
Import ActivityForm from './form.vue'
...
Form.vue
import { reactive, ref, computed } from 'vue'
...
const formRef = ref()
const form = reactive({
name: '',
region: '',
type: '',
})
const props = defineProps({
mode: {
type: String,
default: 'Add',
},
});
const columns = [
{
prop: 'name',
label: '活动名称',
type: 'input',
},
{
prop: 'region',
label: '活动区域',
// jsx部分
render: (form) => (
),
},
{
prop: 'type',
label: '活动形式',
// jsx部分
render: (form) => (
),
},
]
...
改成上面的形式后,一处改动,3处对应生效,开发的重点也转移到form表单中对columns的配置上,columns配置则建立在对jsx的运用,当然举的这个例子只是一个简单案例,复杂的例子在项目中,下面我们正式开启jsx之旅吧
📝JSX是什么
JSX(JavaScript 和 XML),是一个 HTML-in-JavaScript 的语法扩展,首先在 React 中被进入,它允许我们在JavaScript中编写类似HTML的代码,并将其转换为JavaScript对象。Vue3中引入了对JSX的支持,使得我们可以更加灵活地编写组件模板,不再局限于Vue2.x中的模板语法。JSX 可以很好地描述 UI 应该呈现出它应有交互的本质形式。
形如:
const element = Hello World
或
function getGreeting(user) {
if (user) {
return Hello, {formatName(user)}!
;
}
return Hello, Stranger.
;
}
📝JSX 和 template 的区别
–语法上有很大区别:
📝基本用法
安装使用
vite 官方提供了官方的插件来支持在 vue3 中使用 jsx
yarn add @vitejs/plugin-vue-jsx
安装完之后在 vite.config.js 文件中的 plugins 字段中添加 jsx 支持:
import vueJsx from "@vitejs/plugin-vue-jsx";
export default defineConfig({
plugins: [
vueJsx(),
]
})
插值表达式
// template
{{ a + b }}
// jsx
render: () => {
return (
{ a + b }
)
}
条件渲染
// template v-if v-show
是
否
我是v-show
// jsx
render: () => {
const show = ref(true);
return (
{show.value ? 是 : 否}
我是v-show
)
}
// jsx if-else
render: () => {
const isShow = false
const element = () => {
if (isShow) {
return 是
} else {
return 否
}
}
return (
{
element()
}
我是v-show
)
}
样式绑定
// template
// jsx
// jsx 模板字符串
header
//jsx 数组
header
// jsx 样式绑定需要使用双大括号。
render: () => {
const width = '100px'
return (
)
}
列表循环
// template v-for
- {{ item }}
// jsx 数组 .map 函数
render: () => {
return
{ list.map(item => - {item}
)}
>
}
事件处理
// template
// jsx 数组 .map 函数
render: () => {
const clickButton = val => {
console.log(val)
}
return (
doThis(), ['stop'])}>
)
}
标签属性绑定
// template
//jsx
render: () => {
return (
)
}
V-model
// 一般用法
// template
// jsx
// 指定绑定值写法
// template
// jsx
// 修饰符写法
// template
// jsx
插槽
定义插槽
jsx/tsx中是没有 slot
标签的,定义插槽需要使用{}
或者使用renderSlot
函数
setup 函数默认接收两个参数 1. props 2. ctx 上下文 其中包含 slots、attrs、emit 等
// template
// jsx
import { renderSlot } from "vue"
export default defineComponent({
// 从ctx中解构出来 slots
setup(props, { slots }) {
return () => (
{ renderSlot(slots, 'default') } // 等价于 { slots.default?.() }
{ slots.title?.() }
)
}
})
使用插槽
通过 v-slots 来使用插槽
// template
删除
// jsx
render: (form) => {
const slots = {
action: ({ row }) => handleDel(row)}>
删除
,
};
return (
);
},
jsx基础模板
import { defineComponent, onMounted, ref } from 'vue';
export default defineComponent({
// props: ['xx'],
setup(props,{ emit }) {
onMounted(() => {
// ...
})
return () => (
)
}
})
组件运用
在 .vue 文件中使用 jsx组件
// 父
import JSXDemo from '@/components/JSXDemo.vue'
// JSXDemo.vue
import { ref } from 'vue'
export default {
setup () {
const countRef = ref(200)
const render = () => {
return DEMO1--{countRef.value}
}
return render
}
}
在.jsx文件格式中父子组件属性传递
// 父组件
import { defineComponent, ref } from 'vue'
import JSXChild from './JSXChild.jsx'
export default defineComponent(() => { // 传入 setup 函数
const countRef = ref(360)
const render = () => {
return
数量--{countRef.value}
// vue3的template会自动解析ref的.value,在jsx中ref的.value是不会被自动解析的
>
}
return render
})
// 子组件 JSXChild.jsx
import { defineComponent } from 'vue'
export default defineComponent({ // 传入组件配置
props: ['a'],
setup (props) {
const render = () => {
return
child {props.a}
>
}
return render
}
})
📝经验总结
我们该怎么选择 JSX 和 template ?
template优势:template 的语法是固定的,有 v-if、v-for 等等语法。按照这种固定格式的语法书写的代码, Vue3 在编译层面就可以很方便地去做静态标记的优化,减少Diff过程。比如静态提升,类型标记,树结构打平等来提高虚拟 DOM 运行时性能。这也是 Vue 3 的虚拟 DOM 能够比 Vue 2 快的一个重要原因。
JSX优势:template 因为语法限制原因,不能够像 JSX 那样可以支持更动态的需求。每一个 .vue 文件结尾的文件都是一个组件,而且只能 export default 出一个组件,JSX 则不同 ,是可以在一个文件内返回多个组件的,比如我们写一个页面的时候其实可能会需要把一些小的节点片段拆分到小组件里面进行复用,这些小组件在jsx里面,写个简单的函数组件就能搞定,例如:
那如何选择呢?
在实现业务需求的时候,优先使用 template,尽可能地利用 Vue 本身的性能优化,如列表、弹窗和抽屉。而对于动态性要求较高的组件可以使用 JSX 来实现,比如动态表单,封装动态递归组件。而对于公司项目来说,大多数业务需求都是表单类的,那就赶紧用上jsx吧,用久了你就会发现,哎,真香。
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net
简单记一下,以前没怎么用过。 EditText View的getText直接返回的就是 Editable 而 TextView则是getEditableText才返回 Editable。 还有就是注释所说, * Replaces the specified r…