vue3.0 学习使用记录

vue学习

在最近的一次项目中,前端js框架里使用了vue。vue的编程思想比较新颖,用起来也感觉高效便捷。由于个人原因,做完这个项目之后可能就接触不到前端的内容了,所以记录这个项目中对vue的学习和理解。对自己的要求是可以不记得具体的技术,但是要记住这个框架的思想。

vue简介

vue是一个JavaScript框架,最大的特点是响应式
响应式原理:意思就是在改变数据的时候,视图会跟着更新
对比jquery来说,jquery是通过语法操作html中的标签,从而改变标签的属性,值等。而vue是需要改变的html标签绑定一个变量,当变量发生变化时html中的标签的值也发生变化。

vue3.0安装

1. 安装node

sudo tar xf node-v14.16.1-linux-x64.tar.xz -C /opt

cd /opt/node-v14.16.1-linux-x64/bin
sudo ln -s /opt/node-v14.16.1-linux-x64/bin/node /usr/local/bin/node
sudo ln -s /opt/node-v14.16.1-linux-x64/bin/npm /usr/local/bin/npm

# 验证版本
node -v
npm -v

2. 装淘宝镜像

npm install -g cnpm --registry=https://registry.npm.taobao.org
sudo ln -s /opt/node-v14.16.1-linux-x64/bin/cnpm /usr/local/bin/cnpm

cnpm -v

3. vue环境安装

cnpm -g vue @vue/cli
sudo ln -s /opt/node-v14.16.1-linux-x64/bin/vue /usr/local/bin/vue

vue -V

vue3.0要求4.5以上的版本

4. 创建新项目

vue create todolist

启动项目

访问页面

vue 项目架构

一个新建的vue项目架构如下:

assets: 存放静态资源、图标、图片
components:存放一般组件,公共组件,通用组件
router:配置路由。vue中实现页面跳转需要定义的路由
sotre: 配置状态管理
views:vue 主要业务实现的位置
App.vue:页面的入口文件,通常是入口页面。上面的首页就是该文件中的。

组件

组件是vue功能的集合。可以把每一个.vue文件看成一个组件,包括App.vue也是一个组件,一个关于主页面的组件。组件的结构由三部分组成:

  1. template
  2. script
  3. style
<template>
    
</template>


<script>
    
</script>


<style scoped lang="scss">
    
</style>

组件结构

一个组件包括很多内容,大体上可以分为:

  1. defineComponent 引入
  2. 子组件引入(可选)
  3. 组件定义
  • 组件名称
  • 接收父组件的数据(可选)
  • 定义子组件(可选)
  • setup 定义变量和函数

setup中定义变量和函数,最后都要通过return返回,只有return中返回的变量才能被页面上响应。

//------------------------数据的展示------------------------
<template>
  
</template>
    

//--------------------------数据的定义和返回---------------------
<script>

// 所有的组件都需要从vue中定义
import {defineComponent} from 'vue'
import NavHeader from '@/components/navHeader/NavHeader'

// 调用defineComponent中的组件
export default defineComponent({
    name: 'Home', // 组件名称
    
    // 接收父组件的数据
    props: {

    },
    // 定义子组件
    components:{
       
    },
    setup(props, ctx) {
        
        // 数字
        let num = ref(10)
        
        return {
            num
        }
    }
})

</script>


<style scoped lang='scss'>    
</style>

数据结构

vue中常见的数据结构包括:

  • 数字
  • 字符串
  • 字典
  • 数组

ref 用来定义响应式变量,只可以定义单个变量
reactive 用来打包定义变量,可以定义多个变量

数据定义

//------------------------数据的展示------------------------
<template>
    <div>
        <nav-header></nav-header>
        <nav-main></nav-main>
        <nav-footer></nav-footer>
        {{ data.num }}
        {{ data.name }}
        {{ data.arr.slice(0,2) }}
        {{ data.obj }}
    </div>
</template>
    

//--------------------------数据的定义和返回---------------------
<script>

// 所有的组件都需要从vue中定义
import {defineComponent, ref, reactive} from 'vue'


