Vue3的表单和开发模式

85 阅读2分钟

Vue3的表单和开发模式

知识补充(浅拷贝和深拷贝)

    <!-- 1.对象的引用赋值 -->
    <script>
      // const info = { name: "why", age: 18 };
      // const obj = info;
      // info.name = "kobe";
      // console.log(obj.name);  打印结果是'kobe',因为这里是引用赋值,赋值给 obj 的是内存地址
    </script>
    <!-- 2.对象的浅拷贝 -->
    <script>
      // const info = { name: "why", age: 18 };
      // const obj = Object.assign({}, info);
​
      // info.name = "kobe";
      // console.log(obj.name);  打印结果是'why',因为直接创建了一个新的对象赋值给了obj,
      //                      但当 info 中还存在子元素对象,则赋值给 obj 的新对象中依旧会存在这个       //                        子元素对象的内存地址
    </script>
    <!-- 3.对象的深拷贝 -->
    <script>
      // const info = { name: "why", age: 18, friend: { name: "kobe" } };
      // const obj = JSON.parse(JSON.stringify(info));
      // info.friend.name = "james";
      // console.log(obj.friend.name); 打印结果是'kobe', 因为进行了深拷贝,赋值给 obj 的是           //                               info 的所有初始元素,包括子元素对象                                               
    </script>
    <!-- 4.利用库函数 lodash-->
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
    <!-- lodash 进行浅拷贝 -->
    <script>
      // const info = { name: "why", age: 18 };
      // const obj = _.clone(info);
      // info.name = "kobe";
      // console.log(obj.name);  打印结果是'why',因为利用 lodash 库函数进行了浅拷贝
    </script>
    <!-- lodash进行深拷贝 -->
    <script>
      // const info = { name: "why", age: 18, friend: { name: "kobe" } };
      // const obj = _.cloneDeep(info);
      // info.friend.name = "james";
      // console.log(obj.friend.name); 打印结果是'kobe', 因为利用 lodash 库函数进行了深拷贝
    </script>

v-model 的基本使用

表单提交是开发中非常常见的功能,也是和用户交互的重要手段:

  • 用户在登录、注册时需要提交账号密码;
  • 用户在检索、创建、更新信息时,需要提交一些数据;

当我们需要在代码逻辑中获取到用户提交的数据,我们通常会使用 v-model 指令来完成:

  • v-mode 指令可以在表单 inputtextarea 以及 select 元素上创建双向数据绑定
  • 它会根据控件类型自动选取正确的方法来更新元素;
  • 尽管有些神奇,v-model 本质上不过是语法糖,它负责监听用户的输入事件来更新数据,并在某种极端场景下进行一些特殊处理;

v-model 的原理

