相关文章推荐
宽容的毛衣  ·  使用php ...·  5 月前    · 
要出家的牙膏  ·  Shiro 权限框架 ...·  1 年前    · 
卖萌的芹菜  ·  Windbg fails to open ...·  1 年前    · 
帅气的猴子  ·  MySQL :: MySQL 8.0 ...·  1 年前    · 
精彩文章免费看

【VUE+TS】1.0 Vue3.0+TS打造企业级组件库

目的

使用vue单元测试库保证代码质量
开源项目的开发发布流程
设计合理的设计广泛适用的API
如何保证代码质量
vue3的实现原理

表单组件库

涉及到数据(校验)安全

代码质量高
适应场景丰富
开源维护参与
完善的发布流程
源码(响应式原理)

和其他表单组件库的区别

无需编写代码:由json负责组装代码的要求。
开源全栈通用:对于校验部分可以做到全栈
拖拽实现表单生成。

开发模式讲解:JSX的开发模式
vue3的TS规范定义(vue3的源码全部使用TS编写的)
高泛用性的API
响应式原理(vue3的原理)
完善功能开发(组件开发)
自动化发布流程

TypeScript

TS 最重要的核心就是 type (类型),和js最大的区别就是把 java 换成了 type ,也就是说有类型的js。

所以使用ts:

1.任何变量都声明类型;
2.不到万不得已不要使用any
3.给对象声明接口

win+R
F:\work_mysself\company_workspace\vue-json-schema-form_workspace
vue create vue-json-schema-form
  "desc-singleQuote": "是否使用单引号:习惯单引",
  "singleQuote": true,
  "desc-arrowParens": "匿名函数单个参数时是否写括号:习惯写",
  "arrowParens": "always",
  "desc-trailingComma": " object属性一行行写下去之后,是否在最后加一个逗号",
  "trailingComma": "all"

还有很多规则,可以去官网学习并设置。
设置好之后打开src\main.ts,尝试保存,或者shift+alt+f格式化,发现没有变化,这是需要我们配置一下这个文件:
<div class="home"> <img alt="Vue logo" src="../assets/logo.png" /> <HelloWorld msg="Welcome to Your Vue.js + TypeScript App" /> </template> <script lang="ts"> import { defineComponent } from "vue"; import HelloWorld from "@/components/HelloWorld.vue"; // @ is an alias to /src export default defineComponent({ name: "Home", components: { HelloWorld, </script>

避免props出现 undefined值,如下代码是正常的:
比如修改src/main.js

