zoukankan      html  css  js  c++  java
  • 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=" 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>
  • 相关阅读:
    POJ 1003 解题报告
    POJ 1004 解题报告
    POJ-1002 解题报告
    vi--文本编辑常用快捷键之光标移动
    常用图表工具
    September 05th 2017 Week 36th Tuesday
    September 04th 2017 Week 36th Monday
    September 03rd 2017 Week 36th Sunday
    September 02nd 2017 Week 35th Saturday
    September 01st 2017 Week 35th Friday
  • 原文地址:https://www.cnblogs.com/huidou/p/13612650.html
Copyright © 2011-2022 走看看