// 调用defineComponent中的组件
export default defineComponent({
    name: 'Home', // 组件名称
    
    // 接收父组件的数据
    props: {

    },
    // 定义子组件
    components:{
        NavHeader,
        NavMain,
        NavFooter
    },
    setup(props, ctx) {
        
        // 数字
        let num = ref(10)
        
        // 字符串
        let name = ref('jack')
       
        // 数组  
        let arr = ref(['a', 'b', 'c', 'd'])
        
        // 字典
        let obj = ref({age: 20})

        // reactive 方法 
        let data = reactive({
            name: 'jack',
            age: 20,
            ojb: {
                price: 20
            },
            arr: ['a', 'b', 'c', 'd']
        })
        return {
            data
        }
    }
})

</script>



<style scoped lang='scss'>    
</style>

在实际的编程过程中,似乎不需要用关键字refreactive。如在未来网络学院的开发过程中,一个vue文件定义的相应式变量如下:

 return {
        tableConfig: {
          config: tableConfigBase(),
          tableData: [],
          selectedRows: [],
        },
        createModal: {
          visible: false
        },
        createForm: {
          dialog_title: '添加讲师',
          name: '',
          title: '',
          profile: '',
          img: [],
        },
        searchForm: {
          keywords: ''
        },
        createRules: {
          name: [
            { required: true, message: '请输入名称', trigger: 'change' },
            { min: 2, max: 20, message: '长度在 2~20 个字符内', trigger: 'change' },
            {validator: nameUniqueAcq, trigger: 'blur'},
            {validator: urlAcq, trigger: 'blur'},
          ],
          title: [
            { required: true, message:'请输入头衔', trigger: 'change' },
            { min: 1, max: 500, message: '长度在 2~500 个字符内', trigger: 'change' },
          ],
          profile: [
            { required: false, message: '长度在 200 个字符内', trigger: 'change' },
          ],
          img: [
            { required: true, message: '请上传图片', trigger: 'change'}
          ],
        },
        pager:{},
        disabledDel: 'disabled',
        disableDis: 'disabled',
        disableEn: 'disabled',
      }

vue基础语法

指令

Vue.js的指令是以v-开头的,它们作用于HTML元素,指令提供了一些特殊的特性,将指令绑定在元素上时,指令会为绑定的目标元素添加一些特殊的行为,我们可以将指令看作特殊的HTML特性(attribute)。

作用
指令的作用是当表达式的值改变时,相应地将某些行为应用到 DOM 上。

v-if
v-if可以实现条件渲染,Vue会根据表达式的值的真假条件来渲染元素。

<a v-if="ok">yes</a>

如果属性值ok为true,则显示。否则,不会渲染这个元素。

v-else
v-else是搭配v-if使用的,它必须紧跟在v-if或者v-else-if后面,否则不起作用。

<div>ok的值为:{{ ok }}</div>
<div v-if='ok'>如果值为true显示</div>
<div v-else>如果值为false显示</div>

v-for
用v-for指令根据遍历数组来进行渲染

两种渲染方式

<div v-for="(item,index) in items"></div>   //使用in,index是一个可选参数,表示当前项的索引
<div v-for="item of items"></div>   //使用of
 let list = ref([11,23,34,45,56])
 
<div v-for='(index, item) in list'>
    <span>{{ item }}--{{ index }}</span>
</div>

v-model
这个指令用于在表单上创建双向数据绑定。限制在<input><select><textarea>components中使用

 <input v-model='input_value'  @keydown.enter="enter"/>
let input_value = ref('')
let enter = () => {
    console.log(input_value.value)
}

![image_1f5i6uiup1irig8hr8pdd4fr2q.png-21.3kB][15]

<1> lazy 默认情况下,v-model同步输入框的值和数据。可以通过这个修饰符,转变为在change事件再同步。

<input v-model.lazy="msg">

<2> number 自动将用户的输入值转化为数值类型

<input v-model.number="msg">

<3> trim:自动过滤用户输入的首尾空格

<input v-model.trim="msg">

v-on
v-on主要用来监听dom事件,以便执行一些代码块。表达式可以是一个方法名。
简写为:@

<button @click='change_ok'>点击按钮</button>

let change_ok = () => {
    console.log('00000')
    ok.value = !ok.value
}

<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>

<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>

<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>

<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>

<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即元素自身触发的事件先在此处处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>

<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>

<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>

<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 -->
<!-- 而不会等待 `onScroll` 完成  -->
<!-- 这其中包含 `event.preventDefault()` 的情况 -->
<div v-on:scroll.passive="onScroll">...</div>

