业务组件示例 - 登陆组件

业务组件开发的详细过程

  • 按照开发文档先创建组件整体目录

demo-login
    designer/
        components/
            index.vue   // 设计时组件,用于组件编辑
        index.js        // 设计时入口页面 
    src/
        views/
            index.vue   // 具体业务组件
        index.js        // 业务组件入口文件
    index.js            // 业务组件入口文件
    package.json        // 配置文件
  • 开发具体实现

demo-login/index.js只需要按照约束来编码: ``` js import runtime from './src' import designer from './designer'

export default {
// 运行时源码
... runtime,

// 设计器配置 
designer
}
```

下面我们以开发一个登陆用的组件为例,首先一般简单的登陆包含三个部分: 用户名输入框、密码输入框、和登录按钮三部分。所以我们先简单的在src/views/index.vue中这样写:

<template>
    <div>
        <div class='group'>
            <input :title="用户名" v-model="account"/>
        </div>
        <slot></slot>
        <div class='group'>
            <input title="密码" v-model="password"/>
        </div>
        <div class='group'>
            <button type="primary" :show-loading='loading'>登陆</button>
        </div>
    </div>
</template>
<script>
    export default {
        data() {
            return {
                account: '',
                password: '',
                loading: false,
            }
        },
    }
</script>

这里我们直接使用了vux的组件库来快速开发。目前我们已经支持生成小程序,由于小程序的一些限制,vuex会被被逐步移除。你可以自己来实现这些。

嗯,如果你的业务就是这样,其实已经算完成了。不过如果以后出现类似的或者更复杂的需求,谁又愿意再去做这些重复的工作呢。
因此,我们可以给组件设计一些props来做扩展,比如说‘‘用户名’’,以后可能会使手机号码或者邮箱等等,接下来我们来做一些改造。

<template>
    <div>
        <div class='group'>
            <input :title="accountName" v-model="account" :placeholder='accountPlaceholder'/>
        </div>
        <div class='group'>
        <slot></slot>
        </div>
        <div class='group'>
            <input title="密码" v-model="password" :placeholder='passwordPlaceholder'/>
        </div>
        <div class='group'>
            <button type="primary" :show-loading='loading' @click.native='submit'>{{btnName}}</button>
        </div>
    </div>
</template>

<script>
    import axios from '@platform/axios'

    export default {
        ... // 省略一些代码
        props: {
            accountName: {   // 用于修改用户名标题
                type: String,
                default: '用户名'
            },
            accountPlaceholder: String,     // 用于修改用户名输入栏的提示
            passwordPlaceholder: String,    // 用于修改密码输入栏的提示
            accountField: String,           // 用于修改接口中'用户名'对应的字段
            passwordField: String,          // 用于修改接口中'密码'对应的字段
            btnName: {                      // 用于修改按钮显示的文本
                type: String,
                default: '登录'
            },
            url: String,                    // 用于修改接口的请求地址
            href: Object,                   // 用于修改登陆后挑战的地址
        },
        ...
        methods: {
            submit() {                      // 提交操作
                this.loading = true;
                axios.post(this.url, {
                    [this.accountField]: this.account,
                    [this.passwordField]: this.password,
                }).then(() => {
                    this.loading = false
                    this.$location.push(this.href)
                }).catch(() => {
                    this.loading = false
                })
            }
        },
    }
</script>

这样改变后,我们这个登陆组件已经健壮了很多。你所能想到的能配置的内容都可以交给props来接收。 接下来我们来对src/index.js入口文件编码

import component from './views/index.vue'

export default {
    component,
}

好了,业务组件已经开发完成。我们设计了这些props主要是为设计时组件提供接口,这样我们在编辑区域做的修改可以实时反映到业务组件上。

// designer/components/index.vue
<template>
    <div class="content">
        <el-form :label-position="'right'"
            label-width="120px">
            <el-form-item label="账号绑定字段">
                <el-input v-model.trim="accountField"
                    @input="submit"
                    placeholder="请输入账号绑定的字段"></el-input>
            </el-form-item>
            <el-form-item label="账号显示名称">
                <el-input v-model.trim="accountName"
                    @input="submit"
                    placeholder="请输入账号名称"></el-input>
            </el-form-item>
            <el-form-item label="密码绑定字段">
                <el-input v-model.trim="passwordField"
                    @input="submit"
                    placeholder="请输入密码绑定的字段"></el-input>
            </el-form-item>
            <el-form-item label="账号输入提示">
                <el-input v-model.trim="accountPlaceholder"
                    @input="submit"
                    placeholder="请输入值为空时的输入提示"></el-input>
            </el-form-item>
            <el-form-item label="密码输入提示">
                <el-input v-model.trim="passwordPlaceholder"
                    @input="submit"
                    placeholder="请输入值为空时的输入提示"></el-input>
            </el-form-item>
            <el-form-item label="按钮显示文本">
                <el-input v-model.trim="btnName"
                    @input="submit"
                    placeholder="请输入按钮显示文本"></el-input>
            </el-form-item>
            <el-form-item label="请求接口地址">
                <el-input v-model.trim="url"
                    @input="submit"
                    placeholder="请输入请求接口API地址"></el-input>
            </el-form-item>
            <el-form-item label="页面跳转地址">
                <link-editor v-model="href"
                    @change="changeLinkEvent"></link-editor>
            </el-form-item>
        </el-form>
    </div>
</template>

