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
指令可以在表单input
、textarea
以及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>
\