快速原型开发工具

https://cli.vuejs.org/zh/guide/installation.html

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

npm install -g @vue/cli-service-global

vue serve 的缺点就是它需要安装全局依赖,这使得它在不同机器上的一致性不能得到保证。因此这只适用于快速原型开发。

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

<template>
  <h1>Hello!</h1>
</template>

然后在这个 App.vue 文件所在的目录下运行:

vue serve
// 运行的时候,默认找main.js ,找不到main.js,则去找App.vue

vue serve 使用了和 vue create 创建的项目相同的默认设置 (webpack、Babel、PostCSS 和 ESLint)。它会在当前目录自动推导入口文件——入口可以是 main.jsindex.jsApp.vueapp.vue 中的一个。你也可以显式地指定入口文件:

vue serve MyComponent.vue

表单组件的封装

  • 涉及的细节
    • 插槽
    • parent、parent、parentchildren、provide和inject 组件通信
    • 组件的双向数据绑定
    • 自定义broadcast、broadcast、broadcastdispatch
src                             
├─ components           
│  ├─ el-form-item.vue  
│  ├─ el-form.vue       
│  └─ el-input.vue      
├─ App.vue              
└─ main.js              

App.vue

<template>
  <div>
    <el-form :model="ruleForm" :rules="rules" ref="ruleForm">
      <el-form-item label="用户名" prop="username">
        <el-input v-model="ruleForm.username"></el-input>
      </el-form-item>
      <el-form-item label="密码" prop="password">
        <el-input v-model="ruleForm.password"></el-input>
      </el-form-item>
      <el-form-item>
        <button @click="submitForm">提交表单</button>
      </el-form-item>
    </el-form>
  </div>
</template>
<script>
import elForm from "./components/el-form";
import elInput from "./components/el-input";
import elFormItem from "./components/el-form-item";
export default {
  components: {
    "el-form": elForm,
    "el-input": elInput,
    "el-form-item": elFormItem
  },
  data() {
    return {
      ruleForm: {
        username: "",
        password: ""
      },
      rules: {
        username: [
          { required: true, message: "请输入用户名" },
          { min: 3, max: 5, message: "长度在 3 到 5 个字符" }
        ],
        password: [{ required: true, message: "请输入密码" }]
      }
    };
  },
  methods: {
    submitForm(formName) {
      this.$refs["ruleForm"].validate(valid => {
        if (valid) {
          alert("submit!");
        } else {
          console.log("error submit!!");
          return false;
        }
      });
    }
  }
};
</script>

main.js


import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

// 不停的找所有的子组件,找到后触发方法
Vue.prototype.$broadcast = function (componentName, eventName) {
  let children = this.$children;
  let arr = [];
  function findFormItem(children) {
    children.forEach(child => {
      if (child.$options.name === componentName) {
        if (eventName) {
          arr.push(child.$emit('eventName'))
        } else {
          arr.push(child)
        }
      }
      if (child.$children) {
        findFormItem(child.$children);
      }
    });
  }
  findFormItem(children);
  return arr;
}

// 找到父组件,向父组件派发方法(可跨级)
Vue.prototype.$dispatch = function (componentName, eventName) {
  const parent = this.$parent;
  while (parent) {
    let name = parent.$options.name;
    if (name == componentName) {
      break;
    } else {
      parent = parent.$parent;
    }
  }
  if (parent) {
    if (eventName) {
      // 找到后,触发这个方法
      return parent.$emit(eventName)
    }
    return parent
  }
}


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

el-form.vue

<template>
  <form @submit.prevent>
    <slot></slot>
  </form>
</template>
<script>
export default {
  name: "elForm",
  // 把当前实例暴露出来,放到当前组件的_provided属性
  provide() {
    return { elForm: this };
  },
  props: {
    model: {
      type: Object,
      // 返回函数,保证数据不被共享
      default: () => ({})
    },
    rules: {
      type: Object,
      default: () => ({})
    }
  },
  methods: {
    async validate(cb) {
      // 需要看一下内部的el-form-item书否都通过校验了
      let children = this.$broadcast("elFormItem");
      try{
          await Promise.all(children.map(child=>child.validate()));
          cb(true);
      }catch{
          cb(false)
      }
    }
  }
};
</script>

el-form-item.vue

<template>
  <form @submit.prevent>
    <slot></slot>
  </form>
</template>
<script>
export default {
  name: "elForm",
  // 把当前实例暴露出来,放到当前组件的_provided属性
  provide() {
    return { elForm: this };
  },
  props: {
    model: {
      type: Object,
      // 返回函数,保证数据不被共享
      default: () => ({})
    },
    rules: {
      type: Object,
      default: () => ({})
    }
  },
  methods: {
    async validate(cb) {
      // 需要看一下内部的el-form-item书否都通过校验了
      let children = this.$broadcast("elFormItem");
      try{
          await Promise.all(children.map(child=>child.validate()));
          cb(true);
      }catch{
          cb(false)
      }
    }
  }
};
</script>

el-input.vue


<template>
  <input type="text" :value="value" @input="handleInput">
</template>
<script>
export default {
  name: "elInput",
  props: {
    value: {
      String,
    },
  },

  methods: {
    handleInput(e) {
      this.$emit("input", e.target.value);
      // 跨级找到对应的formItem组件进行校验
      this.$dispatch("elFormItem", "validate");
    },
  },
};
</script>
Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