<script>
    import { LinkEditor } from '@designer'  // 引用了公共组件:路由/外链选择组件
    
    export default {
        props: {
            value: Object
        },
        components: {
            LinkEditor
        },
        data() {
            return {
                accountField: '',
                passwordField: '',
                accountName: '',
                accountPlaceholder: '',
                passwordPlaceholder: '',
                btnName: '',
                url: '',
                href: ''
            }
        },
        watch: {
            value: {
                immediate: true,
                handler(value) {
                    const props = value.props
                    this.accountField = props.accountField
                    this.passwordField = props.passwordField 
                    this.accountName = props.accountName
                    this.accountPlaceholder = props.accountPlaceholder
                    this.passwordPlaceholder = props.passwordPlaceholder
                    this.btnName = props.btnName
                    this.url = props.url
                    this.href = props.href
                }
            }
        },
</script>

设计时组件中我们为业务组件的每个接口参数都提供一个输入框来更改配置。这里需要注意的是:设计时组件存在一个名为value的prop,这个接口是为了接收在设计时组件入口文件中配置的一些初始数据,同时通过watch函数监听value,将初始props赋值到设计时组件

那又如何把在编辑页面做的调整回传给业务组件呢?

实际上引擎内置了触发方法。

// designer/components/index.vue
<script>
    ...
     methods: {
            submit() {
                this.$nextTick(() => {
                    this.$emit('input', {
                        props: {
                            accountField: this.accountField,
                            passwordField: this.passwordField,
                            accountName: this.accountName,
                            btnName: this.btnName,
                            accountPlaceholder: this.accountPlaceholder,
                            passwordPlaceholder: this.passwordPlaceholder,
                            url: this.url,
                            href: this.href,
                        }
                    })
                })
            },
     }
    ...
</script>

在输入框的input事件触发时调用submit(方法名自定义)方法, 通过全局注册的自定义‘input’事件,将所涉及的参数回传给业务组件。

目前需要将涉及的所有prop都加入到props字段中。

接下来我们可以给业务组件提供一些预览数据:

// designer/index.js
import component from './components/index.vue'

export default {
    name: '登陆组件',
    previewData: {
        props: {
            accountField: 'account',
            passwordField: 'password',
            accountName: '用户名',
            accountPlaceholder: '',
            passwordPlaceholder: '',
            btnName: '登陆',
            url: '',
            href: {}
        }
    },
    ctrl: {
        component
    }
}

业务组件需要的prop字段都可以在previewData中定义,这样就会在初始化的时候绑定到业务组件。
现在,一个简单的登陆组件已经开发完成了。
不过,为了避免一些纠纷,一般我们会提供一份‘用户协议’供用户阅读。在点击协议查看时我们会在一个新页面里呈现内容,这时我们就需要用到组件的路由了。

// src/views/index.vue
<template>
    <div>
        <div class='group'>
            <input :title="accountName" v-model="account" :placeholder='accountPlaceholder'/>
        </div>
        <div class='group'>
            <input title="密码" v-model="password" :placeholder='passwordPlaceholder'/>
        </div>
        <div class='agree'>
            <check-icon :value.sync="agree"></check-icon>
            <span class='agreement' @click='route'>用户协议</span>
        </div>
        <div class='group'>
            <button type="primary" :show-loading='loading' @click.native='submit'>{{btnName}}</button>
        </div>
    </div>
</template>
<script>
    ...
     methods: {
            ...
            route() {
                this.$router.push('/agreement') // 指定路由的路径
            }
            ...
     }
    ...
</script>

然后创建src/views/agreement.vue:

<template>
    ...
        <br />
  使用本网站前请您仔细阅读以下条款。若使用本网站则表明您已知道并接受这些条款。如果不接受这些条款请不要使用本网站。<br />
<br />
    ...
  2、 信息发布<br />
  本站的信息按原样提供,不附加任何形式的保证,包括适销性、适合于特定目的或不侵犯知识产权的保证。此外,明源云也不保证本站信息的绝对准确性和绝对完整性。本站中的内容或在这些内容中介绍的产品或相关信息等会随时变更,恕不另行通知。本站中的内容也可能已经过期,明源云不承诺更新它们。<br />
<br />
    ...
</template>
...

接着我们需要配置路由:

// src/routes/index.js
const agreement = () => import('../views/agreement.vue') //导入agreement组件
const routes = [{
    name: 'agreement',  // 路由名称
    path: '/agreement', // 路由路径
    body: {
        header: {
            title: '用户协议',  // 用于修改头部标题的显示
        },
        content: {
            items: [agreement] // 显示协议内容
        }
    }
}]

export default routes

这里只展示了基础的功能,更多配置功能请参考开发文档

最后在src/index.js入口文件注册路由:

import component from './views/index.vue'
import routes from './routes'

export default {
    component,
    routes
}

这样我们就实现了组件内路由的功能了。

当然,你能做的不仅仅如此。如果你想使你的登陆组件可以通过拖拉拽的方式加入一些子组件,比如验证码输入框等,实现起来也很简单:

// src/views/index.vue
<template>
    <div>
        <div class='group'>
            <input :title="accountName" v-model="account" :placeholder='accountPlaceholder'/>
        </div>
        <slot></slot>
        <div class='group'>
            <input title="密码" v-model="password" :placeholder='passwordPlaceholder'/>
        </div>
        <div class='group'>
            <button type="primary" :show-loading='loading' @click.native='submit'>{{btnName}}</button>
        </div>
    </div>
</template>

在业务组件中提供一个插槽,同时在designer/index.js入口文件上做上相应的更改:

import component from './components/index.vue'

export default {
    name: '登陆组件',
    slotNames: 'default',
    ... // 省略
}

这样就能可以实现将其他组件往登陆组件拖拽了。

更多插槽实现请参考详细文档

以上就是开发一个业务组件的基本流程,当然我们能提供的还有更多,查看我们的开发文档加入开发吧!