本篇知识点主要来自Vue官网,是对基础部分知识的学习总结,适用于对vue稍微了解的人群,可以更加规范的使用Vue相关语法,本次代码是脚手架搭建后修改根组件后的代码,具体内容看最后的截图,最后会附上修改和编辑后文件的全部代码。
我们先对一个SFC(单文件组件)的组成部分做一个了解。
<template>
template>
<script>
export default(){
//当前组件实例
}
script>
<style>
组件模板样式
style>
<template>
<h1>{{ msg + ":" + name }}h1>
template>
<template>
{{htmls}}:
<span v-html="htmls">span>
template>
<template>
<div v-bind="attributes">div>
template>
<template>
<div :id="`list-${id}`">
{{number + 1}}
{{ok ? "是":"否"}}
{{msg.split("").reverse().join("")}}
div>
template>
<template>
<div>{{getNumber()}}div>
template>
import { createApp } from 'vue'
import App from './RootApp.vue'
let name = "吕懿洋"
// createApp(组件,组件的props对象)
let app = createApp(App, { name: name })
// 6.设置全局变量,可被任意组件调用
app.config.globalProperties.rootObj = {
author: 'lvyy'
}
app.mount('#app')
<template>
{{rootObj.author}}
template>
<span v-text="msg">span>
<span>{{msg}}span>
<br />
<span v-html="htmls">span>
<span>
<font color="red">红色文字font>
span>
<br />
<span v-show="false">测试v-showspan>
<span style="display:none;">测试等价v-showspan>
<span v-if="number == 1">number == 1span>
<span v-else-if="number == 2">number == 2span>
<span v-else>number != 1 且 number != 2span>
<div v-for="(peo,index) in forList" :key="index">
<span v-for="(value,key,index1) in peo" :key="index + key + index1">
{{`${index1} ${key} : ${value}`}}
<br />
span>
<br />
div>
<button v-on:click="sayHello">hello1button>
<br />
<button @click="sayHello">hello2button>
<br />
<button v-on:[event]="sayHello">hello3button>
<br />
<button @[event]="sayHello">hello4button>
<br />
<button v-on:[event]="getMsg('hello',$event)">hello5button>
<br />
<button @[event]="getMsg('hello',$event)">hello6button>
<br />
<button v-on:[event].stop="getMsg('hello',$event)">hello7button>
<br />
<button @[event].stop="getMsg('hello',$event)">hello8button>
<br />
<button v-on:[event].prevent="getMsg('hello',$event)">hello9button>
<br />
<button @[event].prevent="getMsg('hello',$event)">hello10button>
<br />
<button v-on:[event].capture="getMsg('hello',$event)">hello11button>
<br />
<button @[event].capture="getMsg('hello',$event)">hello12button>
<br />
<button v-on:[event].self="getMsg('hello',$event)">hello13button>
<br />
<button @[event].self="getMsg('hello',$event)">hello14button>
<br />
<button v-on:[event].once="getMsg('hello',$event)">hello15button>
<br />
<button @[event].once="getMsg('hello',$event)">hello16button>
<br />
<button v-on:[event].left="getMsg('hello',$event)">hello17button>
<br />
<button @[event].left="getMsg('hello',$event)">hello18button>
<br />
<button v-on:[event].right="getMsg('hello',$event)">hello19button>
<br />
<button @[event].right="getMsg('hello',$event)">hello20button>
<br />
<button v-on:[event].middle="getMsg('hello',$event)">hello21button>
<br />
<button @[event].middle="getMsg('hello',$event)">hello22button>
<br />
<button v-on:keyup.x.once="getMsg('hello',$event)">hello23button>
<br />
<button @keyup.y="getMsg('hello',$event)">hello24button>
<br />
<ChildApp v-on:myEvent="getMsg('hello',$event)">ChildApp>
<br />
<ChildApp @myEvent="getMsg('hello',$event)">ChildApp>
<br />
<img v-bind:src="imageSrc" />
<img v-bind:[attribute1]="imageSrc" />
<img :[attribute1]="imageSrc" />
<div :id="app4+'4'">div>
<div :class="{red:isRed}">文字1div>
<div :class="[className1,className2]">文字2div>
<div :class="[className1,{className2:true}]">文字3div>
<div :style="{fontSize: 28 + 'px'}">文字1div>
<div :style="[style1,style2]">文字2div>
<div v-bind="attributes1">测试绑定ObjAttributediv>
<ChildApp1 :id="id" :name="name">ChildApp1>
<ChildApp1 v-bind="{id:'app6',name:name}">ChildApp1>
<script>
data(){return {...}}
script>
注意: 当一个obj赋值给this.obj时,赋值后this.obj是响应式状态,而obj不是,因此他们两个===比较为false
<button @click="sayDelayHello1">防抖响应button>
// 14.1 引入防抖函数(需要npm i lodash)
import { debounce } from "lodash";
export default(){
data(){
return{
}
},
methods:{
// 14.2 引入防抖函数(需要npm i lodash)
sayHello1() {
console.log("防抖函数2");
},
},
created(){
// 14.3 created中自定义的属性,貌似不用再data中声明,为了遵循规范还是再data中定义一下
this.sayDelayHello1 = debounce(this.sayHello1, 1000);
}
}
{{ reverseMsg }}
export default(){
data(){
return{
msg1:'hello'
}
},
computed: {
// 计算属性看上去像一个方法,其实他是一个属性,如果里面只写get方法,可以简写成这样
reverseMsg() {
return this.msg1
.split("")
.reverse()
.join("");
},
}
<span class="err">结果span>
<span :class="{err:!isSuccess}">结果span>
<span :class="[errClass]">结果span>
<button @click="isSuccess = !isSuccess">{{buttonName}}button>
<span v-bind:class="spanClass">结果span>
<ChildApp1 :class="{success:isSuccess}">ChildApp1>
<span style="color: red; font-size: 28px;">结果span>
<span :style="{color: 'red','font-size': 28+'px'}">结果span>
<span :style="[{color: 'red'},{'font-size': 28+'px'}]">结果span>
<span
v-for="({id,name,age}, index) in forList"
:key="id+name+index"
>{{id + "-" + name + "-" + age + "\t"}}span>
<button @click="pushDatas">尾部追加button>
<button @click="popData">尾部删除button>
<button @click="shiftData">头部删除button>
<button @click="unshiftDatas">头部追加button>
<button @click="spliceDatas">替换button>
<button @click="sortAscDatas">正序button>
<button @click="sortDescDatas">逆序button>
<button @click="reverseDatas">反转button>
<input :value="text" @input="event => text = event.target.value" />
<input v-model="text" />
<input v-model.lazy="text" />
<input v-model.number="text" />
<input v-model.trim="text" />
<textarea :value="text" @input="event => text=event.target.value">textarea>
<textarea v-model="text">textarea>
{{checked}}
<input type="checkbox" v-model="checked" true-value="yes" false-value="no" />
{{names}}
<input type="checkbox" v-model="names" :value="name1" />
<input type="checkbox" v-model="names" :value="name2" />
<input type="checkbox" v-model="names" :value="name3" />
{{radioValue}}
<input type="radio" v-model="radioValue" value="one" />
<input type="radio" v-model="radioValue" value="two" />
{{selected}}
<select v-model="selected">
<option value disabled="true">请选择option>
<option>Aoption>
<option>Boption>
<option>Coption>
select>
{{selected1}}
<select v-model="selected1" multiple>
<option value="A">A.上班option>
<option value="B">B.吃饭option>
<option value="C">C.睡觉option>
select>
{{selectObj}}
<select v-model="selectObj">
<option
v-for="option in selectedOptions"
:value="option"
:key="option.number"
>{{option.number}}option>
select>
聚焦输入框:
<input ref="input" v-model="userId1" />
<ChildApp1 ref="childApp1">ChildApp1>
export default(){
data(){
return{
userId:""
}
},
watch: {
userId: {
handler(newValue, oldValue) {
// this.searchDelayUserId();
this.searchUserId();
},
// 23.2 immediate的触发时机是在created生命周期钩子之前,所以created中定义的有状态的方法不能被调用
immediate: true
}
},
}
// 聚焦输入框
this.$refs["input"].focus();
// 组件上应用ref时,子组件可以通过expose:["data属性名",...] 暴露出子组件的属性,
// 父组件可以通过this.$refs.refName.属性名 获取到
console.log(this.$refs.childApp1.childName);
console.log(this.$refs.childApp1.childId);
<button @click="componentName = componentName == 'ChildApp'?'ChildApp1':'ChildApp'">切换button>
<keep-alive>
<component :is="componentName">component>
keep-alive>
<ChildApp2>ChildApp2>
<template>
<div v-bind="attributes">
<h1>{{ msg + ":" + name }}h1>
{{htmls}}:
<span v-html="htmls">span>
<br />
<button v-bind:disabled="disabled" @click="setNumber">不可点击按钮button>
{{number + 1}}
{{ok ? "是":"否"}}
{{msg.split("").reverse().join("")}}
<div :id="`list-${id}`">
{{getNumber()}}
{{getNumber()}}
<br />
{{rootObj.author}}
<br />
<span v-text="msg">span>
<span>{{msg}}span>
<br />
<span v-html="htmls">span>
<span>
<font color="red">红色文字font>
span>
<br />
<span v-show="false">测试v-showspan>
<span style="display:none;">测试等价v-showspan>
<span v-if="number == 1">number == 1span>
<span v-else-if="number == 2">number == 2span>
<span v-else>number != 1 且 number != 2span>
<div v-for="(peo,index) in forList" :key="index">
<span v-for="(value,key,index1) in peo" :key="index + key + index1">
{{`${index1} ${key} : ${value}`}}
<br />
span>
<br />
div>
<button v-on:click="sayHello">hello1button>
<br />
<button @click="sayHello">hello2button>
<br />
<button v-on:[event]="sayHello">hello3button>
<br />
<button @[event]="sayHello">hello4button>
<br />
<button v-on:[event]="getMsg('hello',$event)">hello5button>
<br />
<button @[event]="getMsg('hello',$event)">hello6button>
<br />
<button v-on:[event].stop="getMsg('hello',$event)">hello7button>
<br />
<button @[event].stop="getMsg('hello',$event)">hello8button>
<br />
<button v-on:[event].prevent="getMsg('hello',$event)">hello9button>
<br />
<button @[event].prevent="getMsg('hello',$event)">hello10button>
<br />
<button v-on:[event].capture="getMsg('hello',$event)">hello11button>
<br />
<button @[event].capture="getMsg('hello',$event)">hello12button>
<br />
<button v-on:[event].self="getMsg('hello',$event)">hello13button>
<br />
<button @[event].self="getMsg('hello',$event)">hello14button>
<br />
<button v-on:[event].once="getMsg('hello',$event)">hello15button>
<br />
<button @[event].once="getMsg('hello',$event)">hello16button>
<br />
<button v-on:[event].left="getMsg('hello',$event)">hello17button>
<br />
<button @[event].left="getMsg('hello',$event)">hello18button>
<br />
<button v-on:[event].right="getMsg('hello',$event)">hello19button>
<br />
<button @[event].right="getMsg('hello',$event)">hello20button>
<br />
<button v-on:[event].middle="getMsg('hello',$event)">hello21button>
<br />
<button @[event].middle="getMsg('hello',$event)">hello22button>
<br />
<button v-on:keyup.x.once="getMsg('hello',$event)">hello23button>
<br />
<button @keyup.y="getMsg('hello',$event)">hello24button>
<br />
<ChildApp v-on:myEvent="getMsg('hello',$event)">ChildApp>
<br />
<ChildApp @myEvent="getMsg('hello',$event)">ChildApp>
<br />
<img v-bind:src="imageSrc" />
<img v-bind:[attribute1]="imageSrc" />
<img :[attribute1]="imageSrc" />
<div :id="app4+'4'">div>
<div :class="{red:isRed}">文字1div>
<div :class="[className1,className2]">文字2div>
<div :class="[className1,{className2:true}]">文字3div>
<div :style="{fontSize: 28 + 'px'}">文字1div>
<div :style="[style1,style2]">文字2div>
<div v-bind="attributes1">测试绑定ObjAttributediv>
<ChildApp1 :id="id" :name="name">ChildApp1>
<ChildApp1 v-bind="{id:'app6',name:name}">ChildApp1>
<button @click="sayDelayHello">防抖响应button>
<button @click="sayDelayHello1">防抖响应button>
<button @click="sayHello1">非防抖响应button>
{{ reverseMsg }}
{{ reverseMsg }}
<br />
{{ reverseMsg }}
{{ reverseMsg }}
<br />
{{ reverseMsg1 }}
{{ reverseMsg1 }}
<br />
{{ reverseMsg1 }}
{{ reverseMsg1 }}
<br />
<span class="err">结果span>
<span :class="{err:!isSuccess}">结果span>
<span :class="[errClass]">结果span>
<button @click="isSuccess = !isSuccess">{{buttonName}}button>
<span v-bind:class="spanClass">结果span>
<ChildApp1 :class="{success:isSuccess}">ChildApp1>
<span style="color: red; font-size: 28px;">结果span>
<span :style="{color: 'red','font-size': 28+'px'}">结果span>
<span :style="[{color: 'red'},{'font-size': 28+'px'}]">结果span>
<span
v-for="({id,name,age},index) in forList"
:key="id+name+index"
>{{id + "-" + name + "-" + age + "\t"}}span>
<br />
<button @click="pushDatas">尾部追加button>
<button @click="popData">尾部删除button>
<button @click="shiftData">头部删除button>
<button @click="unshiftDatas">头部追加button>
<button @click="spliceDatas">替换button>
<button @click="sortAscDatas">正序button>
<button @click="sortDescDatas">逆序button>
<button @click="reverseDatas">反转button>
<input :value="text" @input="event => text = event.target.value" />
<input v-model="text" />
<input v-model.lazy="text" />
<input v-model.number="text" />
<input v-model.trim="text" />
<textarea :value="text" @input="event => text=event.target.value">textarea>
<textarea v-model="text">textarea>
{{checked}}
<input type="checkbox" v-model="checked" true-value="yes" false-value="no" />
{{names}}
<input type="checkbox" v-model="names" :value="name1" />
<input type="checkbox" v-model="names" :value="name2" />
<input type="checkbox" v-model="names" :value="name3" />
{{radioValue}}
<input type="radio" v-model="radioValue" value="one" />
<input type="radio" v-model="radioValue" value="two" />
{{selected}}
<select v-model="selected">
<option value disabled="true">请选择option>
<option>Aoption>
<option>Boption>
<option>Coption>
select>
{{selected1}}
<select v-model="selected1" multiple>
<option value="A">A.上班option>
<option value="B">B.吃饭option>
<option value="C">C.睡觉option>
select>
{{selectObj}}
<select v-model="selectObj">
<option
v-for="option in selectedOptions"
:value="option"
:key="option.number"
>{{option.number}}option>
select>
工号:
<input v-model="userId" />
聚焦输入框:
<input ref="input" v-model="userId1" />
<ChildApp1 ref="childApp1">ChildApp1>
<button @click="componentName = componentName == 'ChildApp'?'ChildApp1':'ChildApp'">切换button>
<keep-alive>
<component :is="componentName">component>
keep-alive>
<ChildApp2>ChildApp2>
div>
div>
template>
<style scoped>
.red {
font-size: 28px;
}
.className1 {
font-size: 28px;
}
.className2 {
color: red;
}
.success {
color: green;
}
.err {
color: red;
}
style>
<script>
// 引入一个子组件
import ChildApp from "./components/ChildApp.vue";
import ChildApp1 from "./components/ChildApp1.vue";
// 引入一张图片
import img1 from "./img/1.png";
// 14.1 引入防抖函数(需要npm i lodash)
import { debounce } from "lodash";
export default {
// 父组件传入的数据
props: {
name: String
},
// 子组件
components: { ChildApp: ChildApp, ChildApp1: ChildApp1 },
// 本组件定义的数据
data() {
return {
id: "app2",
msg: "hello world",
htmls: "红色文字",
disabled: false,
attributes: {
id: "app3",
name: "div1"
},
number: 1,
ok: true,
forList: [
{
id: 1,
name: "张三",
age: 18
},
{
id: 2,
name: "李四",
age: 20
}
],
event: "click",
imageSrc: img1,
attribute1: "src",
app4: "app",
isRed: true,
className1: "className1",
className2: "className2",
style1: {
fontSize: "28px"
},
style2: {
color: "red"
},
attributes1: {
id: "app5",
"other-attr": "hello"
},
name: "美少女",
sayDelayHello1: null,
msg1: "i love you",
submit: "提交",
revert: "还原",
isSuccess: false,
errClass: "err",
text: "hello",
checked: "no",
name1: "张三",
name2: "李四",
name3: "王五",
names: [],
radioValue: "",
selected: "",
selected1: [],
selectedOptions: [{ number: 1 }, { number: 2 }, { number: 3 }],
selectObj: "",
userId: "",
userId1: "",
componentName: "ChildApp"
};
},
created() {
// created中自定义的属性,貌似不用再data中声明,为了遵循规范还是再data中定义一下
this.sayDelayHello1 = debounce(this.sayHello1, 1000);
console.log(this.sayDelayHello1);
this.user = "name";
console.log(this.user);
this.searchDelayUserId = debounce(this.searchUserId, 1000);
},
computed: {
// 计算属性看上去像一个方法,其实他是一个属性,如果里面只写get方法,可以简写成这样
reverseMsg() {
console.log("hello");
return this.msg1
.split("")
.reverse()
.join("");
},
// 非简写形式
reverseMsg1: {
get() {
return this.msg1
.split("")
.reverse()
.join("");
},
set(newValue) {
console.log("改变了");
}
},
// 复杂的表达式写在计算属性中
spanClass: {
get() {
return {
success: this.isSuccess,
err: !this.isSuccess
};
}
},
buttonName: {
get() {
return this.isSuccess ? this.revert : this.submit;
}
}
},
watch: {
userId: {
handler(newValue, oldValue) {
// this.searchDelayUserId();
this.searchUserId();
},
// 23.2 immediate的触发时机是在created之前,所以created中定义的有状态的方法不能被调用
immediate: true
}
},
mounted() {
this.$refs["input"].focus();
console.log(this.$refs.childApp1.childName);
console.log(this.$refs.childApp1.childId);
},
// 本组件定义的方法
methods: {
setNumber() {
this.number = this.number + 1;
},
getNumber() {
console.log("msg改变就会触发事件");
return this.number;
},
sayHello() {
console.log("hello world!");
console.log(this.user);
},
getMsg(param1, event) {
console.log(param1);
console.log(event);
},
// 14.2 设置防抖函数 调用函数名:debounce(业务处理函数, 防抖毫秒数)
sayDelayHello: debounce(function() {
console.log("防抖函数");
}, 1000),
sayHello1() {
console.log("防抖函数2");
},
// 尾部追加多个数据
pushDatas() {
let data1 = { id: 3, name: "王五", age: 22 };
let data2 = { id: 4, name: "秦六", age: 33 };
let length = this.forList.push(data1, data2);
console.log("追加后长度为:" + length);
},
// 尾部删除一个数据
popData() {
let data = this.forList.pop();
console.log("删除尾部数据:", data);
},
// 头部追加一条或多条数据
unshiftDatas() {
let data1 = { id: 3, name: "王五", age: 22 };
let data2 = { id: 4, name: "秦六", age: 33 };
let length = this.forList.unshift(data1, data2);
console.log("头部追加后长度为:" + length);
},
// 头部删除数据
shiftData() {
let data = this.forList.shift();
console.log("头部删除数据为:", data);
},
// 替换数据
spliceDatas() {
let data1 = { id: 3, name: "王五", age: 22 };
let data2 = { id: 4, name: "秦六", age: 33 };
let data = this.forList.splice(0, 1, data1, data2);
console.log("替换前的数据为:", data);
},
// 正序
sortAscDatas() {
this.forList.sort((a, b) => a.id - b.id);
},
// 逆序
sortDescDatas() {
this.forList.sort((a, b) => b.id - a.id);
},
// 反转
reverseDatas() {
this.forList.reverse();
},
searchUserId() {
console.log("检索userId");
}
}
};
script>
import { createApp } from 'vue'
import App from './RootApp.vue'
import ChildApp2 from './components/ChildApp2.vue'
let name = "吕懿洋"
// createApp(组件,组件的props对象)
let app = createApp(App, { name: name })
// 貌似没有效果
app.config.errorHandler = (err) => {
/* 处理错误 */
console.log(err)
}
// 6.设置全局变量,可被任意组件调用
app.config.globalProperties.rootObj = {
author: 'lvyy'
}
app.component("ChildApp2",ChildApp2)
app.mount('#app')
<template>
<div>
<input v-model="data" />
<button @click="childClick">子组件按钮button>
div>
template>
<script>
export default {
name: "ChildApp",
data() {
return {
data: ""
};
},
methods: {
childClick() {
this.$emit("myEvent");
}
}
};
script>
<template>
<div>
<input v-model="data" />
<div :class="$attrs.class">{{id + "-" + name}}div>
div>
template>
<script>
export default {
name: "ChildApp1",
props: {
id: String,
name: String
},
data() {
return {
childName: "ChildApp1",
childId: "ChildApp1",
data: ""
};
},
expose: ["childName"]
};
script>
<template>
<div>
<input v-model="data" />
div>
template>
<script>
export default {
name: "ChildApp2",
data() {
return {
childName: "ChildApp2",
childId: "ChildApp2",
data: ""
};
},
expose: ["childName"]
};
script>
npm i lodash
再执行npm install
,最后 npm run dev
,主要是为了下载防抖函数的插件