写jsx_vue3下jsx教学,保证业务上手无问题!手敲代码,有知识点,附带和template对比...

本文详细介绍了在Vue3中使用JSX的实践,包括注意事项、使用scopedCss、class和style、ref、reactive、插槽、v-if/v-for、v-model等。同时对比了JSX与常规SFC的区别,指出JSX并不简化开发,但提供了更多灵活性。建议学习JSX以拓宽视野,但不应大规模使用,特别是在中小型项目中。
摘要由CSDN通过智能技术生成

(给前端开发爱好者加星标,提升前端技能)

转自:海天酱油_沃利贝尔

https://juejin.cn/post/6911883529098002446

前言

原因:闲的。还有一个原因吗?嘿嘿

然后之前就说过了,我拿vue3直接干公司项目了,是内部的孵化项目,客户不多,但是也是正规的生产项目。

技术栈说明:

公司项目:js,element-plus,vue3,jsx,常规template,按需加载(单独领出来是因为这个也会导致你的项目填坑变多)

个人组件库研究项目:TypeScript,vue3,jsx,常规template

主要讲公司项目吧,公司项目上线一个月。还算稳定,不过我需要给没能力填坑的大家看一个截图。

element-plus提交issues

40a533db97f7f048efbc1aba638a983e.png

vue3提交issues

这里澄清下,vue3的bug其实目前来说可以说没有,单独我发现的方面,但是在使用过程中elementUI组件配合下发现了一个。这里提交的问题其实有一个核心处理点。其他都算是单纯的提问,不是bug。

2eea4d0adf3d49a6414dff2119219ff1.png

小总结

可以上生产,但是要有一定填坑能力。但是时间够你折腾,那么就早点学起来吧。

一、vue3生产注意点

1、不能使用getCurrentInstance的ctx

大家在获取app.config.globalProperties.ELEMENT这里设置的ELEMENT这里设置的ELEMENT是要如下

这里的ctx不是steup里面提供的ctx,而是

const { ctx } = getCurrentInstance()

这里ctx在生产环境下是获取不到的,请各位没玩过生产的别误人子弟,这还是我专门给vue3提交issues问来的。

正确应该使用

const { proxy } = getCurrentInstance()

关于在ts中使用

在ts里面大家估计经常会遇到类型定义错误问题。

使用方式1

interface ProxyEx extends ComponentPublicInstance {
$test: number
}

export default defineComponent({
setup(props, ctx) {
const self = getCurrentInstance() as ComponentInternalInstance
const proxy = self.proxy as ProxyEx
console.log(proxy?.$test)
return {}
},
})

使用方式2

上述方案把类型定义到了页面内部,也可以弄一个全局文件去调用。但是总是不方便的。还有就是我们去扩展@vue/runtime-core文件,

然后我们可以在main.ts文件下面增加这段,也不会产生全局错误了

declare module '@vue/runtime-core' {
interface ComponentCustomProperties {
$test: number
}
}

但是不能放在d.ts文件下面,否则会全局产生错误。我翻了好久的issues也没有找到方案。看官方后续优化解决吧。

二、jsx教学开始

关于jsx的官方教学地址:https://vue3js.cn/docs/zh/guide/render-function.html#jsx

git部分:https://github.com/vuejs/jsx-next/blob/dev/packages/babel-plugin-jsx/README-zh_CN.md

我这里就不放关于h函数的处理了,就直接用和react一样的编码方式来书写。主要是vue3的cli已经内置好了babel插件,也就是说大家不需要单独去引入babel插件。直接可以使用。

也就是大家可以这样写vue文件来书写jsx代码。这里我贴上简单示例

Template对比

简单示例

1、注意事项

1、html代码的js文件或者ts文件后缀名增加‘x’,原本是.js变成.jsx,ts变成.tsx

2、.vue文件的script标签增加 lang="tsx",这个呢是你里面存着jsx写法的就需要加。

比如这种情况

{{ de }}


3、常规jsx语法下是无法配合scpoedCss使用的,解决方法等下就讲

2、在.vue文件下面让你的jsx代码也可以使用scopedCss

也就是大家经常在css部分加的这个

**来源:***github.com/vuejs/jsx-n…

原理:只要取到 __scopeId, 就可以在 setup/render 函数中

其中可以得到__scopeId的方式

方案1:

// main.js
import { createApp } from 'vue';
import App from './App.vue'

createApp(App(App)).mount('#app') // 这里将 App 传回组件

// ./App.vue
export default ({ __scopeId }) => {
// 这里可以取到 __scopeId
})

方案2:

// ./App.vue
export default {
render(ctx) {
// ctx._.type.__scopeId
}
}

方案3: setup 可以返回一个 render 方法, 用于 render jsx

// ./App.vue
export default {
setup() {
return (ctx) {
// ctx._.type.__scopeId
}
}
}

上面的实现对于大家比较抽象,我这里提供一个自己的实现方式

然后附上template对比

简单示例

关于像cssModule,css-in-js等方案大家就自行研究。

3、关于class和style样式

这里提醒一下,大家不太会用的直接拿react代码套进来也可以。也就是你可以直接搜索react使用方式,然后这里一样可以用。就是注意下比如className和class这种区别。语法上两者真的差异不大

class部分使用和template部分没有差别

或者

动态方式就不太一样

style部分如果是没有动态的那么和普通的写法没差异

但是动态的需要是这样的

4、在jsx里面使用ref,reactive等

import { defineComponent, ref, reactive } from 'vue'
const Testref = defineComponent({
setup(props, ctx) {
const dateone = ref('测试')
const datetwo = reactive({
test: '测试',
})
return () => (
{dateone.value}
{datetwo.test}

)
},
})

template对比

{{ dateone }}
{{ test }}



复制代码

5、使用插槽和具名插槽

