zl程序教程

您现在的位置是:首页 >  前端

当前栏目

Ant Design of Vue @1.7.8 学习笔记(Vue2版本)

Vue笔记学习 版本 of Design ant 1.7
2023-09-11 14:19:17 时间

0. 相关库版本

  • Vue 2.6.14

  • core-js 3.8.3

  • ant-design-vue 1.7.8

  • babel-plugin-import 1.13.5

  • less 3.13.1

  • less-loader 10.0.0

1. 组件按需引入

安装依赖

npm install ant-design-vue@1.7.8

// 按需引入
npm install babel-plugin-import -D

配置babel

// babel.config.js
module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset'
  ],
  plugins: [
    ["import", { "libraryName": "ant-design-vue", "libraryDirectory": "es", "style": "css" }]
  ]
}
// "css"-引入css文件   true-引入less文件(需要安装less-loader)

按需引用

import { Button } from 'ant-design-vue';
Vue.use(Button)

2. 定制主题

antd 的样式使用了 Less 作为开发语言,并定义了一系列全局/组件的样式变量,你可以根据需求进行相应调整。

所有的变量都在:default.less

常用的变量:

@primary-color: #1890ff; // 全局主色
@link-color: #1890ff; // 链接色
@success-color: #52c41a; // 成功色
@warning-color: #faad14; // 警告色
@error-color: #f5222d; // 错误色
@font-size-base: 14px; // 主字号
@heading-color: rgba(0, 0, 0, 0.85); // 标题色
@text-color: rgba(0, 0, 0, 0.65); // 主文本色
@text-color-secondary: rgba(0, 0, 0, 0.45); // 次文本色
@disabled-color: rgba(0, 0, 0, 0.25); // 失效色
@border-radius-base: 4px; // 组件/浮层圆角
@border-color-base: #d9d9d9; // 边框色
@box-shadow-base: 0 2px 8px rgba(0, 0, 0, 0.15); // 浮层阴影

2.1 在 vue cli 中定制主题(可按需引入)

vue.config.js 配置

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  css: {
    loaderOptions: {
      less: {
        lessOptions: {
          modifyVars: {
            'primary-color': '#1DA57A',
            'link-color': '#1DA57A',
            'border-radius-base': '2px',
          },
          javascriptEnabled: true
        }
      }
    }
  }
})
  • 如果你在使用 babel-plugin-importstyle 配置来引入样式,需要将配置值从'css'改为 true,这样会引入 less 文件。
module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset'
  ],
  plugins: [
    ["import", { "libraryName": "ant-design-vue", "libraryDirectory": "es", "style": true }]
  ]
}

less版本只能是3版本,4版本有的组件样式会报错。

  • 如果你是通过'ant-design-vue/dist/antd.css'引入样式的,改为 ant-design-vue/dist/antd.less

2.2 配置 less 变量文件(全局引入)

另外一种方式是建立一个单独的 less 变量文件,引入这个文件覆盖 antd.less 里的变量。

@import '~ant-design-vue/dist/antd.less'; // 引入官方提供的 less 样式入口文件
@import 'your-theme-file.less'; // 用于覆盖上面定义的变量

注意,这种方式已经载入了所有组件的样式,不需要无法按需加载插件 babel-plugin-import 的 style 属性一起使用。

3. 国际化

ant-design-vue 目前的默认文案是英文,如果需要使用其他语言,可以使用ConfigProviderLocaleProvider 已经弃用了。

import { ConfigProvider, DatePicker, TimePicker } from 'ant-design-vue';
Vue.use(ConfigProvider)
<template>
  <a-config-provider :locale="locale">
    <div id="app">
        <a-date-picker />
        <a-time-picker />
    </div>
  </a-config-provider>
</template>

<script>
import zhCN from 'ant-design-vue/lib/locale-provider/zh_CN';
// import enUS from 'ant-design-vue/es/locale/en_US';
export default {
  name: 'App',
  data() {
    return {
      locale: zhCN,
    };
  },
}
</script>

