Vue-Cli3 脚手架

Vue-Cli3 官网

https://cli.vuejs.org/zh/

 

vue-cli3 开发单文件组件

# js
Vue.component({

})
new Vue({

})

 

### 缺点

  •  全局定义组件的名字时 不能重复
  •  字符串模板: es6提供模板字符串
  •  不支持 CSS
  •  没有构建步骤 Pug 、 Babel .vue


在Vue 中把 .vue 的文件成为,单文件组件,webpack等构建工具

单文件组件,可以获得:

  1.  完整语法高亮
  2.  common JS模块
  3.  组件作用域的CSS

 

Vue CLI3 脚手架

 基本配置

  •  安装Nodejs
  •  https://nodejs.org/en/download
  •  保证Node.js8.9 或者更高版本
  •  终端中输入 `node -v ` , 保证已安装成功

 

 安装淘宝镜像

https://npm.taobao.org/
npm install -g cnpm --registry=https://registry.npm.taobao.org
// 以后的npm 可以用cnpm代替

 安装Vue Cli3 脚手架

 cnpm install -g @vue/cli

检查其他版本是否正确

vue --version

 

 


快速原型开发


使用 ` vue server ` 和 `vue build` 命令对单个 ` *.vue` 文件进行快速原型开发
不过这需要先额外安装一个全局的扩展:

cnpm install -g @vue/cli-service-global  // -g 全局

vue serve  // 的缺点就是它需要安装全局依赖

 

这使得它在不同机器上的一致性不能得到保证
因此这只适合于快速原型开发

需要的仅仅是一个 ` App.vue` 文件:

### vue ###
<template> <h3>{{msg}}</h3> </template> <script> export default { data(){ return{ msg:"我是你爸爸" }; }, } </script> <style scoped> h3{ color: red; } </style>

# scoped 表示注入的意思, 只对当前的h3 标签起作用

简单3步启动并访问

  1.  npm init
  2.  vue serve
  3.  访问 http://localhost:8080/

 

 

 

vue-cli3生成项目


vue-cli3官网 : https://cli.vuejs.org/zh/

在控制台创建 vue-cli3 项目

vue create <projectname>

1. vue create <projectname>
2. cd <projectname>
3. npm run serve

 

 

目录介绍

  • node_modules        :  包存储路径
  • dependencies         :  项目依赖
  • devDependencies   :  开发依赖
  • public                      :  静态加载文件目录
  • src                           :  一般开发目录
  • assets                     :  当前项目的依赖
  • components            :  注入组件们
  • main.js                    :  入口文件
  • App.vue                  :  app组件

 

 

 

 

购物车项目搭建

 

App.vue

<template>
  <div id="app">
    <h1>{{alltitle}}</h1>
    <ul>
      <li v-for="itme in cartList" :key="itme.id">
        <h2>{{itme.title}}</h2>
        <p>¥ {{itme.price}}</p>
      </li>
    </ul>
    <mycart :cart="cartList" :alltitle="alltitle"></mycart>
  </div>
</template>

<script>
import mycart from './components/Cart'

export default {
  name: 'app',
  data(){
    return{
      cartList:[
        {id:1, title:'秘籍1', price: 999, action:true, count:1},
        {id:2, title:'秘籍2', price: 1999, action:true, count:2},
        {id:3, title:'秘籍3', price: 2999, action:true, count:3},
      ],
      alltitle: "购物车",
    }
  },
  components: {
    mycart
  }
}
</script>

 

./components/cart.vue
<template>
    <div>
        <h2>{{alltitle}}</h2>
        <table border="1">
            <tr>
                <th>#</th>
                <th>课程</th>
                <th>单价</th>
                <th>数量</th>
                <th>总价</th>
            </tr>
            <tr v-for="c in cart" :key="c.id" >
                <td><input type="checkbox" v-model="c.action"></td>
                <td>{{c.title}}</td>
                <td>¥{{c.price}}</td>
                <td>
                    <button> - </button>
                    {{c.count}}
                    <button> + </button>
                </td>
                <td>¥{{c.price * c.count}}</td>
            </tr>
        </table>
    </div>
</template>

<script>
    export default {
        name:'cart',
        props:['alltitle','cart']
    }
