之前学习flask后端时接触到了vue,感觉比大学学的基础html,css,javascript要好用效果还好,所以就看看vue的相关知识,具体的环境搭建,在我之前的flask的后台cms博客里面有。用官网手册进行学习。
vue create 工程名#然创建工程,后选择vue3
cd my_vue#进入目录
npm run serve#运行开发服务器
1.文本插值:“Mustache”语法 (即双大括号),支持单一 JavaScript 表达式
<template>
<p>{{ msg }}</p>
</template>
<script>
export default {
data(){
return{msg:"模板插值"
}
}
};
</script>
2.原始 HTML:双大括号会将数据解释为纯文本,而不是 HTML。若想插入 HTML,你需要使用 v-html 指令:
<template>
<p v-html="rawhtml"></p>
</template>
<script>
export default {
data(){
return{
rawhtml:"图片连接"
}
}
};
</script>
3.动态响应绑定CSS属性Attribute:v-bind 指令;如果绑定的值是 null 或者 undefined,那么该 attribute 将会从渲染的元素上移除;简写语法:
;布尔型 attribute 依据 true / false 值来决定 attribute 是否应该存在于该元素上;还可以动态绑定多个值
<template>
<div v-bind:id="dynamicid" v-bind:class="dynamicclass">绑定class和id</div>
<div :title="dynamictitle">绑定值是null或undefined</div>
<button :disabled="isButtonDisabled">根据布尔值确定button是否可用</button>
<div v-bind="objectOfAttrs">一次绑定多个值</div>
</template>
<script>
export default {
data(){
return{
dynamicid:"appid",
dynamicclass:"appclass",
dynamictitle:undefined,//null
isButtonDisabled:false,
objectOfAttrs:{
id:'apid',
class:"apclass",
}
}
}
};
</script>
<style scoped>
.appclass{color:red;}
</style>
v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回真值时才被渲染。
v-else 元素添加一个“else 区块”,必须跟在一个 v-if 或者 v-else-if 元素后面,否则它将不会被识别。
v-else-if 提供的是相应于 v-if 的“else if 区块”。它可以连续多次重复使用。
另一个按条件显示一个元素的指令是 v-show。
v-if有较高的切换开销,v-show有较高的初始渲染开销。
<template>
<div v-if="flag">能看见1么</div>
<div v-else>看不见1就能看见2</div>
<div v-if="type==='A'">A</div>
<div v-else-if="type==='B'">B</div>
<div v-else-if="type==='C'">C</div>
<div v-else>not abc</div>
<div v-show="flag">我切换开销少</div>
</template>
<script>
export default{
data(){
return {
flag:true,
type:"C"
}
}
}
</script>
1.数组遍历时,每个循环项都要提供一个唯一的 key,以便 Vue 能够高效地跟踪每个元素的状态变化,:key=“item”。可选的第二个参数表示当前项的索引index;for …of …=for …in …
2.也可以遍历对象,它里面有三个参数(value,key,index)。:key=“value”。
<template>
<div>
<p v-for="(item,index) in names" :key="item">{{ item }}-{{ index }}</p>
<div v-for="item in results" :key="item">
<p>{{ item.title }}</p>
<img :src="item.avatar" alt="">
</div>
<p v-for="(value,key,index) of userInfo " :key="value">{{ value }}-{{ key }}-{{ index }}</p>
</div>
</template>
<script>
export default {
data() {
return {
names: ['python', 'flask', 'php', 'vue'] ,
results:[{
"title":"A",
"avatar":"https://lmg.jj20.com/up/allimg/4k/s/02/2109250006343S5-0-lp.jpg"
},{
"title":"B",
"avatar":"https://img1.baidu.com/it/u=1187129814,1675470074&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500"
}],
userInfo:{
name:"zoe",
age:27,
gender:"f"
}
}
}
}
</script>
1.监听事件:使用 v-on 指令 (简写为 @) 来监听 DOM 事件,并在事件触发时执行对应的 JavaScript。用法:v-on:click="handler"
或 @click="handler"
。分为内联事件处理器和方法事件处理器。
2.可以使用event并可以传参。
3.事件修饰符。
<template>
<h>1.内联事件处理器</h>
<button v-on:click="count++">Add</button>
<p>{{ count }}</p>
<h>2.方法事件处理器</h>
<button @click="add_2">Add_2</button>
<p>{{ count2 }}</p>
<h>事件传参event和$event</h>
<p @click="get_e">无外参</p>
<p @click="get_name_e(item,$event)" v-for="(item,index) of names" :key="index">{{ item }}</p>
<h>3.事件修饰符</h>
<div @click="clockDiv">
<p @click.stop="clockP">测试冒泡</p>
</div>
</template>
<script>
export default{
data(){
return {
count:0,
count2:0,
names:['zoe','jane','frank']
}
},
methods:{
add_2(){
this.count2++;
},
get_e(event){
console.log(event);
},
get_name_e(name,event){
console.log(name);
console.log(event);
},
clockDiv(){
console.log('Div');
},
clockP(){
console.log('P');
}
}
}
</script>
1.Vue 能够侦听响应式数组的变更方法,并在它们被调用时触发相关的更新,会对调用它们的原数组进行变更,这些变更方法包括:
push() pop() shift() unshift() splice() sort() reverse()
2.对调用它们的原数组不会变更的方法包括如下,只能通过复制给原数组实现变更
filter(),concat() 和 slice()
<template>
<h3>数组变化侦听</h3>
<button @click="addListHandler">添加数组</button>
<p v-for="(item,index) of names" :key="index">{{ item }}</p>
</template>
<script>
export default{
data(){
return {
names:['zoe','janey','jake']
}
},
methods:{
addListHandler(){
// this.names.push("frank")#√
// this.names.concat(['frank'])#×
this.names=this.names.concat(['frank'])//√
}
}
}
</script>
1.在script里面可以写computed属性,他和methods的区别是调用时不用(),而且只要内部的东西不变,它只会在页面出此渲染,而方法会消耗渲染成本。
<template>
<h3>{{code.name}}</h3>
<h3>{{ yon }}</h3>
<h3>{{ yon_m() }}</h3>
</template>
<script>
export default{
data(){
return{
code:{
name:'zoe',
skill:['python','php','vue']
}
}
},
computed:{
yon(){
return this.code.skill.length>0?'yes':'no';
}
},
methods: {
yon_m(){
return this.code.skill.length>0?'yes':'no';
}
}
}
</script>
1.为 class 和 style 的 v-bind 用法提供了特殊的功能增强。除了字符串外,表达式的值也可以是对象或数组以及数组嵌套对象。
<template>
<p :class="{'activate':isActive,'text-danger':hasError}">1.绑定对象</p>
<p :class="classObject">2.绑定多对象</p>
<p :class="[arrActivate,arrHasError]">3.绑定数组</p>
<p :class="[isArray?'activate text-danger':'activate']">4.绑定简单运算</p>
<p :class="[isArray?'activate':'',{'text-danger':hasError}]">5.数组嵌套对象</p>
</template>
<script>
export default{
data(){
return{
isActive : false,
hasError : true,
classObject:{
'activate':true,
'text-danger':true
},
arrActivate:"activate",
arrHasError:"text-danger",
}
}
}
</script>
<style scoped>
.activate{
font-size:30px;
}
.text-danger{
color:red;
}
</style>
<template>
<h3>侦听器</h3>
<p>{{ myname }}</p>
<button @click="upnamehandle">修改名字</button>
</template>
<script>
export default{
data(){
return {
myname:"zoe"
}
},
methods:{
upnamehandle(){
this.myname = "queen";
}
},
watch:{
myname(newValue,oldValue){
console.log(newValue,oldValue);
}
}
}
</script>
<template>
<h>表单绑定输入</h>
<form>
<input type="text" v-model="message">
<p>{{ message }}</p>
<input type="checkbox" id="c" v-model="checked"/>
<lable for="c">{{ checked }}</lable>
</form>
</template>
<script>
export default {
data(){
return {
message:"",
checked:false
}
}
}
</script>
<template>
<div ref="c" class="container">{{ content }}</div>
<input type="text" ref="t">
<button @click="getElementHandle">获取元素</button>
</template>
<script>
export default{
data(){
return{content:"内容"}
},
methods:{
getElementHandle(){
this.$refs.c.innerHTML="我变了";//innerHTML:原生js,改变了变量content
console.log(this.$refs.t.value);//打印了input里面的内容
}
}
}
</script>
<template>
<IndexDemo/><!--3.显示组件-->
</template>
<script>
import IndexDemo from "./components/IndexDemo.vue"//1.引入组件
export default{
components: {
IndexDemo//2.注入组件
}
}
</script>
<style scoped>
/* scoped:样式只在当前组件生效 */
</style>
import { createApp } from 'vue'
import App from './App.vue'
import ArrayDemo from "./components/ArrayDemo.vue"//1.import这个组件
const app=createApp(App)
app.component("ArrayDemo",ArrayDemo)//2.绑定到全局app上,并给一个名字,之后就都用这个名字
app.mount('#app')
<template>
<ArrayDemo/>//在App.vue里面显示
</template>
//父亲
<template>
<h3>parent</h3>
<ChildDemo title="我是父亲给孩子的静态数据" :m="message"/>
</template>
<script>
import ChildDemo from './ChildDemo.vue'
export default{
data(){
return{
message:"动态数据"
}
},
components:{
ChildDemo
}
}
</script>
//孩子
<template>
<h3>child</h3>
<p>{{ title }}</p>
<p>{{ m }}</p>
</template>
<script>
export default{
data(){
return{}
},
props:["title","m"]//从父亲那里拿来的数据
}
</script>
type校验;
数字和字符串可以直接default;
数组和对象的默认值需要通过工厂函数返回默认值;
required必须要传参数;
props拿到的数据只读,不能修改。
<template>
<h3>parent</h3>
<ChildDemo :title="title" />
</template>
<script>
import ChildDemo from './ChildDemo.vue'
export default{
data(){
return{
title:"类型校验",
age:20,
names:['zoe','joy']
}
},
components:{
ChildDemo
}
}
</script>
<template>
<h3>child</h3>
<p>{{ title }}</p>
<p>{{ age }}</p>
<p>{{ names }}</p>
</template>
<script>
export default{
data(){
return{}
},
props:{
title:{
type:[String,Number,Array,Object],
required:true//必须要传参数,
},
age:{
type:Number,
default:0//数字和字符串可以直接default
},
names:{
type:Array,
default(){
return ["默认返回的列表"]//数组和对象的默认值需要通过工厂函数返回默认值
}
}
}
}
</script>
props只能父传子,但通过$emit可以子传父,并触发事件
<template>
<h3>parent组件自定义事件</h3>
<ChildDemo @someEvent="getHandle" />
<p>父元素:{{ message }}</p>
</template>
<script>
import ChildDemo from './ChildDemo.vue'
export default{
data(){
return{
message:""
}
},
components:{
ChildDemo
},
methods:{
getHandle(data){
this.message = data;
}
}
}
</script>
<template>
<h3>child</h3>
<button @click="clickEventHandle">传递数据</button>
</template>
<script>
export default{
data(){
return{
msg:"child数据"
}
},
methods:{
clickEventHandle(){
this.$emit("someEvent",this.msg)
}
}
}
</script>
<template>
<h3>Main组件</h3>
<p>搜素内容为:{{ search }}</p>
<SearchDemo @searchEvent="getSearch"/>
</template>
<script>
import SearchDemo from "./SearchDemo.vue"
export default{
data(){
return{
search:""
}
},
components:{
SearchDemo
},
methods:{
getSearch(data){
this.search = data;
}
}
}
</script>
<template>
搜索:<input type="text" v-model="search">
</template>
<script>
export default{
data(){
return{
search:""
}
},
watch:{//侦听器
search(newValue){
this.$emit("searchEvent",newValue)
}
}
}
</script>
“透传 attribute”指的是传递给一个组件,却没有被该组件声明为 props 或 emits 的 attribute 或者 v-on 事件监听器。最常见的例子就是 class、style 和 id。
插槽元素slot是一个插槽出口,传递的是一个HTML结构,标示了父元素提供的插槽内容将在哪里被渲染。
插槽内容动态传递数据时,在父级传入动态数据。
没有传递插槽内容时可以在子级给默认值。
v-slot:具名插槽,给插槽名字,然后引用多个插槽。缩写是#
插槽数据要父元素和子元素都传递是,子先传给父,父再在slot里面渲染传递给子(v-slot=“slotProps”)。
<template>
<!-- 3.显示子组件,这里传递着父元素的html -->
<SlotDemo>
<template v-slot:first>
<h3>我是父元素里面的html元素1{{ message }}</h3>
</template>
<!-- 具名插槽v-slot的缩写# -->
<template #seconder>
<!-- 没有传递任何html,所以用默认值 -->
</template>
</SlotDemo>
</template>
<script>
import SlotDemo from "./components/SlotDemo.vue"//1.引入子组件
export default{
data(){
return{
message:"插槽动态数据"
}
},
components: {
SlotDemo//2.注入子组件
}
}
</script>
<template>
<h3>我是子元素内容</h3>
<slot name="first">默认值1</slot>
<br>
<slot name="seconder">默认值2</slot>
</template>
8个生命周期函数:
创建期:beforeCreate created
挂载期:beforeMounte mounted
更新期:beforeUpdate updated
销毁期:beforeUnmount unmounted
1.component :is=“XX”
<template>
<component :is="tabComponent"></component>
<button @click="change">切换组件</button>
</template>
<script>
import ComponentA from "./components/ComponentA.vue";
import ComponentB from "./components/ComponentB.vue";
export default {
data(){
return{
tabComponent: "ComponentA"
}
},
components:{
ComponentA,
ComponentB,
},
methods:{
change(){
this.tabComponent = this.tabComponent=="ComponentA" ? "ComponentB" : "ComponentA";
}
}
}
</script>
2.组件切换时,被切换的就会被卸载掉,使用keep-alive
组件强制被切换的组件保持存活状态。
3.异步组件,使组件异步加载。方法:导入组件时使用异步导入方法即可:
const ComponentB=defineAsyncComponent(()=>import("./ComponentB.vue")
1.provide,inject