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>
  • 相关阅读:
    【题解】 bzoj1191: [HNOI2006]超级英雄Hero (二分图)
    谈谈Android项目框架的前世今生
    十四个好用的开源漏洞检测工具
    关于Java导出100万行数据到Excel的优化方案
    逗号分割符--字段中含逗号等情况的解析方法Java实现
    Java日期处理
    服务器&浏览器伪装的故事
    浏览器User-agent简史(user-agent)
    修改tomcat服务器banner的方法
    life_motto
  • 原文地址:https://www.cnblogs.com/huidou/p/13612650.html
Copyright © 2011-2022 走看看