</script>

 

 

购物车项目操作

app.vue

<template>
  <div id="app">
    <h1>{{alltitle}}</h1>
    <ul>
      <li v-for="itme in cartList" :key="itme.id">
        <h2>{{itme.title}}</h2>
        <p>¥ {{itme.price}}</p>
      </li>
    </ul>
    <mycart :cart="cartList" :alltitle="alltitle"></mycart>
  </div>
</template>

<script>
//  导入文件
import mycart from './components/Cart'
export default {
  name: 'app',
  data(){
    return{
      cartList:[
        {id:1, title:'秘籍1', price: 999, active:true, count:1},
        {id:2, title:'秘籍2', price: 1999, active:true, count:2},
        {id:3, title:'秘籍3', price: 2999, active:true, count:3},
      ],
      alltitle: "购物车",
    }
  },
  components: {
    mycart
  }
}
</script>

 

 

cart.vue

<template>
    <div>
        <h2>{{alltitle}}</h2>
        <table border="1">
            <tr>
                <th>#</th>
                <th>课程</th>
                <th>单价</th>
                <th>数量</th>
                <th>总价</th>
            </tr>
            <tr v-for="(c, index) in cart" :key="c.id" >
                <td><input type="checkbox" v-model="c.active"></td>
                <td>{{c.title}}</td>
                <td>¥{{c.price}}</td>
                <td>
                    <button @click="sub(index)"> - </button>
                       {{c.count}}
                    <button  @click="add(index)"> + </button>
                </td>
                <td>¥{{c.price * c.count}}</td>
            </tr>
            <tr>
                <td></td>
                <!--   colspan 合并   -->
                <td colspan="2">{{activeCount}} / {{count}}</td>
                <td colspan="2">¥ {{total}}</td>
            </tr>
        </table>
    </div>
</template>

<script>
    export default {
        name:'cart',
        props:['alltitle','cart'],
        methods:{
            remove(i){
                if (window.confirm('是否确定删除')){
                    //  这个数组中 删除  那个索引的 1条数据
                    this.cart.splice(i,1);
                }
            },
            sub(i){
                // 取到当前的数量
                let count = this.cart[i].count;
                //  如果大于1 ,'?' 相当于then,则  则 -1,  ':' = 否则 删除那一条数据
                count > 1 ? this.cart[i].count -=1 : this.remove(i);
            },
            add(i){
                // 取到当前的一条数据  +1
                this.cart[i].count ++
            },
        },
        computed:{
            count(){
            //  cart的总数
                return this.cart.length
            },
            activeCount(){
              // 过滤参数 把active 是false 过滤掉
                // 返回 v.active 为 true的对象
              return this.cart.filter(v=>v.active).length
            },
            total(){
                // let num = 0;
                // this.cart.forEach(c=>{
                //     if(c.active){
                //         num += c.price * c.count;
                //     }
                // });
                // return num

                // reduce 回调函数, 第一个参数是起始参数就是后面定义的0,第二个参数是数组遍历的对象
                return this.cart.reduce((num,c)=>{
                    if (c.active){
                        num += c.price * c.count;
                    }
                    return num
                },0)
            }
        },
    }
</script>

 

 

 

Mock模拟数据

发起请求
安装

cnpm i axios -S     # -S 保存 

 

去入口文件 导入 axios对象 ,然后挂载到Vue 的原型上  

import axios from 'axios'
Vue.prototype.$http = axios;

 

可以在每个实例里   this.$http   拿到axios 对象

created(){
    this.$http.get('/api/cartList')
}

 

 

 

 

做数据持久化

入口文件 main.js

// 使用中央数据总线 创建一个bus,传递数据使用
Vue.prototype.$bus = new Vue;

 

App.vue

<template>
  <div id="app">
    <h1>{{alltitle}}</h1>
    <ul>
      <li v-for="(itme, index) in cartList" :key="itme.id">
        <h2>{{itme.title}}</h2>
        <p>¥ {{itme.price}}</p>
        <button @click="addCart(index)">添加商品</button>
      </li>
    </ul>
    <mycart :cart="cartList" :alltitle="alltitle"></mycart>
  </div>