import { createApp, defineComponent, h } from 'vue'
// import App from './App.vue'
import router from './router'
import store from './store'
import HelloWorld from './components/HelloWorld.vue'
const App = defineComponent({
  render() {
    return h('div', { id: 'app' }, [
      h('img', { alt: 'Vue logo', src: './assets/logo.png' }),
      h(HelloWorld, {
        msg: '欢迎来到Vue+TS 的应用现场',
        age: 12,
createApp(App).use(store).use(router).mount('#app')

这里图片不显示是因为如果是正常写的html代码会vue-loader会进行自动寻址。
如果想正常显示可以这么写:

import { createApp, defineComponent, h } from 'vue'
// import App from './App.vue'
import router from './router'
import store from './store'
import HelloWorld from './components/HelloWorld.vue'
const img = require('./assets/logo.png') //eslint-disable-line
const App = defineComponent({
  render() {
    return h('div', { id: 'app' }, [
      h('img', { alt: 'Vue logo', src: img }),
      h(HelloWorld, {
        msg: '欢迎来到Vue+TS 的应用现场',
        age: 12,
createApp(App).use(store).use(router).mount('#app')

setup

setup自带参数(props,{slots,attrs,emit})
attrs 和 slots 是有状态的对象,它们总是会随组件本身的更新而更新。这意味着你应该避免对它们进行解构,并始终以 attrs.x 或 slots.x 的方式引用。

使用JSX开发vue3组件

JSX目前有2个解决方案,推荐vueComponent/jsx

声明使用,需要修改babel.config.js

module.exports = {
  presets: ['@vue/cli-plugin-babel/preset'],
  plugins: ['@vue/babel-plugin-jsx'], //这样配置jsx就可以用了

修改src/main.js:

import { createApp, defineComponent } from 'vue'
// import App from './App.vue'
import router from './router'
import store from './store'
import HelloWorld from './components/HelloWorld.vue'
import App from './App'
createApp(App).use(store).use(router).mount('#app')

新增src\App.tsx:

import { ref, reactive, defineComponent } from 'vue'
const img = require('./assets/logo.png') //eslint-disable-line
export default defineComponent({
  setup() {
    const state = reactive({ name: 'jokcy' })
    const numberRef = ref(1)
    setInterval(() => {
      state.name + -1
      numberRef.value += 1
    }, 1000)
    return () => {
      const number = numberRef.value
      return (
        <div id="app">
          <img src={img} alt="Vue Logo" />
          <p>{state.name + number}</p>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
  margin: 40px 0 0;
  list-style-type: none;
  padding: 0;
  display: inline-block;
  margin: 0 10px;
  color: #42b983;
</style>

修改src\App.tsx

import { ref, reactive, defineComponent } from 'vue'
import HelloWorld from '@/components/HelloWorld.vue'
const img = require('./assets/logo.png') //eslint-disable-line
export default defineComponent({
  setup() {
    const state = reactive({ name: 'jokcy' })
    const numberRef = ref(1)
    setInterval(() => {
      state.name + -1
      numberRef.value += 1
    }, 1000)
    return () => {
      const number = numberRef.value
      return (
        <div id="app">
          <img src={img} alt="Vue Logo" />
          <p>{state.name + number}</p>
          <HelloWorld age={24} />

如果age缺失,编译就会提示缺少必备参数。
包括传字符串也会报错:

还可以复用很复杂的业务逻辑:

import { ref, reactive, defineComponent } from 'vue'
import HelloWorld from '@/components/HelloWorld.vue'
const img = require('./assets/logo.png') //eslint-disable-line
// function renderHelloWorld(num: number) {
//   return <HelloWorld age={num} />
const renderHelloWorld = (num: number) => {
  return <HelloWorld age={num} />
export default defineComponent({
  setup() {
    const state = reactive({ name: 'jokcy' })
    const numberRef = ref(1)
    setInterval(() => {
      state.name + -1
      numberRef.value += 1
    }, 1000)
    return () => {
      const number = numberRef.value
      return (
        <div id="app">
          <img src={img} alt="Vue Logo" />
          <p>{state.name + number}</p>
          {renderHelloWorld(12)}

2种写法都可以。
而且还可以在html代码中使用v-model等:

import { ref, reactive, defineComponent } from 'vue'
import HelloWorld from '@/components/HelloWorld.vue'
const img = require('./assets/logo.png') //eslint-disable-line
// function renderHelloWorld(num: number) {
//   return <HelloWorld age={num} />
const renderHelloWorld = (num: number) => {
  return <HelloWorld age={num} />
export default defineComponent({
  setup() {
    const state = reactive({ name: 'jokcy' })
    const numberRef = ref(1)
    setInterval(() => {
      state.name += 1
      numberRef.value += 1
    }, 1000)
    return () => {
      const number = numberRef.value
      return (
        <div id="app">
          <img src={img} alt="Vue Logo" />
          <p>{state.name + number}</p>
          <input type="text" v-model={state.name} />
          {renderHelloWorld(12)}

其实我们相当于把每个例如div标签看成一个个h函数即可。
当然可以通过input修改上面显示的值:

export default defineComponent({ setup() { const state = reactive({ name: 'jokcy' }) const numberRef = ref(1) // setInterval(() => { // state.name += 1 // numberRef.value += 1 // }, 1000) return () => { const number = numberRef.value return ( <div id="app"> <img src={img} alt="Vue Logo" /> <p>{state.name + number}</p> <input type="text" v-model={state.name} /> {renderHelloWorld(12)}