v-bind
v-bind用来动态的绑定一个或者多个特性。没有参数时,可以绑定到一个包含键值对的对象。常用于动态绑定class和style。以及href等。
简写为一个冒号

 <a v-bind:href='herf'>百度</a>

<img :src='img_url' alt='leishen'>

let img_url = ref('https://image-1300284638.cos.ap-nanjing.myqcloud.com/leishen.jpeg')

常用的v-bind标签

  • v-bind:style
  • v-bind:title
  • v-bind:src

v-html
双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML ,你需要使用 v-html 指令:

<div v-html="rawHtml"></div>

这个 div 的内容将会被替换成为属性值 rawHtml,直接作为 HTML——会忽略解析属性值中的数据绑定。

动作监听

动作监听的流程:

  1. 标签上定义监听函数 @click='监听函数名'
  2. setup中实现监听函数
  3. setup中return监听函数
<template>
    <!-- <one></one> -->
    <button @click='alert_action'>点击事件</button>
</template>


<script>
    import {defineComponent, ref, reactive, computed} from 'vue'
    import one from '@/components/one/One'

    export default defineComponent({
        name: 'Main', // 组件名称
        
        components:{
             one
        },
        setup() {
           
           let alert_action = () => {
                alert('你点击了我')
           }

           return {
                alert_action
           }
        }

    })
</script>


<style scoped lang="scss">
    
</style>

vue全局使用

引用组件

子组件可以定义在components中,而views中往往定义父组件。在父组件中使用子组件的流程为:

  1. 子组件定义

<template>
    <div>这是子组件</div>
</template>


<script>
    import {defineComponent, ref, reactive, computed} from 'vue'
    export default defineComponent({
        name: 'One', // 组件名称

        setup() {

        }

    })
</script>


<style scoped lang="scss">
    
</style>
  1. 父组件定义

<template>
    <one></one>
</template>


<script>
    import {defineComponent, ref, reactive, computed} from 'vue'
    
    // 从components中的one文件夹下的One.vue中引入
    import one from '@/components/one/One'

    export default defineComponent({
        name: 'Main', // 组件名称
        
        // 组件本地化
        components:{
             one
        },
        setup() {

        }

    })
</script>


<style scoped lang="scss">
    
</style>

父子组件中传递数据

  1. 父组件传递给子组件

在父组件使用的子组件中加入参数传递:num='num'


<template>
    <one :num='num'></one>
</template>


<script>
    import {defineComponent, ref, reactive, computed} from 'vue'
    import one from '@/components/one/One'

    export default defineComponent({
        name: 'Main', // 组件名称
        
        components:{
             one
        },
        setup() {
           
           let alert_action = () => {
                alert('你点击了我')
           }

           let num = ref(100)

           return {
                alert_action,
                num
           }
        }

    })
</script>


<style scoped lang="scss">
    
</style>

子组件中props用来接收父组件的传参,定义好变量,然后直接使用


<template>
    <div>这是子组件</div>
    <div>父组件传递过来的是: {{ num }}</div>
</template>


<script>
    import {defineComponent, ref, reactive, computed} from 'vue'
    export default defineComponent({
        name: 'One', // 组件名称
        
        props: {
            num:{
                type: Number
            }
        },
        setup(props) {
             
        }

    })
</script>


<style scoped lang="scss">
    
</style>

  1. 子组件传递给父组件

子组件传值给父组件叫事件分发。通过ctx.emit分发事件

  1. 子组件
<template>
    <div>这是子组件</div>
    <div>父组件传递过来的是: {{ num }}</div>
    <button @click='send'>点击传递参数</button>
</template>


<script>
    import {defineComponent, ref, reactive, computed} from 'vue'
    export default defineComponent({
        name: 'One', // 组件名称
        
        props: {
            num:{
                type: Number
            }
        },
        setup(props, ctx) {
            let send = () => {
                 // 使用事件分发
                 ctx.emit("send", 200)   
            }
            return {
                send
            }
        }

    })
</script>


<style scoped lang="scss">
    
</style>

父组件


<template>
    // 父组件接收send事件,将其在send_father函数中处理
    <one :num='num' @send='send_father'></one>
    <div>父组件收到的子组件的传参: {{ recv_value }}</div>
</template>