v-model 的原理其实是两个操作:

  • v-bind(:) 绑定 value 属性的值;
  • v-on(@) 绑定 input 事件监听到函数中,函数会获取最新的值赋值到绑定的属性中;```
    <div id="app"></div>
    <template id="my-app">
      <!-- 1.v-bind value的绑定 2.监听input事件,更新message的值 -->
      <!-- <input type="text" :value="message" @input="inputChange" /> -->
      <input type="text" v-model="message" />
      <h2>{{message}}</h2>
    </template>
    <script src="../js/Vue.js"></script>
    <script>
      const App = {
        template: "#my-app",
        data() {
          return {
            message: "Hello World",
          };
        },
        methods: {
          inputChange(event) {
            this.message = event.target.value;
          },
        },
      };
      Vue.createApp(App).mount("#app");
    </script>

v-model 绑定其他表单

    <div id="app"></div>
    <template id="my-app">
      <!-- 1.绑定textarea -->
      <label for="intro">
        自我介绍
        <textarea
          name="intro"
          id="intro"
          cols="30"
          rows="10"
          v-model="intro"
        ></textarea>
      </label>
      <h2>intro: {{intro}}</h2>
​
      <!-- 2.绑定checkbox -->
      <!-- 2.1.单选框 -->
      <label for="agree"
        ><input id="agree" type="checkbox" v-model="isAgree" />同意协议
      </label>
      <h2>isAgree: {{isAgree}}</h2>
​
      <!-- 2.2.多选框 -->
      <span>你的爱好:</span>
      <label for="basketball"
        ><input
          id="basketball"
          type="checkbox"
          v-model="hobbies"
          value="basketball"
        />篮球
      </label>
      <label for="football"
        ><input
          id="football"
          type="checkbox"
          v-model="hobbies"
          value="football"
        />足球
      </label>
      <label for="basketball"
        ><input
          id="tennis"
          type="checkbox"
          v-model="hobbies"
          value="tennis"
        />网球
      </label>
      <h2>hobbies: {{hobbies}}</h2>
​
      <!-- 3.绑定radio -->
      <span>你的性别:</span>
​
      <label for="male">
        <input id="male" type="radio" v-model="gender" value="male" />男
      </label>
      <label for="female">
        <input id="female" type="radio" v-model="gender" value="female" />女
      </label>
      <h2>gender: {{gender}}</h2>
​
      <!-- 4.绑定select -->
      <span>喜欢的水果:</span>
      <select v-model="fruits" multiple size="2">
        <option value="apple">苹果</option>
        <option value="orange">橘子</option>
        <option value="banana">香蕉</option>
      </select>
      <h2>fruits: {{fruits}}</h2>
    </template>
    <script src="../js/Vue.js"></script>
    <script>
      const App = {
        template: "#my-app",
        data() {
          return {
            intro: "Hello World",
            isAgree: false,
            hobbies: [],
            gender: "",
            fruits: "",
          };
        },
      };
      Vue.createApp(App).mount("#app");
    </script>

v-model 修饰符 - lazy

作用:

  • 默认情况下,v-model 在进行双向绑定时,绑定的是 input 事件,会在每次内容输入后就将最新的值和绑定的属性进行同步;
  • 如果我们在 v-model 后跟上 lazy 修饰符,会将绑定的事件切换为 change 事件,只有在提交时(比如回车)才会触发;
    <div id="app"></div>
    <template id="my-app">
      <!-- 加lazy修饰符,在提交时才会触发 -->
      <input type="text" v-model.lazy="message" />
      <h2>{{message}}</h2>
    </template>
    <script src="../js/Vue.js"></script>
    <script>
      const App = {
        template: "#my-app",
        data() {
          return {
            message: "Hello World",
          };
        },
      };
      Vue.createApp(App).mount("#app");
    </script>

v-model 修饰符 - number

v-model 赋值默认是 string 类型,如果我们想传入数字类型,需要加修饰符 number

    <div id="app"></div>
    <template id="my-app">
           <!-- number修饰符 -->
      <input type="text" v-model.number="message" />
      <h2>{{message}}</h2>
    </template>
    <script src="../js/Vue.js"></script>
    <script>
      const App = {
        template: "#my-app",
        data() {
          return {
            message: 100,
          };
        },
      };
      Vue.createApp(App).mount("#app");
    </script>

v-model 修饰符 - trim

自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符:

    <div id="app"></div>
    <template id="my-app">
       <!-- trim修饰符,去除两边空格 -->
       <input type="text" v-model.trim="message" />
    </template>
    <script src="../js/Vue.js"></script>
    <script>
      const App = {
        template: "#my-app",
        data() {
          return {
            message: "Hello World",
          };
        },
      };
      Vue.createApp(App).mount("#app");
    </script>

注册全局组件

    <div id="app"></div>
    <template id="my-app">
      <component-a></component-a>
      <component-b></component-b>
    </template>
    <template id="component-a">
      <h2>{{title}}</h2>
      <p>{{desc}}</p>
      <button @click="btnClick">按钮点击</button>
    </template>
​
    <template id="component-b">
      <input type="text" v-model="message" />
      <h2>{{message}}</h2>
    </template>
​
    <script src="../js/Vue.js"></script>
    <script>
      const App = {
        template: "#my-app",
      };
​
      const app = Vue.createApp(App);
      // 使用app注册一个全局组件
      // 全局组件: 意味着这个组件可以在任何的组件模板中使用
      app.component("component-a", {
        template: "#component-a",
        data() {
          return {
            title: "我是标题",
            desc: "我是内容,哈哈哈哈哈",
          };
        },
        methods: {
          btnClick() {
            console.log("按钮发生了点击");
          },
        },
      });
​
      app.component("component-b", {
        template: "#component-b",
        data() {
          return {
            message: "Hello World",
          };
        },
      });
      app.mount("#app");
    </script>

组件的名称

在通过 app.component 注册一个组件时,第一个参数是组件的名称,定义组件的方式有两种:

  • 使用 kebab-case(短横线分隔符)

    当时用 kebab-case 定义组件时,必须在引用这个自定义元素时使用 kebab-case;

  • 使用 PascalCase(驼峰标识符)

当使用 PascalCase定义一个组件时,引用时两种命名法均可以;

注册局部组件

    <div id="app"></div>
​
    <template id="my-app">
      <h2>{{message}}</h2>
      <component-a></component-a>
    </template>
​
    <template id="component-a">
      <h2>我是组件A</h2>
      <p>我是内容,哈哈哈哈</p>
    </template>
​
    <script src="../js/Vue.js"></script>
    <script>
      const ComponentA = {
        template: "#component-a",
      };
​
      const App = {
        template: "#my-app",
        components: {
          ComponentA: ComponentA,
        },
        data() {
          return {
            message: "Hello World",
          };
        },
      };
​
      Vue.createApp(App).mount("#app");
    </script>

\