注意:a-config-provider 需要在#app外部。

4. 主要组件

4.1 Form表单

具有数据收集校验提交功能的表单,包含复选框、单选框、输入框、下拉选择框等元素。

  • 用于创建一个实体或收集信息
  • 需要对输入的数据类型进行校验时
<template>
    <div id="app">
      <a-form :form="form" @submit="handleSubmit">
        <a-form-item label="Note">
          <a-input v-decorator="note_deco" />
        </a-form-item>
        <a-form-item label="Gender">
          <a-select v-decorator="gender_deco" placeholder="请选择性别" @change="handleSelectChange">
            <a-select-option :value="1">male</a-select-option>
            <a-select-option :value="2">female</a-select-option>
          </a-select>
        </a-form-item>
        <a-form-item>
          <a-checkbox :checked="checkedGender" @change="handleChangeRule">Gender is required</a-checkbox>
        </a-form-item>

        <a-form-item label="自定义校验提示(validateStatus help hasFeedback)" has-feedback validate-status="warning" help="校验不通过提示文本">
          <a-input></a-input>
        </a-form-item>

        <a-form-item>
          <a-button type="primary" html-type="submit">Submit</a-button>
        </a-form-item>
      </a-form>
    </div>
</template>

<script>
import zhCN from 'ant-design-vue/lib/locale-provider/zh_CN';
export default {
  name: 'App',
  data() {
    return {
      locale: zhCN,
      form: this.$form.createForm(this, {name: 'aaaa'}),
      note_deco: ['note111', {initialValue: "2345", rules: [{ required: true, message: 'Please input your note!' }]}],
      checkedGender: true
    };
  },
  computed: {
    gender_deco(){ // 动态校验规则 checkedGender
      return ['gender222', {rules: [{required: this.checkedGender, message: 'Please input your gender'}]}]
    }
  },
  methods: {
    handleSubmit(e){ // 提交获取数据
      e.preventDefault();
      this.form.validateFields((err, values) => {
        if(!err){
          console.log(values) // {note111: 'Hi, 1', gender222: 1}
        }
      })
    },
    handleSelectChange(value){ // 设置其他字段的值
      this.form.setFieldsValue({  // 这里不能用v-modal来设置
        note111: `Hi, ${value}`
      })
    },
    handleChangeRule(e){ // 切换字段的校验规则
      this.checkedGender = e.target.checked
      this.$nextTick(() => {
        this.form.validateFields(['gender222'], { force: true });
      });
    }
  }
}
</script>

4.1.1 自定义/第三方表单组件与Form融合

自定义或第三方的表单控件,也可以与 Form 组件一起使用。只要该组件遵循以下的约定:

  • 提供受控属性 value 或其它与 valuePropName-参数) 的值同名的属性。
  • 提供 onChange 事件或 trigger-参数) 的值同名的事件。
  • 不能是函数式组件。

4.1.2 动态增/减表单项

<template>
  <div id="app">
    <a-form :form="form" @submit="handleSubmit">
      <a-form-item v-for="item of form.getFieldValue('keys')" :key="item">
        <a-input v-decorator="[
          `name[${item}]`,
          {
            rules: [
              {
                required: true,
                message: `请输入${item}`
              }
            ]
          }
        ]"></a-input>
        <a-button @click="remove(item)">删除</a-button>
      </a-form-item>
      <a-form-item>
        <a-button type="dashed" @click="add">添加字段</a-button>
      </a-form-item>
      <a-form-item>
        <a-button type="primary" html-type="submit">Submit</a-button>
      </a-form-item>
    </a-form>
  </div>
</template>

