跳转到内容

使用 Vue 开发自定义控件

一、初衷:

  1. Trantor 集成内置的 Engine 组件无法满足业务的需要

  2. 使用者在开发自定义容器与控件的时候需要使用 Vue 框架来开发

    对此,我们使用 vuera 来兼容 Vue框架开发的组件,让用户能够使用 Vue 以及周边生态来开发自定义容器与控件

二、 准备工作

  1. 环境搭建

    环境搭建具体请参考 自定义数据容器与控件

    使用例子请参考 Demo

  2. Vue 环境准备

    • 安装 t-tools

      Terminal window
      yarn add t-tools -g
      // or
      npm install t-tools -g

      注意,t-tools 版本需要使用新版本防止部分功能不生效,目前需使用 ^0.1.7

    • 安装依赖

      在根目录下 package.json 中新增以下依赖:

      {
      "devDependencies": {
      "@terminus/t-tools": "0.1.7",
      "@terminus/t-tools-externals-deps": "0.0.10",
      "@terminus/t-tools-externals-lazy-deps": "0.0.10",
      "@terminus/t-tools-externals-lazy-pkgs": "0.0.10",
      "babel-loader": "^8.2.2",
      "babel-plugin-import": "^1.13.3",
      "css-loader": "4.3.0",
      "vue-loader": "^15.9.8",
      "vue-template-compiler": "^2.6.14",
      "webpack": "^4.29.5",
      "webpack-merge": "^5.7.0"
      },
      "dependencies": {
      "ant-design-vue": "^1.7.8",
      "core-js": "2",
      "vue": "^2.6.14",
      "vue-router": "^3.5.2",
      "vuera": "^0.2.7"
      },
      }
    • 配置根目录 settings.js(webpack 配置)

      const { dynamicExternals } = require('@terminus/t-tools-externals-lazy-pkgs');
      const { VueLoaderPlugin } = require('vue-loader')
      const webpack = require('webpack')
      module.exports ={
      dist: './dist',
      dev:{
      port: 8000,
      browser: true
      },
      isTrantor: true,
      externals: [ 'react', 'react-dom', 'moment', 'lodash', 'classnames', 'classnames/bind', 'mobx', 'mobx-react', '@terminus/nusi', '@terminus/nusi-engine', '@terminus/i18n-plat-sdk-js'],
      dynamicExternals,
      // 这里需要改为 true,让自定义组件开发时使用用户安装的依赖
      node_modules: true,
      tool: 'webpack',
      cssmodule: true,
      // 配置 webpack,让 t-tools 获得处理 vue、css 的能力
      webpackConfig: (webpackConfig, webpackMerge)=> {
      const config = {
      module: {
      rules: [
      {
      test: /\.vue$/,
      loader: 'vue-loader'
      },
      {
      test: /\.css$/,
      use: ['style-loader', 'css-loader']
      }
      ],
      },
      plugins: [
      new VueLoaderPlugin(),
      new webpack.WatchIgnorePlugin([
      /\.d\.ts$/
      ])
      ]
      }
      webpackConfig.module.rules[0].options['appendTsSuffixTo'] = [/\.vue$/]
      return webpackMerge.merge(webpackConfig, config);
      }
      }

三、开发自定义容器(组件)

  • /src/components/Demo/index.tsx

    import React from 'react'
    import { VueInReact } from 'vuera'
    import MyVueComponent from './Demo.vue'
    // 容器类型
    import { ListContainer } from '@terminus/nusi-engine'
    export default class extends ListContainer {
    render() {
    // vuera
    const Component = VueInReact(MyVueComponent)
    return (
    // 将ListContainer 的属性透传到 vue 组件中
    <Component message='Hello from Vue!' ctx={this.props}/>
    )
    }
    }
  • /src/components/Demo.vue

    <template>
    <a-form :form="form" :label-col="{ span: 5 }" :wrapper-col="{ span: 12 }" @submit="handleSubmit">
    <a-form-item label="Note">
    <a-input
    v-decorator="['note', { rules: [{ required: true, message: 'Please input your note!' }] }]"
    />
    </a-form-item>
    <a-form-item label="Gender">
    <a-select
    v-decorator="[
    'gender',
    { rules: [{ required: true, message: 'Please select your gender!' }] },
    ]"
    placeholder="Select a option and change input text above"
    @change="handleSelectChange"
    >
    <a-select-option value="male">
    male
    </a-select-option>
    <a-select-option value="female">
    female
    </a-select-option>
    </a-select>
    </a-form-item>
    <a-form-item :wrapper-col="{ span: 12, offset: 5 }">
    <a-button type="primary" html-type="submit">
    Submit
    </a-button>
    </a-form-item>
    </a-form>
    </template>
    <!-- 这边使用 lang 为 ts -->
    <script lang="ts">
    import Vue from 'vue';
    import Antd from 'ant-design-vue';
    import 'ant-design-vue/dist/antd.css';
    Vue.use(Antd);
    export default {
    props: {
    // this.props 属性中可以拿到原 container 中的所有属性方法
    // 具体使用方法参考 [自定义控件与容器的实践](https://trantor-docs.app.terminus.io/v0.17.x/doc/developer-guide/custom-component#%E5%9B%9B%E3%80%81%E8%87%AA%E5%AE%9A%E4%B9%89%E6%8E%A7%E4%BB%B6%E4%B8%8E%E5%AE%B9%E5%99%A8%E7%9A%84%E5%AE%9E%E8%B7%B5)
    ctx: Object
    },
    data() {
    return {
    formLayout: 'horizontal',
    form: this.$form.createForm(this, { name: 'coordinated' }),
    };
    },
    mounted() {
    console.log('xxxxxxxxxxxx', this)
    },
    methods: {
    handleSubmit(e) {
    e.preventDefault();
    this.form.validateFields((err, values) => {
    if (!err) {
    console.log('Received values of form: ', values);
    }
    });
    },
    handleSelectChange(value) {
    console.log(value);
    this.form.setFieldsValue({
    note: `Hi, ${value === 'male' ? 'man' : 'lady'}!`,
    });
    },
    }
    };
    </script>
  • manifest.json

    自定义容器描述文件

    {
    "Demo": {
    "type": "container",
    "entry": {
    "CustomComponents/Demo": "./components/Demo/index.tsx"
    },
    "model": "",
    "description": "Vue Demo 容器组件。"
    }
    }

注意事项

09 - 017 自定义组件使用 vue 开发方式均一致,注意使用最新的 t-tools,如有疑问可以直接钉钉联系许超

相关链接: