AntDesignVue使用尝鲜

August 12, 2019

1375 6 minutes and 15 seconds
AntDesignVue使用尝鲜

这次更新博客主要是总结上两周干的事情,方便整理一下目前的进度和后续的思路。首先是事情的起源,主要是因为在改写 simpleui 的过程中,总是会有一些不方便自己使用的东西,并且并不是很满意 simpleui 的展示效果,同时想扩展 simpleui 的使用性;后续在改写过程中,自己整理了一套新的解决思路,感觉可以将现代前端的组件化思路带入到 django template 里面来,所以自己重新开了一套 admin 的主题框架,经过两周的编写,越来越深入的感觉不仅可以做一套 admin 的 theme 出来;甚至可以像之前比较流向的 xadmin 一样写一套不同于 django admin 的中后台管理框架,所以应运而生了一个想法,经过两周的尝试,确实可以行得通。不过中间确实遇到了很多问题,需要将这些问题记录一下~

Q: 选择前端渲染还是后端渲染

A: 这个问题真的是个非常困扰人的问题,首先是想使用 django 的框架作为快速开发的后端,但是同时呢也不想舍弃现在前端在页面展示上的技术领先,两者皆不可抛。那么如何结合两者到一起呢? django 的 template 有着当时那个时代领先的 extends 和 include 机制,转念一想其实这一套机制本质上是不是十分相似于现在前端的 component 吗?于是从这里下手,进行尝试和构建~ 具体尝试过程就跳过不谈了,最终通过一种方式实现了这个机制


# 首先声明 a.html 最为我们的目标组件,进行开发
# 在 a.html 中 通过 <script type="x-template">...</script> 进行组件声明

<script type="text/x-template" id="home-iframe-content">
  <div :style="contentStyle">
    <iframe :src="href" :style="iframeStyle" frameborder="0"></iframe>
  </div>
</script>

<script type="text/javascript">
  Vue.component('iframe-wrapper', {
    delimiters: ['<%', '%>'],
    props: {
      href: {
        type: String,
        required: true
      },
      height: {
        type: String,
        required: false
      },
      width: {
        default: '100%',
        type: String,
        required: false
      },
      overflow: {
        default: 'auto',
        type: String,
        required: false
      }
    },
    template: '#home-iframe-content',
    data() {
      return {
        contentStyle: {
          margin: '0',
          padding: '0',
          borderRadius: '5px',
        },
        iframeStyle: {
          height: this.height,
          width: this.width,
          overflow: this.overflow
        }
      }
    }
  })
</script>

# 之后我们可以在想引用该组件的地方通过 django 的 include 方式进行导入
# 在 b.html 中我们通过如下方式可以使用该组件

{% include 'web/a.html' %}

<script type="text/x-template" id="layout-demo-a">
    ···
    <a-tab-pane v-for="(pane, index) in activePanes" :key="pane.key">
    <span slot="tab"><a-icon :type="pane.icon"></a-icon><% pane.name %></span>
    <iframe-wrapper :href="pane.content" :height="height"></iframe-wrapper>
    </a-tab-pane>
    ···
</script>

Q: 如何混用 vue 的 template 和 django 的 template

A: 在这里目前只遇到了一种情况下的两者语法重复的问题,在 django 中对于 render 中的 context 取值是通过 双大括号进行的

{{ }}

但这同时也是 vue 的取值方式,这里我们可以通过对 vue 的声明进行修改

delimiters: ['<%', '%>']

将 vue 的取值方式改为 尖括号和百分号结合的方式,此外还有一种方式,就是在 django 自带的 tags 中包含了

openvariable => {{  closevariable => }}

两种声明方式,这样我们可以在 django render template 之后在 vue 通过浏览器渲染数据时依然可以取到 双大括号的取值符号。

Q: 如何通过 extends 方法扩展 vue 全局的 instance

A: 我们通过在 base.html 中声明根 div 中声明了 vue 实例,但是通过 extends 方式继承了 base.html 页面之后,每个页面都需要声明不同的 data methods 和 vue 的其他属性方式,但是我们不能够将这些代码统统放到 base.html 页面里面,这样的话,势必造成内容的混乱。我们可以通过 vue 的 mixin 方式进行属性值的混入,我们在 base.html 中申明一个 vue 实例,混入一个 mixins 的对象,然后将独享绑定到 window 实例里面,这样我们就可以在继承 base.html 之后,通过 django render 的过程中生成所需要的 mixins 属性,增加到 windows.mixins 里面,这样在 后续 vue 实例运行时,就可以取到我们的实例属性了。

Q: 如何需改 django forms widgets 达到修改 django forms render 样式更改

A: 当我们实现了上述的三种方式之后,我们可以合理构建我们的 django 和 vue 的’混合体生物’了,但是还是无法渲染 django forms 的展示方式和内容,毕竟有点格格不入,相当不协调,配上我们的 ant design vue,所以我们需要修改 django forms widgets 来达到渲染我们需要的 vue 组件的问题,还好是最基础的组件和组织形式,所以比较容易实现~ 在 django 的 settings 里面添加如下内容就行了


INSTALLED_APPS = [
    'django.forms',
    ...
]

FORM_RENDERER = 'django.forms.renderers.TemplatesSetting'

# 并且在 django 的 templates 项目中创建 widgets 文件夹就行了,目录结构同 django forms 的

附:粘贴上几张正在做的 django admin 框架的 贴图

Dashboard 页面 image Models 内容页 image

PS: 这个 框架开在开发阶段 后续会在 钟馗沙箱中作为展示前端使用 并且后续也将开源 名字暂定 django-vue-admin