</template>

<script>
import mycart from './components/Cart'

export default {
  name: 'app',
  data(){
    return{
      cartList:[],
      // cartList:[
      //   {id:1, title:'秘籍1', price: 999, active:true, count:1},
      //   {id:2, title:'秘籍2', price: 1999, active:true, count:2},
      //   {id:3, title:'秘籍3', price: 2999, active:true, count:3},
      // ],
      alltitle: "购物车",
    }
  },
  methods:{
    addCart(i){
      const good = this.cartList[i];
      // 使用中央数据总线 传递数据到 cart
      this.$bus.$emit('addCart',good)
    }
  },
  // created(){
  //   this.$http.get('/api/cartList')
  //   .then(res=>{
  //     this.cartList = res.data.result;
  //   }).catch(err=>{
  //     console.log(err);
  //   })
  // },
  async created(){
    try{
      const res = await this.$http.get('/api/cartList')
      this.cartList = res.data.result
    } catch (err) {
      console.log(err)
    }
  },
  components: {
    mycart
  },
}
</script>

 

 

cart.vue

<template>
    <div>
        <h2>{{alltitle}}</h2>
        <table border="1">
            <tr>
                <th>#</th>
                <th>课程</th>
                <th>单价</th>
                <th>数量</th>
                <th>总价</th>
            </tr>
            <tr v-for="(c, index) in cart" :key="c.id" >
                <td><input type="checkbox" v-model="c.active"></td>
                <td>{{c.title}}</td>
                <td>¥{{c.price}}</td>
                <td>
                    <button @click="sub(index)"> - </button>
                    {{c.count}}
                    <button  @click="add(index)"> + </button>
                </td>
                <td>¥{{c.price * c.count}}</td>
            </tr>
            <tr>
                <td></td>
                <!--   colspan 合并   -->
                <td colspan="2">{{activeCount}} / {{count}}</td>
                <td colspan="2">¥ {{total}}</td>
            </tr>
        </table>

    </div>
</template>