官方:https://vue3js.cn/docs/zh/guide/component-slots.html#插槽内容

const testslot = defineComponent({
setup(props, ctx) {
return () => (

{/*默认插槽*/}
{ctx.slots.default && ctx.slots.default()}

{/*具名插槽*/}
{ctx.slots.name && ctx.slots.name()}

)
},
})

template对比


6、作用域插槽使用

官方地址:https://vue3js.cn/docs/zh/guide/component-slots.html#作用域插槽

传参

const TestA = defineComponent({
setup(props, ctx) {
return () =>
{ctx.slots.default && ctx.slots.default('作用域传参')}

},
})

使用

const TestD = defineComponent({
setup(props, ctx) {
return () => (
组件:TestD v-slots={{
default: (n: string) => {n},
}}
/>

)
},
})

template对比

**传参
**


使用

{{ slotProps}}

7、v-if 和 v-for

官方:https://vue3js.cn/docs/zh/guide/render-function.html#v-if-和-v-for

const iffor = defineComponent({
setup(props, ctx) {
const ces = true
const ifelse = () => {
if (ces) return
if部分

else return
else部分

}

const forarr = () => {
let i = 0
return new Array(10).fill('').map(() => {
i++
return {i}
})
}

return () => (

{ifelse()}
{forarr()}

)
},
})

template对比

{{ item.name }}

No items found.

8、v-model的使用

template部分我就不放了,太简单了

9、jsx情况下可以不要.vue文件示例

示例1:

export const TestCom = defineComponent({
setup(props, ctx) {
return () =>
},
})

示例2:

import { ref } from 'vue'
interface Props {
text: string
}

// ref不能放在组件内部,否则会重新赋值,导致不会响应式变化
const num = ref(1)
const dataone = ref('测试无defineComponent数据变化')

const addnum = () => {
num.value++
}
const inpt = ref('')
const onInput = () => {
console.log(inpt.value)
}

const NoDcom = (props: Props, ctx: any) => {
//console.log(props, ctx)
return (
{dataone.value}
点击测试数据变化
变化的数字{num.value}

)
}
export default NoDcom

10、关于在vue文件组件注册

注意jsx的文件就不要加jsx后缀了

使用和常规的组件注册一样

import { TestCom } from './Test'

export default defineComponent({
components: { TestCom},
setup(props, ctx) {
return {}
},
})

11、关于click事件之类

原本模板中是@click,全部改为onClick模式,和react比较相似

举例

template

12、使用Teleport

在jsx下使用vue内置的组件需要额外导入组件,并且名称不能变。

import { defineComponent, Teleport } from 'vue'
// 使用Teleport
const teleportCum = defineComponent({
setup(props, ctx) {
return () => (
teleport值

)
},
})

Template使用

并且是不需要单独导入,也没有大小写区分的问题

13、使用Transition

和使用teleport一样,就不单独写代码了。上面的例子一样,把Teleport换成Transition就可以跑了

14、关于指令修饰符

官方自带的指令修饰符方面是说类似自己实现

地址:https://v3.cn.vuejs.org/guide/render-function.html#v-on

然后我个人在项目中因为自定义了一个可以随意拖动的v-move指令,并且定义了boundary修饰符代表是否可以只在父元素范围内移动。这时候就很烦了

最后多方百度下至少自定义的指令修饰符是通过“_”连接,如下


{ctx.slots.default && ctx.slots.default()}

而template里面

三、关于jsx和常规的sfc(vue文件方式)

写到这里,说实在我有点想不到该写什么。jsx给我的感觉就是在用react语法。为什么呢?因为这个babel插件是阿里团队优先搞出来了,然后大家都知道阿里是react技术栈为主的。所以语法上面靠近react。

我说说我的几个见地吧

1、jsx并没有更加方便,只是让你更接近vue模板渲染的底层原理

2、jsx语法灵活很多,光我上面就出现了两种jsx书写方式,个人还是推荐defineComponent方式,更加是一个整体

3、jsx书写会比较强迫的让你把for循环等小逻辑模板单独成为一个函数,优点就是颗粒度更小了,和sfc书写方式相比,没有那么方便。

特别是什么呢,我上面的提供方式优点不方便在return部分写逻辑,如果你写if会报错,官方方面都是用的render方式,其实两者的差异并不大

4、如果你用vue那么jsx可以作为一种优化方式(官方推荐使用template方式意味着,template方式bug会优先解决),而不是大规模使用。特别是中小公司,大公司也好不到哪里去。除了业内头部公司,有几个团队能完全规范化的呢?

这里我说一句话:何不食肉糜?

要是全用jsx,那我还是用react吧。何况react薪资更高呢

5、jsx一定要学,但是ts更要学。虽然未来一定不是ts的天下(浏览器领域),但是ts所带来的影响已经把中高端领域覆盖。

6、学习jsx是让你拓宽视野,react生态毕竟是领头羊。

四、关于vue3书写方式,我想新手很容易写出这种代码吧。

放一个我个人封装的组件地址:https://github.com/ht-sauce/visualization/tree/master/src/componentsLibrary/Popper

文档地址:https://www.yuque.com/cv8igf/oy3c8b/uy5sqv

这恐怕就是大佬所担心的面条式代码,说白了,这就是vue2所带来的习惯。vue3的情况下,那么props,函数,响应式部分都是可以抽离到单独的js文件,但是vue2恐怕只能抽离props部分了。

五、致谢

谢谢大家观看。喜欢的点个赞。

觉得本文对你有帮助?请分享给更多人或点个在看0fc58523f21a234fac33bcd3735f957d.png

关注==>>「前端开发爱好者」,一起提升前端技能!

2fd64234b62af113d5a08eac0eb25ab1.png

「赞」「在看」「转发」支持一下

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值