<script>
let id = 0;
export default {
  name: 'App',
  data() {
    return {
    };
  },
  beforeCreate(){
    this.form = this.$form.createForm(this, {name: 'dynamic_form_item'})
    this.form.getFieldDecorator('keys', { initialValue: [], preserve: true });
  },
  methods: {
    handleSubmit(e){ // 提交获取数据
      e.preventDefault();
      this.form.validateFields((err, values) => {
        if(!err){
          console.log(values)
        }
      })
    },
    add(){ // 添加字段
      const keys = this.form.getFieldValue('keys');
      const nextKeys = keys.concat(id++);
      this.form.setFieldsValue({
        keys: nextKeys
      })
      console.log(nextKeys);
    },
    remove(key){ // 删除字段
      const keys = this.form.getFieldValue('keys');
      this.form.setFieldsValue({
        keys: keys.filter(k => k !== key),
      });
    }
  }
}
</script>

4.1.3 自定义校验规则

<a-input v-decorator="[
  `name[${item}]`,
  {
    rules: [
      {
        required: true,
        message: `请输入${item}`
      },
      {
        validator: cosutomValidator
      }
    ],
    validateFirst: true
  }
]"></a-input>

cosutomValidator(rule,value, callback){
  if (value !== '123') {
      callback('输入必须为123!')
  }
  callback()
}

Form 没有采用v-model的方式,data中没有显式的表示各个字段,一般适用于数据收集、校验。

4.2 FormModel 表单

  • 需要对输入的数据类型进行校验时。
<template>
  <div id="app">
    <a-form-model ref="ruleForm" :model="form" :rules="rules">
      <a-form-model-item label="Name" prop="name">
        <a-input v-model="form.name"></a-input>
      </a-form-model-item>
      <a-form-model-item label="Region" prop="region">
        <a-select v-model="form.region" placeholder="请选择地区">
          <a-select-option value="shanghai">上海</a-select-option>
          <a-select-option value="beijing">北京</a-select-option>
        </a-select>
      </a-form-model-item>
      <a-form-model-item :wrapper-col="{ span: 14, offset: 4 }">
        <a-button type="primary" @click="onSubmit">提交</a-button>
        <a-button @click="resetForm">重置</a-button>
      </a-form-model-item>
    </a-form-model>
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      form: {
        name: "",
        region: undefined
      },
      rules: { // 校验规则
        name: [
          {required: true, message: '请输入姓名', trigger: 'blur'},
          { min: 3, max: 5, message: 'Length should be 3 to 5', trigger: 'blur' },
          {validator: (rule, value, callback) => {
            if(value === '3333'){
              callback()
            }else{
              callback(new Error("必须为3333"))
            }
          }, trigger: 'blur'}
        ],
        region: [
          {required: true, message: '请选择', trigger: 'change'}
        ]
      }
    };
  },
  methods: {
    onSubmit(){
      this.$refs.ruleForm.validate(valid => {
        if (valid) {
          alert('submit!');
        } else {
          console.log('error submit!!');
          return false;
        }
      });
    },
    resetForm(){ // 重置表单
      this.$refs.ruleForm.resetFields();
    }
  }
}
</script>

4.2.1 动态增/减表单项

<template>
  <div id="app">
    <a-form-model ref="ruleForm" :model="form">
      <a-form-model-item v-for="(domain, index) in form.domains" :key="domain.key" 
        label="Domains" :prop="('domains.'+index+'.value')"
        :rules="{required:true,message:'domain can not be null',trigger:'blur'}"
      >
        <a-input v-model="domain.value"></a-input>
      </a-form-model-item>
      
      <a-form-model-item :wrapper-col="{ span: 14, offset: 4 }">
        <a-button type="primary" @click="addDomain">添加</a-button>
        <a-button type="primary" @click="onSubmit">提交</a-button>
        <a-button @click="resetForm">重置</a-button>
      </a-form-model-item>
    </a-form-model>
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      form: {
        domains: []
      }
    };
  },
  methods: {
    addDomain(){
      this.form.domains.push({
        value: '',
        key: Date.now(),
      });
    },
    removeDomain(item) {
      let index = this.form.domains.indexOf(item);
      if (index !== -1) {
        this.form.domains.splice(index, 1);
      }
    },
    onSubmit(){
      this.$refs.ruleForm.validate(valid => {
        if (valid) {
          alert('submit!');
        } else {
          console.log('error submit!!');
          return false;
        }
      });
    },
    resetForm(){
      this.$refs.ruleForm.resetFields();
    }
  }
}
</script>