<script>
    export default {
        name:'cart',
        props:['alltitle',],
        data(){
          return{
              // 初始一个空数组,存放添加或者删除的数据
              // 刷新网页时 获取里面的数据,如果没有数据就是一个空数组
              cart:JSON.parse(localStorage.getItem('cart')) || [],
          }
        },
        watch:{
            // 深度监听deep:true  cart 数据
          cart:{
            handler(n){
                this.setLocalData(n);
            },
              deep:true
          }
        },
        created() {
            // 从中央数据总线里把数据取出来,
            this.$bus.$on('addCart',good=>{
                //  find查找那个 商品对应的ID
                const ret = this.cart.find(v=>v.id===good.id);
                // 如果购物车 没有数据 商品那一条数据, 则会添加进 那个列表里
                if (!ret){
                    this.cart.push(good);
                }else{
                    // 如果有 则会自加1
                    ret.count ++
                }
            })
        },
        methods:{
            setLocalData(n){
                // 可以计算总数量
                localStorage.setItem('cart',JSON.stringify(n));
            },
            remove(i){
                if (window.confirm('是否确定删除')){
                    //  这个数组中 删除  那个索引的 1条数据
                    this.cart.splice(i,1);
                }
            },
            sub(i){
                // 取到当前的数量
                let count = this.cart[i].count;
                //  如果大于1 ,'?' 相当于then,则  则 -1,  ':' = 否则 删除那一条数据
                count > 1 ? this.cart[i].count -=1 : this.remove(i);
            },
            add(i){
                // 取到当前的一条数据  +1
                this.cart[i].count ++
            },
        },
        computed:{
            count(){
            //  cart的总数
                return this.cart.length
            },
            activeCount(){
              // 过滤参数 把active 是false 过滤掉
                // 返回 v.active 为 true的对象
              return this.cart.filter(v=>v.active).length
            },
            total(){
                // let num = 0;
                // this.cart.forEach(c=>{
                //     if(c.active){
                //         num += c.price * c.count;
                //     }
                // });
                // return num
// reduce 回调函数, 第一个参数是起始参数就是后面定义的0,第二个参数是数组遍历的对象 return this.cart.reduce((num,c)=>{ if (c.active){ num += c.price * c.count; } return num },0) } }, } </script>

 

 

 


第三方组件(element-ui)

1.  通用组件
      -  基础组件,大部分UI都是这种组件,比如表单,布局,弹窗等

2.  业务组件
      -  与需求挂钩,会被复用,比如抽奖,摇一摇等

3.  页面组件
     -  每个页面都是一个组件,不会复用


使用组件
安装 element-ui 插件库

npm install element-ui -S   # -S 保存

 

修改main.js

import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css'
import App from './App.vue';

Vue.use(ElementUI);

new Vue({
  el: '#app',
  render: h => h(App)
});

 

按需引入

借助 babel-plugin-component,我们可以只引入需要的组件,以达到减小项目体积的目的。

首先,安装 babel-plugin-component:

npm install babel-plugin-component -D

然后,将 .babelrc 修改为:

{
  "presets": [["es2015", { "modules": false }]],
  "plugins": [
    [
      "component",
      {
        "libraryName": "element-ui",
        "styleLibraryName": "theme-chalk"
      }
    ]
  ]
}

 

 

vue-cli 中可以使用 vue add element 安装

 vue add element 

选择按需导入

import on demand


安装之前注意提前提交当前工作内容, 脚手架会覆盖若干文件

发现项目发生了变化,打开App.vue , ctrl+z 撤回

 

饿了么UI 官网
https://element.eleme.cn/#/zh-CN/component/quickstart

 

 

main.js

import Vue from 'vue'
import App from './App.vue'
import axios from 'axios'
// 加入UI
import './plugins/element.js'
// 提示警告信息
Vue.config.productionTip = false

Vue.prototype.$http = axios;
// 使用中央数据总线 创建一个bus,传递数据使用
Vue.prototype.$bus = new Vue;

new Vue({
  render: h => h(App),
}).$mount('#app')

 


element.js

import Vue from 'vue'
import { Button, Table ,TableColumn,InputNumber } from 'element-ui'

Vue.use(Button)
Vue.use(Table)
Vue.use(TableColumn)
Vue.use(InputNumber)

 

 

cart.vue

<template>
    <div>
        <h2>{{alltitle}}</h2>
        <template>
            <el-table
                ref="multipleTable"
                :data="cart"
                border
                tooltip-effect="dark"
                style="width: 100%"
                @selection-change="handleSelectionChange">
                <el-table-column type="selection" width="55"></el-table-column>
                <el-table-column prop="title" label="课程" width="120"></el-table-column>
                <el-table-column prop="price" label="单价" width="120"></el-table-column>
                <el-table-column label="数量" width="200">
                    <template slot-scope="scope">
                        <el-input-number v-model="scope.row.count" :min="0" :max="100" ></el-input-number>
                    </template>
                </el-table-column>
                <el-table-column label="总价" width="120">
                    <template slot-scope="scope">
                        ¥ {{scope.row.price * scope.row.count}}
                    </template>
                </el-table-column>
            </el-table>
            <div style="margin-top: 20px">
                <el-button @click="toggleSelection()">取消选择</el-button>
            </div>
        </template>

        <table border="1">
            <tr>
                <th>#</th>
                <th>课程</th>
                <th>单价</th>
                <th>数量</th>
                <th>总价</th>
            </tr>
            <tr v-for="(c, index) in cart" :key="c.id" >
                <td><input type="checkbox" v-model="c.active"></td>
                <td>{{c.title}}</td>
                <td>¥{{c.price}}</td>
                <td>
                    <button @click="sub(index)"> - </button>
                    {{c.count}}
                    <button  @click="add(index)"> + </button>
                </td>
                <td>¥{{c.price * c.count}}</td>
            </tr>
            <tr>
                <td></td>
                <!--   colspan 合并   -->
                <td colspan="2">{{activeCount}} / {{count}}</td>
                <td colspan="2">¥ {{total}}</td>
            </tr>
        </table>
    </div>
</template>

<script>
    export default {
        name:'cart',
        props:['alltitle',],
        data(){
          return{
              // 初始一个空数组,存放添加或者删除的数据
              // 刷新网页时 获取里面的数据,如果没有数据就是一个空数组
              cart:JSON.parse(localStorage.getItem('cart')) || [],
              multipleSelection: []
          }
        },
        watch:{
            // 深度监听deep:true  cart 数据
          cart:{
            handler(n){
                this.setLocalData(n);
            },
              deep:true
          }
        },
        created() {
            // 从中央数据总线里把数据取出来,
            this.$bus.$on('addCart',good=>{
                //  find查找那个 商品对应的ID
                const ret = this.cart.find(v=>v.id===good.id);
                // 如果购物车 没有数据 商品那一条数据, 则会添加进 那个列表里
                if (!ret){
                    this.cart.push(good);
                }else{
                    // 如果有 则会自加1
                    ret.count ++
                }
            })
        },
        methods:{
            // element UI
            toggleSelection(rows) {
                if (rows) {
                    rows.forEach(row => {
                        this.$refs.multipleTable.toggleRowSelection(row);
                    });
                } else {
                    this.$refs.multipleTable.clearSelection();
                }
            },
            handleSelectionChange(val) {
                this.multipleSelection = val;
            },

            setLocalData(n){
                // 可以计算总数量
                localStorage.setItem('cart',JSON.stringify(n));
            },
            remove(i){
                if (window.confirm('是否确定删除')){
                    //  这个数组中 删除  那个索引的 1条数据
                    this.cart.splice(i,1);
                }
            },
            sub(i){
                // 取到当前的数量
                let count = this.cart[i].count;
                //  如果大于1 ,'?' 相当于then,则  则 -1,  ':' = 否则 删除那一条数据
                count > 1 ? this.cart[i].count -=1 : this.remove(i);
            },
            add(i){
                // 取到当前的一条数据  +1
                this.cart[i].count ++
            },
        },
        computed:{
            count(){
            //  cart的总数
                return this.cart.length
            },
            activeCount(){
              // 过滤参数 把active 是false 过滤掉
                // 返回 v.active 为 true的对象
                return this.multipleSelection.length;
                // return this.multipleSelection.filter( v => v.active ).length;
            },
            total(){
                // let num = 0;
                // this.cart.forEach(c=>{
                //     if(c.active){
                //         num += c.price * c.count;
                //     }
                // });
                // return num

                // reduce 回调函数, 第一个参数是起始参数就是后面定义的0,第二个参数是数组遍历的对象
                return this.cart.reduce((num,c)=>{
                    if (c.active){
                        num += c.price * c.count;
                    }
                    return num
                },0)
            }
        },
    }
</script>

 

 

 

 

 

Element的表单组件分析

自定义校验 callback 必须被调用。 更多高级用法可参考 async-validator。

element.js

import Vue from 'vue'
import { Button, Table ,TableColumn,InputNumber,Form,FormItem,Input } from 'element-ui'

Vue.use(Button)
Vue.use(Table)
Vue.use(TableColumn)
Vue.use(InputNumber)
Vue.use(Form)
Vue.use(FormItem)
Vue.use(Input)

 

App.vue

<template>
  <div id="app">
    <FormItem></FormItem>
  </div>
</template>

<script>
  // @ 相当于src 目录下
  import FormItem from '@/components/FormItem.vue';

    components: {
      FormItem
    },
  }
</script>

 

FormItem.vue

<template>
    <div>
        <h3>element 表单</h3>
        <el-form
            :model="ruleForm"
            status-icon
            :rules="rules"
            ref="ruleForm"
            label-width="100px"
            class="demo-ruleForm">
            <el-form-item label="用户名" prop="name">
                <el-input type="text" v-model="ruleForm.name" ></el-input>
            </el-form-item>
            <el-form-item label="密码" prop="pwd">
                <el-input type="password" v-model="ruleForm.pwd" ></el-input>
            </el-form-item>
            <el-form-item>
                <el-button type="primary" @click="submitForm('ruleForm')">提交</el-button>
            </el-form-item>
        </el-form>
    </div>
</template>

<script>
    // 自定义校验 callback 必须被调用。 更多高级用法可参考 async-validator
    // Form 定义数据 负责定义校验规则
    // FormItem 负责显示错误信息
    // Input 负责双向数据绑定

    // provide inject 内部共享数据
    export default {
        data() {
            return {
                ruleForm: {
                    name: 'huige',
                    pwd: '123',
                },
                rules: {
                    name: [
                        { required: true, message: '请输入名字' },
                        { mix:6,max:10, message: '请输入6~10位用户名' },
                    ],
                    pwd: [
                        { required: true, message: '请输入密码' }
                    ]
                }
            };
        },
        methods: {
            //自定义校验 callback 必须被调用。 更多高级用法可参考 async-validator。
            submitForm(name) {
                this.$refs[name].validate((valid) => {
                    if (valid) {
                        alert('验证成功,可以提交!');
                    } else {
                        console.log('验证失败,不能提交!!');
                        return false;
                    }
                });
            },
            resetForm(name) {
                this.$refs[name].resetFields();
            }
        }
    }
</script>

 

 

 

 

 

表单组件设计-Input实现双向数据绑定

Input.vue

<template>
    <div>
        <!--  实现 v-model 是 v-bind:value 绑定值 ,v-on:input 绑定事件    -->
        <input :type="type" :value="inputVal" @input="handleInput" >
    </div>
</template>

<script>
    export default {
        props:{
            type:{
                type: String,
                default: 'text',
            },
            value:{
                type:String,
                default:"",
            }
        },
        data(){
            return {
                inputVal: this.value
            }
        },
        methods:{
            handleInput(e){
                //  赋值, 实现双向数据绑定
                this.inputVal = e.target.value;
                this.$emit('input',this.inputVal)
                // 通知父组件值的更新
            }
        }
    }
</script>

 

FormElemtent.vue

<template>
    <div>
        {{ruleForm}}
        <m-input v-model="ruleForm.name" ></m-input>
        <m-input type='password' v-model="ruleForm.pwd" ></m-input>
    </div>
</template>

<script>
    import MInput from './Input'
    export default {
        components : {
            MInput
        },
     }
</script>

 

 

 

 

表单组件-设计FormItem组件

0. label 和 prop 实行

1. 获取当前输入框的规则

2. 如果输入框和rule不匹配 ,显示错误信息

3. Input 组件中涌入输入内容时,通知FormItem做校验(校验方法)

4. 使用async-validator 做校验

 

Form.vue

<template>
    <div>
        <slot></slot>
    </div>
</template>

<script>
    // 1. 申明 props 获取数据模型(model) 和校验规则对象
    export default {
        // provide: {}
        provide(){
          return{
              form: this
          }
        },
        props:{
            //  对象数据
            model:{
                type:Object,
                required:true,
            },
            rules:{
                type: Object
            }
        },
        methods:{
            validate(callback){
                // 获取所有的验证结果 统一处理,只要有一个失败就失败

                // tasks保存着验证之后的多个promise对象
                const tasks = this.fileds.map(item=>item.validate())
                let ret = true;
                Promise.all(tasks).then(results=>{
                    results.forEach(valid=>{
                        if(!valid){
                            ret = false
                        }
                    })
                })
                callback(ret)
            }
        },
        created() {
            // 缓存需要校验的表单项
            this.fileds = [];
            this.$on('formItemAdd', item=>{
                this.fileds.push(item);
            })
        },
    }
</script>

 

FormItem.vue

<template>
    <div>
        <label v-if="label">{{label}} </label>
        <!--  槽作用      -->
        <slot> </slot>
        <!--   显示错误信息  -->
        <p v-if='validateState==="error"' class="error" >{{errorMessage}}</p>
    </div>
</template>

<script>
    import schema from 'async-validator'
    export default {
    // 0. label 和 prop 实行
    // 1. 获取当前输入框的规则
    // 2. 如果输入框和rule不匹配 ,显示错误信息
    // 3. Input 组件中涌入输入内容时,通知FormItem做校验(校验方法)
    // 4. 使用async-validator 做校验
    // 需要安装  npm i async-validator -S
        data(){
            return{
                validateState:'', // 显示校验值
                errorMessage:'',  // 显示错误信息
            }
        },
        // 通过provide可以获取到全局的组件对象
        inject:['form'], // 这个form 就是 Form.vue 里的 this
        mounted() {
            if (this.prop){
                // 必须判断,form组件的子组件可能不是formitem
                this.$parent.$emit('formItemAdd',this)
            }
        },
        methods:{
            validate(value){
                return new Promise(resolve => {
                    // console.log(value); // 输入框的值
                    //  这个key 在es6里面 可以是一个动态的数组
                    const descriptor = {[this.prop] : this.form.rules[this.prop]}; //此对象要存储校验规则
                    // 获取检验对象 -> Form组件对象 -> rules[this.prop]
                    // console.log(this.form.rules[this.prop])
                    const validate =  new schema(descriptor);
                    //   这个key 在es6里面 可以是一个动态的数组
                    validate.validate({[this.prop]: value},errors=>{
                        if (errors){
                            // 显示错误
                            this.validateState= "error";
                            this.errorMessage = errors[0].message;
                            resolve(false)
                        }else {
                            // 错误置空
                            this.validateState= "";
                            this.errorMessage ="";
                            resolve(true)
                        }
                    })
                })
            }
        },
        created(){
            // 创建一个监听事件,监听 validate 函数
            this.$on('validate',this.validate);
        },
        props:{
            label: {
                type:String,
                default: "",
            },
            prop:{
                // name 或者 pwd的规则
                type: String,
                default: "",
            }
        }
    }
</script>

<style scoped>
    .error{
        color: red;
    }
</style>

 

FormElement.vue

<template>
    <div>
        <h3>element 表单</h3>
        {{ruleForm}}
        <m-form :model="ruleForm" :rules="rules">
            <m-form-item label="用户名" prop="name">
                <m-input v-model="ruleForm.name" ></m-input>
            </m-form-item>
            <m-form-item label="密码" prop="pwd">
                <m-input type='password' v-model="ruleForm.pwd" ></m-input>
            </m-form-item>
            <m-form-item>
                <el-button type="primary" @click="submitForm2('ruleForm')">提交</el-button>
            </m-form-item>
        </m-form>

        <el-form
            :model="ruleForm"
            status-icon
            :rules="rules"
            ref="ruleForm"
            label-width="100px"
            class="demo-ruleForm">
            <el-form-item label="用户名" prop="name">
                <el-input type="text" v-model="ruleForm.name" ></el-input>
            </el-form-item>
            <el-form-item label="密码" prop="pwd">
                <el-input type="password" v-model="ruleForm.pwd" ></el-input>
            </el-form-item>
            <el-form-item>
                <el-button type="primary" @click="submitForm('ruleForm')">提交</el-button>
            </el-form-item>
        </el-form>
    </div>
</template>

<script>
    // 自定义校验 callback 必须被调用。 更多高级用法可参考 async-validator
    // Form 定义数据 负责定义校验规则
    // FormItem 负责显示错误信息
    // Input 负责双向数据绑定

    // provide inject 内部共享数据
    import MInput from './Input'
    import MFormItem from './FormItem'
    import MForm from './Form'
    export default {
        components : {
            MInput,
            MFormItem,
            MForm
        },
        data() {
            return {
                ruleForm: {
                    name: 'huige',
                    pwd: '123',
                },
                rules: {
                    name: [
                        { required: true, message: '请输入名字' },
                        { min:6,max:10, message: '请输入6~10位用户名' },
                    ],
                    pwd: [
                        { required: true, message: '请输入密码' }
                    ]
                }
            };
        },
        methods: {
            //自定义校验 callback 必须被调用。 更多高级用法可参考 async-validator。
            submitForm(name) {
                this.$refs[name].validate((valid) => {
                    if (valid) {
                        alert('验证成功,可以提交!');
                    } else {
                        alert('验证失败,不能提交!!');
                        return false;
                    }
                });
            },
            // 自己写的校验事件
            submitForm2(name) {
                this.$refs[name].validate((valid) => {
                    if (valid) {
                        alert('验证成功,可以提交!');
                    } else {
                        alert('验证失败,不能提交!!');
                        return false;
                    }
                });
            },
            resetForm(name) {
                this.$refs[name].resetFields();
            }
        }
    }
</script>

 

posted @ 2020-09-04 11:10  H·c  阅读(676)  评论(0编辑  收藏  举报