<script>
    import {defineComponent, ref, reactive, computed} from 'vue'
    import one from '@/components/one/One'

    export default defineComponent({
        name: 'Main', // 组件名称
        
        components:{
             one
        },
        setup() {
           
           let alert_action = () => {
                alert('你点击了我')
           }

           let num = ref(100)
           
           let recv_value = ref(0)
           let send_father = (val) => {
               recv_value.value = val
           }

           return {
                alert_action,
                num,
                send_father,
                recv_value
           }
        }

    })
</script>


<style scoped lang="scss">
    
</style>

全局共享变量之状态管理

在store中的index.js中可以定义全局使用的变量和方法。全局使用指的是所有组件可以修改,共享使用。

使用这些变量或者函数的方法是:

import {useStore} from 'vuex'

setup(props, ctx) {
        
    let  store = useStore()
    //
    store.commit('addTodo',{
        title: value.value,
        complete: false
    }

路由

在router文件夹下存放着vue的路由信息

路由就是页面的静态路由。

根路由:每一个vue项目都有一个根路由,该路由的主要作用是页面的默认路由。

 {
    path: '/',
    name: 'Start',
    component: Start
  },

path: 路由路径
name:路由的名字
component: 该路由对应的组件。该组件必须先引入进来,并且是只需要显示引入的。其他组件由于不需要立刻显示,所以使用懒加载,即不立即加载到vue项目中。

其他路由的加载

{
    path: '/home',
    name: 'Home',
    component: () => import('../views/Home.vue')
  },

路由的使用

import {useRouter} from 'vue-router'
 setup(props, ctx) {
    // router是全局路由对象
    let router = useRouter()
    let start = () =>{
             // 使用push的方式,跳转路由
             router.push({
                // 路由的目的地可以用name:模块
                name:'Home',
                // 也可以是path:路径。两者二选一
                path: '/home'
            })
        }
 }

路由的传参

路由的传参有两种方式,分别是

  1. query 类似于get,显示传参,地址栏可以看到参数,刷新保存参数
  2. params 类似于post,地址栏看不到参数,刷新不保存参数

query

 setup(props, ctx) {
    // router是全局路由对象
    let router = useRouter()
    let start = () =>{
             // 使用push的方式,跳转路由
             router.push({
                name:'Home',
                query:{
                    name: name.value,
                    num: num.value,
                }
                
            })
        }
 }

使用

import {useRouter, useRoute} from 'vue-router'

// route是当前路由对象
let route = useRoute()

console.log(route.query)

有一点需要注意数字类型的参数会变成字符串类型

params
params传参只能用name来路由

let start = () =>{
         router.push({
            name:'Home',
            params:
                {
                 name: name.value,
                 num: num.value,
                }
        })
        }

接收参数:

import {useRouter, useRoute} from 'vue-router'

// route是当前路由对象
let route = useRoute()

console.log(route.params)

插槽

定义
插槽就是子组件中的提供给父组件使用的一个占位符,用 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的标签。

https://www.cnblogs.com/mandy-dyf/p/11528505.html

vue2 和vue3的区别

建立数据 data
这里就是Vue2与Vue3 最大的区别 — Vue2使用选项类型API(Options API)对比Vue3合成型API(Composition API)

选项类型
旧的选项型API在代码里分割了不同的属性(properties):data,computed属性,methods
合成类型
新的合成型API能让我们用方法(function)来分割,相比于旧的API使用属性来分组,这样代码会更加简便和整洁。

vue2

export default {
  props: {
    title: String
  },
  data () {
    return {
      username: '',
      password: ''
    }
  },
  methods: {
    login () {
      // 登陆方法
    }
  }
}

Vue2 的选项型API是把methods分割到独立的属性区域的。我们可以直接在这个属性里面添加方法来处理各种前端逻辑。

vue3

export default {
  props: {
    title: String
  },
  setup () {
    const state = reactive({
      username: '',
      password: ''
    })

    const login = () => {
      // 登陆方法
    }
    return { 
      login,
      state
    }
  }
}

Vue3 的合成型API里面的setup()方法也是可以用来操控methods的。创建声名方法其实和声名数据状态是一样的。— 我们需要先声名一个方法然后在setup()方法中返回(return), 这样我们的组件内就可以调用这个方法了。

项目代码结构

所有的vue代码都写在views当中
公共组件存放在components中
有关网络请求的axios都存放在network中
页面跳转路由存放在router中

vue在实际项目中的使用技巧

vue与后端交互

vue通过 axios 与后端交互。通过引入axios中的各种方法,完成网络请求

import { fetch, post, del, postForm } from '../base/axios'

const URL = {
  listUrl: '/page/list/',
  createUrl: '/page/create/',
  delUrl: '/page/delete/',
  disableUrl: '/page/disable/',
  enableUrl: '/page/enable/',
  pageStateChange: '/page/page_state_change/',
  getFiles: '/page/get_files/'
}

export function pageList (data) {
  return fetch(URL.listUrl, data)
}

export function pageCreate(form) {
    return postForm(URL.createUrl, form)
}

export function pageDelete(page_id) {
    return del(URL.delUrl + page_id + '/')
}

export function pageDisable(data) {
    return fetch(URL.disableUrl, data)
}

export function pageEnable(data) {
  return fetch(URL.enableUrl, data)
}

export function pageStateChange(data) {
  return fetch(URL.pageStateChange, data)
}

export function pageGetFiles(page_id) {
    return fetch(URL.getFiles + page_id + '/')
}

普通post请求:

export function post (url, data = {}) {
  return new Promise((resolve, reject) => {
  // var qs = require('querystring')
    axios.create({
      headers: {'X-CSRFToken': getCookie('csrftoken'), 'Content-Type': 'application/x-www-form-urlencoded'},
    }).post(url, data).then(response => {
      resolve(response.data)
    }, err => {
      reject(err)
    })
  })
}

form-data的请求

export function postForm (url, data= {}) {
  return new Promise((resolve, reject) => {
    axios.create({
      withCredentials: true,
      headers: {'X-CSRFToken': getCookie('csrftoken'), 'Content-Type':  "multipart/form-data"},
    }).post(url, data).then(response => {
      resolve(response.data)
    }, err => {
      reject(err)
    })
  })
}

在vue文件中的网络请求为:

import { pageList, pageDelete, pageDisable, pageEnable, pageCreate, pageStateChange, pageGetFiles } from 'api/page/index'

pageList(data).then((res =>{
            this.tableConfig.tableData = res.data;
            this.pager.total = res.total
        })).catch(err => {
          this.$alert(`${ err }`, '提示', {
            confirmButtonText: '确定',
          });
      });

vue 导入组件和方法

vue使用的过程中需要导入组件或者方法,方法如axios请求。导入的语法是:

  • 导入组件需要使用大括号
  • 导入方法需要用大括号包裹
 import { useRouter } from 'vue-router'
 import { tableConfigBase } from 'utils/common.js'
 import { pageList, pageDelete, pageDisable, pageEnable, pageCreate, pageStateChange, pageGetFiles } from 'api/page/index'
 import {  showConfirmMessageBox, showMessage } from 'api/base/message'
 import UploadFile from 'components/common/UploadFile'
 import Pagination  from 'components/common/Pagination'

导入组件是从别的文件中导入组件,除需要使用大括号之外,还需要本地引入

 export default {
    components: {
      UploadFile,
      Pagination
    },
    .....
}

导入方法指的是从js文件中能够导入一个函数。如 showConfirmMessageBox,就是:

export function showConfirmMessageBox (message) {
  return ElMessageBox.confirm(message, '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
    center: true
  })
}

vue属于js的一个库,理所当然可以使用js。想要引用一个js,需要js的函数export

vue异步变同步的方法

axios是异步请求,如果想要将异步变成同步,使用asyncawait两个关键字即可。
async 修饰 vue函数
await 修饰 axios请求方法

 async editRow(index, row){
        this.createForm.name = row.name
        this.createForm.desc = row.desc
        this.createForm.page_url = row.page_url
        this.createForm.edit = true
        this.createForm.page_id = row.id
        await pageGetFiles(row.id).then((res => {
          if (res.result == 0) {
            for (var i = 0; i < res.page_files.length; i++) {
              this.createForm.file.push({'page_file_id': res.page_files[i].id, 'name': res.page_files[i].name})
            }
          }
        }))
        this.createModal.visible = true
      },

vue中formdata的使用

formdata 用于有静态资源从vue传输到django中,如图片和文件等。使用如下:
创建: var data = new FormData()
添加:

    data.append('name', this.createForm.name)
    data.append('desc', this.createForm.desc)
    data.append('page_url', this.createForm.page_url)
    data.append('edit', this.createForm.edit)
    data.append('page_id', this.createForm.page_id)

特别注意,如果添加文件也是使用中格式
data.append('new_files', file.raw)
如果添加多个文件,那么直接用同一个key,会被打包成列表
取值:data.get(key)
如果value是一个数组,取值方法: data.getAll(key)

vue代码

 var data = new FormData();
data.append('name', this.createForm.name)
data.append('desc', this.createForm.desc)
data.append('page_url', this.createForm.page_url)
data.append('edit', this.createForm.edit)
data.append('page_id', this.createForm.page_id)
this.createForm.file.forEach((file) => {
  if (file.raw) {
    data.append('new_files', file.raw)
  }else{
    data.append('old_files', file.page_file_id)
  }
})
export function postForm (url, data= {}) {
  return new Promise((resolve, reject) => {
    axios.create({
      withCredentials: true,
      headers: {'X-CSRFToken': getCookie('csrftoken'), 'Content-Type':  "multipart/form-data"},
    }).post(url, data).then(response => {
      resolve(response.data)
    }, err => {
      reject(err)
    })
  })
}
export function pageCreate(form) {
    return postForm(URL.createUrl, form)
}
pageCreate(data)

django的接收:

# 接收到formdata的出文件之外的数据
data = request.POST
# 接收文件,getlist是接收多个文件  get是接收单个文件
new_files = request.FILES.getlist('new_files')

vue校验

在input输入框中需要一些校验,以下面的demo为例

 <el-dialog title="添加页面" v-model="createModal.visible" width="800px" :before-close="closeDialog">
      <div class="demo-dialog">
        <el-form :model="createForm" :rules="createRules" ref="createForm" label-width="100px">
          <el-form-item label="名称" prop="name">
            <el-input v-model="createForm.name"></el-input>
          </el-form-item>
          <el-form-item label="描述" prop="desc">
            <el-input v-model="createForm.desc"></el-input>
          </el-form-item>
          <el-form-item label="网址" prop="page_url">
            <el-col>
              <el-input v-model="createForm.page_url" >
                 <template #prepend>page/</template>
              </el-input>
            </el-col>
          </el-form-item>
          <el-form-item label="页面文件" prop="file">
            <upload-file :allowed-type="['html']"
                         v-model:file-list="createForm.file"
                         :multiple="true">支持上传单个或多个html文件
            </upload-file>
          </el-form-item>
        </el-form>
      </div>
      <template #footer>
          <span class="dialog-footer">
            <el-button @click="submitCancel">取 消</el-button>
            <el-button type="primary" @click="submitForm('createForm')">确 定</el-button>
          </span>
      </template>
    </el-dialog>

校验规则

createRules: {
  position: [
    { required: true, message: '请选择位置', trigger: 'change' },
  ],
  name: [
    { required: true, message: '请输入认证名称', trigger: 'change' },
    { min: 2, max: 50, message: '长度在 2~50 个字符内', trigger: 'change' },
  ],
  desc: [
    { required: false, max: 200, message: '长度在 200 个字符内', trigger: 'change' },
  ],
  page_url: [
    { required: true, message: '请填写链接', trigger: 'change' },
    { min: 1, max: 50, message: '长度在 1~50 个字符内', trigger: 'change' },
     {validator: urlAcq, trigger: 'change'}
  ],
  file: [
    { required: true, message: '请上传html文件', trigger: 'change' },
    {validator: indexHtmlAcq, trigger: 'change'}
  ]
},

自定义校验 上传文件包含index.html

const indexHtmlAcq = (rule, files, callback) => {
        let index_html_num = 0
        files.forEach((file) =>{
            if(file.name == 'index.html'){
                 index_html_num = index_html_num + 1
            }
        })
        if(index_html_num == 0){
            callback(new Error('必须添加一个index.html文件'))
        }else if(index_html_num > 1){
             callback(new Error('只能添加一个index.html文件'))
        }
        return callback()
      }

自定义校验 输入框中只允许输入数字字母-_

      const urlAcq = (rule, str, callback) =>{
        const reg =/^[-_a-zA-Z0-9]+$/;
        if(!reg.test(str)){
            callback(new Error('url中包含特殊字符'))
        }
        return callback()
      }

清空校验的红色提示

this.$nextTick(() => {
          this.$refs["createForm"].clearValidate()
        })
原文地址:https://www.cnblogs.com/goldsunshine/p/14892580.html