4.2.2 Form.item有多个子元素时需要主动监听事件(校验)

Form.Item 会对唯一子元素进行劫持,并监听 blurchange 事件,来达到自动校验的目的,所以请确保表单域没有其它元素包裹。如果有多个子元素,将只会监听第一个子元素的变化。

如果有多个子元素,有可能会影响校验的显示。可以在表单元素上自行绑定blur和change事件。

<a-form-model-item prop="form.name" ref="name" :autoLink="false">
  <a-input v-model="other" />
  <span>hahha</span>
  <div>
    <a-input
      v-model="form.name"
      @blur="() => {$refs.name.onFieldBlur()}"
      @change="() => {$refs.name.onFieldChange()}"
    />
  </div>
</a-form-model-item>

FormModel Vs Form区别:

  • 本质区别是双向绑定
  • FormModel 需要在data中定义字段名称,Form是$form对象手动收集
  • FormModel 中需要在Item上定义prop字段(用于校验),Form需要定义decorator
  • FormModel 校验放在rules中,Form校验定义在decorator中
  • FormModel rules是绑定在Form/FormItem上,Form中rules 是绑在输入控件上
  • FormModel 需要注意Form.Item 会对唯一子元素进行劫持,并监听 blurchange 事件,来达到自动校验的目的,所以请确保表单域没有其它元素包裹。如果有多个子元素,将只会监听第一个子元素的变化(确保输入控件是第一个子元素)
  • 隐藏元素不参与校验,在隐藏元素上使用 v-if 而不用 v-show

4.3 Table 表格

  • Table上需要加rowKey,或者在data中加入key
  • 单元格自动省略,column数据中加入 ellipsis: true
  • 远程请求数据,Table加@change事件根据页数请求数据更新dataSrouce
  • 树形数据,data中包含chlidren数组
  • 固定列,columnfixed: 'left', 固定左侧
  • 固定表头需要指定column的宽度
  • 筛选 row-selection
  • column.dataIndex列数据在数据项中对应的 key,支持 a.b.c 的嵌套写法
  • 如果设置了唯一的dataIndex,可以不设置column.key
  • column.customRender 设置自定义渲染,(当前行的值,当前行数据,行索引),非插槽
  • column.slots 配置支持 slot 的属性,如 slots: { filterIcon: ‘XXX’}
  • column.scopedSlots 配置支持slot-scope的属性,如 scopedSlots: { customRender: ‘XXX’}

slots customRender scopedSlots.customRender

<template>
  <div id="app">
    <a-table :columns="columns" :data-source="data" rowKey="name">
      <template #age_1="text, record, index, column">{{ text + ' year old' }}</template>
      <template #customTitle>年龄</template>
    </a-table>
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      columns: [
        { dataIndex: 'name', title: '姓名' },
        { 
          dataIndex: 'age',
          // title: '年龄',
          slots: { title: 'customTitle' },
          // customRender: (text, row, index) => {
          //   console.log(text, row, index)
          //   if (text < 18) {
          //     return <a href="javascript:;">{text}</a>;
          //   }
          //   return text;
          // },
          scopedSlots: { customRender: "age_1" }
        }
      ],
      data: [
        { name: 'zhangsan', age: 15 },
        { name: 'lisi', age: 30 }
      ]
    };
  }
}
</script>
  • slots 表格支持的插槽,如 title footer filterIcon
  • customRender 直接自定义渲染结果,非插槽
  • scopedSlots.customRender 自定义渲染插槽,有text, record, index, column四个插槽参数
  • customRender 优先级 比 scopedSlots.customRender 高