什么是 Vue?
Vue (发音为 /vjuː/,类似 view) 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。无论是简单还是复杂的界面,Vue 都可以胜任。
快速入门
基本案例
效果为单击button按钮 count++
import { createApp } from 'vue'
createApp({
data() {
return {
count: 0
}
}
}).mount('#app')
<div id="app">
<button @click="count++">
Count is: {{ count }}
</button>
</div>
文本插值
最基本的数据绑定形式是文本插值,它使用的是“Mustache”语法 (即双大括号):
<span>Message: {{ msg }}</span>
双大括号标签会被替换为相应组件实例中 msg 属性的值。同时每次 msg 属性更改时它也会同步更新。
{{ }}里可以可以使用javascript表达式
{{ number +1}}
{{ ok ?'YES':'NO'}}
{{ message.split('').reverse().join('') }}
原始 HTML
双大括号会将数据解释为纯文本,而不是 HTML。若想插入 HTML,你需要使用 v-html指令:
<!-- v-html=innerHtml -->
<div v-html="html"></div>
v-html 会将html标签渲染
v-text 和 {{}} 不会渲染HTML标签,而是将标签和标签里的内容以纯文本的方式原样输出
绑定事件
可以使用 v-on 指令 (简写为 @) 来监听 DOM 事件,并在事件触发时执行对应的 JavaScript。用法:v-on:事件(如:click,change …)=“调用的JavaScript方法” 或 @click=“handler”
事件处理器的值可以是:
- 内联事件处理器:事件被触发时执行的内联 JavaScript 语句 (与 onclick 类似)。
- 方法事件处理器:一个指向组件上定义的方法的属性名或是路径。
事件处理
常用:
:::info
stop 阻止事件冒泡
prevent 取消事件默认行为 可以取消a标签的默认行为
once 只执行一次
:::
<div id="out_box" @click="out()">
<div id="inner_box" @click.stop="getMsg()">
<a href="https://blog.csdn.net/m0_59673811" id="lrj" @click.once.prevent="getMsg2">孤独患者请自愈</a>
</div>
<a href="https://blog.csdn.net/m0_59673811" id="lrj" @click.prevent @click.once="getMsg2">孤独患者请自愈</a>
</div>
数据绑定
数据绑定的一个常见需求场景是操纵元素的 CSS class 列表和内联样式。因为 class 和 style 都是 attribute,我们可以和其他 attribute 一样使用 v-bind 将它们和动态的字符串绑定。但是,在处理比较复杂的绑定时,通过拼接生成字符串是麻烦且易出错的。因此,Vue 专门为 class 和 style 的 v-bind 用法提供了特殊的功能增强。除了字符串外,表达式的值也可以是对象或数组。
- 绑定对象绑定对象
我们可以给 :class (v-bind:class 的缩写) 传递一个对象来动态切换 class:
<div :class="{ active: isActive }"></div>
上面的语法表示 active 是否存在取决于数据属性 isActive 的真假值。
- 绑定数组
我们可以给 :class 绑定一个数组来渲染多个 CSS class:
data() {return{ activeClass:'active', errorClass:'text-danger'}}
<div :class="[activeClass, errorClass]"></div>
渲染的结果是:
template<div class="active text-danger"></div>
v-if
v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回真值时才被渲染
<img alt="Vue logo" src="./assets/logo.png" :title="msg" v-if="aaa">
<img alt="Vue logo" src="./assets/logo.png" :title="msg" v-if="bbb">
true 渲染 false buxuanran
data() {
return {
aaa: false,
bbb: true
}
v-else
可以使用 v-else 为 v-if 添加一个“else 区块”。
<span v-if="age>=18">十八岁</span>
<span v-else>不是十八</span>
渲染结果为显示十八岁
data(){
return {
age=18
}
}
一个 v-else 元素必须跟在一个 v-if 或者 v-else-if 元素后面,否则它将不会被识别。
v-else-if
提供的是相应于 v-if 的“else if 区块”。它可以连续多次重复使用:
<span v-if="age>18">已成年</span>
<span v-else-if="age<18">未满十八</span>
<span v-else>十八</span>
渲染结果为 ”十八“
data(){
return {
age=18
}
}
一个使用 v-else-if 的元素必须紧跟在一个 v-if 或一个 v-else-if 元素后面。
v-show
一个可以用来按条件显示一个元素的指令是 v-show。
<img alt="Vue logo" src="./assets/logo.png" :title="msg" v-show="aaa">
<button @click="change">显示</button>
change(){
this.aaa= this.aaa === true ? false :true
}
v-show 不支持在 元素上使用,也不能和 v-else 搭配使用。
注意:
- v-show 控制css样式是否displat
- v-if 控制标签是否渲染
v-for
v-for 指令基于一个数组来渲染一个列表。v-for 指令的值需要使用 item in items 形式的特殊语法,其中 items 是源数据的数组,而 item 是迭代项的别名:
<ul v-for="name in names" :key="name">
<li v-text="name"></li>
</ul>
//通过下标
<!--第一个参数是列表元素,第二个参数是列表索引-->
<ul v-for="(name,index) in names" :key="name + index">
<li v-text="names[index]"></li>
</ul>
<!--第一个参数是对象属性值,第二个参数是对象属性名-->
<div v-for="(value,key) in person" v-text="key+':'+value" :key="key">
<table>
<!--person 集合里对象别名 persons集合名-->
<!--通过对象名.对象属性名的方式去遍历-->
<tr v-for="person in persons" :key="person.id">
<td v-text="person.name"></td>
<td v-text="person.age"></td>
</tr>
</table>
计算属性 (computed)
写在 computed里
computed: {
msg() {
return '她说彩礼八十万';
},
通过getter\setter实现对属性数据的显示和监视,计算属性存在缓存,多次读取只执行一次getter计算。
监听器 watch
watch: {
/**
* 监听器
* @param newValue 新值 变化后的值
* @param oldValue 旧值 变化前的值
*/
slogan(newValue, oldValue) {
console.log(newValue,oldValue)
}
team:{
handler(){
this.battle();
},
//初始化时调用
immediate:true,
//是否深度监听
//deep:true
}
表单操作
v-model
双向数据绑定(数据改变,渲染视图)
在前端处理表单时,我们常常需要将表单输入框的内容同步给 JavaScript 中相应的变量。手动连接值绑定和更改事件监听器可能会很麻烦:
<input
:value="text"
@input="event => text = event.target.value">
v-model 指令帮我们简化了这一步骤:
<input v-model="text">
另外,v-model 还可以用于各种不同类型的输入,、 元素。它会根据所使用的元素自动使用对应的 DOM 属性和事件组合:
- 文本类型的 和 元素会绑定 value property 并侦听 input 事件;
- 和 会绑定 checked property 并侦听 change 事件;
- 会绑定 value property 并侦听 change 事件。
注意
:::info
v-model 会忽略任何表单元素上初始的 value、checked 或 selected attribute。它将始终将当前绑定的 JavaScript 状态视为数据的正确来源。你应该在 JavaScript 中使用data 选项来声明该初始值。
:::
基本用法
文本
{{slogan}}
<span v-text="slogan"></span>
<input type="text" v-model="slogan">
data() {
return {
slogan: '她说彩礼八十万'
}
}
多行文本
<span>文本框输入内容:</span>
<p style="white-space: pre-line;">{{ message }}</p>
<textarea v-model="message" placeholder="输入内容"></textarea>
注意在 中是不支持插值表达式的。请使用 v-model 来替代:
<!-- 错误 -->
<textarea>{{ text }}</textarea>
<!-- 正确 -->
<textarea v-model="text"></textarea>
复选框
单一的复选框,绑定布尔类型值:
<input type="checkbox" id="checkbox" v-model="checked" />
<label for="checkbox">{{ checked }}</label>
单选按钮
<div>选择: {{ picked }}</div>
<input type="radio" id="one" value="One" v-model="picked" />
<label for="one">One</label>
<input type="radio" id="two" value="Two" v-model="picked" />
<label for="two">Two</label>
多选按钮
可以将多个复选框绑定到同一个数组或集合的值:
<input type="checkbox" id="" name="aihao" value="" v-model="hobbies">游泳
<input type="checkbox" id="" name="aihao" value="run" v-model="hobbies">跑步
<input type="checkbox" id="" name="aihao" value="skiing" v-model="hobbies">滑雪
{{
data() {
return {
hobbies:['run','skiing']
}
}
单选下拉列表框
<select name="hometown" v-model="hometown">
<option value="beijing">北京</option>
<option value="henan">河南</option>
<option value="hebei">河北</option>
</select>{{hometown}}
多选下拉列表
<select name="hometown" v-model="hometown" multiple>
<option value="beijing">北京</option>
<option value="henan">河南</option>
<option value="hebei">河北</option>
</select>{{hometown}}
v-model修饰符
.trim
如果想要默认自动去除用户输入内容中两端的空格,你可以在 v-model 后添加 .trim 修饰符:
{{slogan}}
<input type="text" v-model.trim="slogan">
.lazy
默认情况下,v-model 会在每次 input 事件后更新数据。可以添加 lazy 修饰符来改为在每次 chang 事件后更新数据:
<span v-text="slogan"></span>
<input type="text" v-model.trim.lazy="slogan">
.number
如果你想让用户输入自动转换为数字,你可以在 v-model 后添加 .number 修饰符来管理输入:
<input type="text" v-model.number="age">
如果该值无法被 parseFloat() 处理,那么将返回原始值。
number 修饰符会在输入框有 type=“number” 时自动启用。
组件基础
组件允许我们将 UI 划分为独立的、可重用的部分,并且可以对每个部分进行单独的思考。在实际应用中,组件常常被组织成层层嵌套的树状结构:
这和我们嵌套 HTML 元素的方式类似,Vue 实现了自己的组件模型,使我们可以在每个组件内封装自定义内容与逻辑。Vue 同样也能很好地配合原生 Web Component
1. 如何导入组件
- 定义组件
<template>
<h1 v-text="slogan"></h1>
</template>
<script>
export default {
name: "Demo",
data(){
return{
slogan:'孤独患者请自愈'
}
},
}
</script>
- 引入组件
<template>
<Demo></Demo>
</template>
<script>
//引⼊组件
import Demo from "@/components/demo/Demo";
export default {
name: 'App',
components:{
Demo
}
}
</script>
组件传值
父传子
- 在⽗组件定义⼀个值
<Demo msg="她说彩礼⼋⼗万"></Demo>
- 接收值
props:{
msg:{
type:String,
//必须接收值
request:true,
//没有值的情况下 设置默认值
default:'她说彩礼八十万'
}
}
子传父
- 定义⼀个⼦组件
<template>
<button type="button" v-text="innerSlogan" @click="my"></button>
</template>
<script>
export default {
name: "Demo2",
data(){
return{
innerSlogan:"郁金香没她郁金香"
}
},
//定义⼀个⽅法
methods:{
my(){
//第⼀个参数发送出去的动作 第⼆次参数是该动作携带的值
this.$emit('my',this.innerSlogan)
}
}
}
</script>
- 接收
<template>
<span v-text="slogan"></span>
<span v-text="msg"></span>
<Demo2 @my="my"></Demo2>
</template>
<script>
import Demo2 from "@/components/demo/Demo2";
export default {
name: "Demo",
data(){
return{
slogan:'嗨害'
}
},
props:{
msg:{
type:String,
request:true,
default:'盛夏亦是她'
}
},
components:{
Demo2
},
methods:{
my(content){
this.slogan=content;
}
}
}
</script>
运行步骤 首先子元素发送了⼀个叫动作叫my,并携带了参数,然后根据⼦组件的click的单机事件发送出去,然后父组 件捕获子组件传送的值
父子组件表单传值
<template>
>>>父组件表单
<input type="text" v-model="username"><br>
<HelLrj :parent="username" @getSubValue="username=$event"></HelLrj>
<br>
<hr>
<!--触发函数-->
<HelLrj :parent="username" @getSubValue="subValue"></HelLrj>
<LrjA v-model:parent="username"></LrjA>
</template>
<script>
import HelLrj from "@/components/chao05/HelLrj";
import LrjA from "@/components/chao05/LrjA";
export default {
name: 'App',
components: {
HelLrj,LrjA
},
data() {
return {
username: ''
}
},
methods: {
subValue(value) {
this.username=value
}
}
}
</script>
<template>
>>>子组件表单 :value绑定
<input type="text" :value="parent" @input="$emit('getSubValue',$event.target.value)"><br>
>>>子组件 v-model 绑定
<input type="text" v-model="parentValue" @input="$emit('getSubValue',$event.target.value)"><br>
</template>
<script>
export default {
name: "HelLrj",
props: {
parent: {
type: String
}
},
computed:
{
parentValue() {
return this.parent;
}
}
}
</script>
<template>
<input type="text" :value="parent" @input="$emit('update:parent',$event.target.value)"><br>
</template>
<script>
export default {
name: "LrjA",
props:{
parent:{
type:String
}
}
}
</script>
slot插槽
<template>
<HelLrj ref="HelLrj">
lirenjie
</HelLrj>
</template>
<script>
import HelLrj from "@/components/chao06/HelLrj";
export default {
name: 'App',
components: {
HelLrj
}
}
</script>
子组件标签里的内容会显示在子组件标签位置
<template>
<slot></slot>
<h1>她说彩礼八十万</h1>
<slot></slot>
</template>
<script>
export default {
name: "HelLrj"
}
</script>
具名插槽
<template>
<HelLrj ref="HelLrj">
<template v-slot:default>
lirenjie
</template>
<template v-slot:nva>
残情
</template>
<template v-slot:foot>
孤独患者
</template>
</HelLrj>
</template>
<script>
import HelLrj from "@/components/chao06/HelLrj";
export default {
name: 'App',
components: {
HelLrj
},
</script>
会找相对应的 v-slot:‘name’,没有name就找defaule(默认)
<template>
<slot name="nva"></slot>
<h1>她说彩礼八十万</h1>
<slot name="foot"></slot>
<slot></slot>
</template>
<script>
export default {
name: "HelLrj"
}
</script>
插槽缩写与插槽传值
- 插槽缩写
<HelLrj ref="HelLrj">
<template #lrj>
插槽缩写
</template>
</HelLrj>
</template>
#+name定义 使用
<template>
<slot name="lrj"></slot>
</template>
<script>
export default {
name: "HelLrj"
}
</script>
插槽传值
<template>
<slot name="set" :names="names"></slot>
</template>
<script>
export default {
name: "HelLrj",
data(){
return{
names:['lrj','gzy','zn']
}
}
}
</script>
绑定属性传值,传过去的是对象属性名,
<template>
<HelLrj ref="HelLrj">
<!--插槽传值-->
<template #set="lrjData">
<div v-text="lrjData"></div>
<div v-for="(name,index) in lrjData.names" :key="name+index" v-text="name"></div>
</template>
</HelLrj>
</template>
<script>
import HelLrj from "@/components/chao06/HelLrj";
export default {
name: 'App',
components: {
HelLrj
},
</script>
使用解构赋值的方式进行插槽传值
<template>
<slot name="set" :names="names"></slot>
</template>
<script>
export default {
name: "HelLrj",
data(){
return{
names:['lrj','gzy','zn']
}
}
}
</script>
{ 属性名 } 绑定的属性名结构取值
<template>
<HelLrj ref="HelLrj">
<template #set="{names}">
<div v-text="names"></div>
<div v-for="(name,index) in names" :key="name+index" v-text="name"></div>
</template>
</HelLrj>
</template>
<script>
import HelLrj from "@/components/chao06/HelLrj";
export default {
name: 'App',
components: {
HelLrj
},
</script>
组件深入
依赖注入
解决props逐级透传问题
通常情况下,当我们需要从父组件向子组件传递数据时,会使用 props。想象一下这样的结构:有一些多层级嵌套的组件,形成了一颗巨大的组件树,而某个深层的子组件需要一个较远的祖先组件中的部分数据。在这种情况下,如果仅使用 props 则必须将其沿着组件链逐级传递下去,这会非常麻烦:
provide 和 inject 可以帮助我们解决这一问题。一个父组件相对于其所有的后代组件,会作为依赖提供者。任何后代的组件树,无论层级有多深,都可以注入由父组件提供给整条链路的依赖
案例
<template>
<h1>SOLRJ</h1>
<button @click="changeSlogan">改变slogan</button>
<button @click="changeObj">改变Obj</button>
<div v-text="slogan"></div>
<div v-text="obj.slogan"></div>
<LrjM></LrjM>
</template>
<script>
import LrjM from "@/components/chao07/LrjM";
export default {
name: "SOLRJ",
components: {
LrjM
},
data() {
return {
slogan: '她说彩礼八十万',
obj: {
slogan: '她说彩礼八十万'
}
}
},
// provide:{
// slogan: '她说彩礼八十万'
// }
provide() {
return {
//使用函数的形式可以访问this
slogan: '她说彩礼八十万',
obj: this.obj,
msg: () => {
return this.slogan;
}
}
}, methods: {
changeSlogan() {
this.slogan = '孤独患者请自愈'
},
changeObj() {
this.obj.slogan = '孤独患者请自愈'
}
}
}
</script>
<template>
<h1>LrjM</h1>
<LrjN></LrjN>
<hr>
<LrjN2></LrjN2>
</template>
<script>
import LrjN from "@/components/chao07/LrjN";
import LrjN2 from "@/components/chao07/LrjN2";
export default {
name: "LrjM",
components: {
LrjN,LrjN2
}
}
方式一
<template>
<h1>LrjN</h1>
<div v-text="slo"></div>
<div v-text="person.slogan"></div>
<div v-text="getMsg"></div>
</template>
<script>
export default {
name: "LrjN",
inject:['slogan','obj','msg'],
computed:{
slo(){
return this.slogan
},
person(){
return this.obj
},
getMsg(){
return this.msg();
}
}
}
</script>
方式二
<template>
<h1>LrjN2</h1>
<div v-text="slo"></div>
<div v-text="person.slogan"></div>
<div v-text="getMsg"></div>
</template>
<script>
export default {
name: "LrjN2",
// inject:['slogan','obj','msg'],
//对象方式注入inject
inject: {
slogan: {
from: 'slogan',
default: ''
},
obj: {
from: 'obj',
default: {}
},
msg: {
from: 'msg',
default: () => {
return ''
}
}
},
computed: {
slo() {
return this.slogan
},
person() {
return this.obj
},
getMsg() {
return this.msg();
}
}
}
</script>
vue动画基础
入门案例
实现鼠标悬停div旋转,鼠标离开div恢复
<template>
<div id="box" :class="{me:isMe}" @mouseenter="isMe=!isMe" @mouseleave="isMe=!isMe"></div>
</template>
<script>
export default {
name: "LrjA",
data() {
return {
isMe: false
}
}
}
</script>
<style scoped>
#box {
width: 450px;
height: 450px;
background-color: #00aa00;
position: absolute;
top: 100px;
left: 100px;
transition: 500ms;
}
.me {
transform: rotate(45deg);
}
</style>
transtion基本使用
给transtion绑定name属性,绑定的css样式都使用name做前缀
<template>
<button @click="isShow=!isShow">显示|隐藏</button>
<transition name="lrj">
<div class="box" :class="{me:isMe}" @mouseenter="isMe=!isMe" @mouseleave="isMe=!isMe" v-show="isShow"></div>
</transition>
</template>
<script>
export default {
name: "LrjA",
data() {
return {
isMe: false,
isShow:true
}
}
}
</script>
<style scoped>
.box {
width: 450px;
height: 450px;
background-color: #00aa00;
position: absolute;
top: 100px;
left: 100px;
transition: 500ms;
}
.me {
transform: rotate(45deg);
}
/*进入前*/
.lrj-enter-from{
width: 0px;
height: 0px;
}
/*进入中*/
.lrj-enter-active{
transition: 3s all ease;
}
/*进入完成*/
.lrj-enter-to{
width: 450px;
height: 450px;
}
/*离开之前*/
.lrj-leave-form{
width: 450px;
height: 450px;
}
/*离开中*/
.lrj-leave-active{
transition: 3s all ease;
}
/*离开完成*/
.lrj-leave-to{
width: 0px;
height: 0px;
}
</style>
transtion自定义类名
<template>
<button @click="isShow=!isShow">显示|隐藏</button>
<transition name="lrj"
enter-from-class="enter-from"
enter-active-class="enter-active"
enter-to-class="enter-to"
leave-from-class="leave-from"
leave-active-class="leave-active"
leave-to-class="leave-to">
<div class="box" :class="{me:isMe}" @mouseenter="isMe=!isMe" @mouseleave="isMe=!isMe" v-show="isShow"></div>
</transition>
</template>
<script>
export default {
name: "LrjA",
data() {
return {
isMe: false,
isShow: true
}
}
}
</script>
<style scoped>
.box {
width: 450px;
height: 450px;
background-color: #00aa00;
position: absolute;
top: 100px;
left: 100px;
transition: 500ms;
}
.me {
transform: rotate(45deg);
}
/*进入前*/
.enter-from {
width: 0px;
height: 0px;
}
/*进入中*/
.enter-active {
transition: 3s all ease;
}
/*进入完成*/
.enter-to {
width: 450px;
height: 450px;
}
/*离开之前*/
.leave-form {
width: 450px;
height: 450px;
}
/*离开中*/
.leave-active {
transition: 3s all ease;
}
/*离开完成*/
.leave-to {
width: 0px;
height: 0px;
}
</style>
transtion生命周期函数
<transition name="lrj"
enter-from-class="enter-from"
enter-active-class="enter-active"
enter-to-class="enter-to"
leave-from-class="leave-from"
leave-active-class="leave-active"
leave-to-class="leave-to"
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
@before-leave="beforeLeave"
@leave="leave"
@after-leave="afterLeave"
:duration="{enter:5000,leave:5000}"
:css="true">
进入前 @before-enter @before-leave=“beforeLeave” 离开前
进入中 @enter=“enter” @leave=“leave” 离开中
进入后 @after-enter=“afterEnter” @after-leave=“afterLeave” 离开后
参数
:duration = {enter:进入时延(毫秒数),leave:离开时延(毫秒数)}
:css = {boolean值} 是否启动css样式
enter(element,done) {
//element调用函数的对象
//done是一个函数 可以在函数中延时调用函数
console.log(element)
setTimeout(()=>{
done();
},5000);
}
leave(element,done) {
console.log(element)
setTimeout(()=>{
done();
},5000);
}
transtion初始化过渡
<transition name="lrj"
appear
appear-class="appear-from"
appear-active-class="appear-active"
appear-to-class="appear-to"
>
<div class="box" :class="{me:isMe}" @mouseenter="isMe=!isMe" @mouseleave="isMe=!isMe" v-show="isShow"></div>
</transition>
transtion多元素渲染
默认不允许多元素渲染
<template>
<button @click="isShow=!isShow">显示|隐藏</button>
<div v-text="info"></div>
<transition name="lrj"
appear
appear-class="appear-from"
appear-active-class="appear-active"
appear-to-class="appear-to"
enter-from-class="enter-from"
enter-active-class="enter-active"
enter-to-class="enter-to"
leave-from-class="leave-from"
leave-active-class="leave-active"
leave-to-class="leave-to"
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
@before-leave="beforeLeave"
@leave="leave"
@after-leave="afterLeave"
:duration="{enter:5000,leave:5000}"
:css="true">
<div class="box a" :class="{me:isMe}" @mouseenter="isMe=!isMe" @mouseleave="isMe=!isMe" v-if="isShow"></div>
<div class="box b" :class="{me:isMe}" @mouseenter="isMe=!isMe" @mouseleave="isMe=!isMe" v-else></div>
</transition>
v-if 两个div只会渲染一个
transition过度模式
<button class="box" style="background-color: #4365c3" type="button" @click="toggle">状态切换</button>
<transition
mode="out-in"
enter-from-class="enter-from"
leave-to-class="leave-to"
>
<div class="box on" v-if="isShow">设备开机</div>
<div class="box off" v-else>设备关机</div>
</transition>
</template>
<script>
export default {
name: "HelloLrj",
data() {
return {
isShow: true
}
}, methods: {
toggle() {
this.isShow = !this.isShow
}
}
}
</script>
过度模式设置 mode 两个值:1.in-out 先进后厨
2.out-in 先出后进
transition多组件过度
默认不允许多组件渲染,使用v-if v-else 来控制 之渲染一个
<template>
<button @click="toggle" type="button">更改状态</button>
<transition
mode="out-in"
enter-from-class="enter-from"
leave-to-class="leave-to">
<LrjOn ref="lrjOn" v-if="isOn"></LrjOn>
<LrjOff ref="lrjOff" v-else></LrjOff>
</transition>
</template>
<script>
import LrjOn from "@/components/chao09/LrjOn";
import LrjOff from "@/components/chao09/LrjOff";
export default {
name: "HelloLrj",
components: {
LrjOn,
LrjOff
},
data() {
return {
isOn: true,
}
}, methods: {
toggle() {
this.isOn = !this.isOn
}
}
}
</script>
<template>
<div class="box on">设备开机</div>
</template>
<script>
export default {
name: "LrjOn"
}
</script>
<template>
<div class="box off">设备关机</div>
</template>
<script>
export default {
name: "LrjOff"
}
</script>
transition-group
案例
随机添加删除
<template>
<button @click="add">添加</button>
<button @click="del">删除</button>
<transition-group
enter-active-class="animate__animated animate__zoomInDown"
leave-active-class="animate__animated animate__zoomOutUp">
<div class="lrj" v-for="num in nums" :key="num" v-text="num"></div>
</transition-group>
</template>
<script>
export default {
name: "LrjA",
data() {
return {
nums: [1, 2, 4, 5, 6, 7, 8, 9],
//参考值
reference: 10,
}
}, methods: {
add() {
//向下取整
this.nums.splice(Math.floor(Math.random() * this.nums.length), 0, this.reference++)
},
del() {
//向下取整
this.nums.splice(Math.floor(Math.random() * this.nums.length), 1)
}
}
}
</script>
<style scoped>
button {
width: 200px;
height: 200px;
font-size: 66px;
}
.lrj {
float: left;
margin-top: 115px;
margin-left: 15px;
width: 60px;
height: 60px;
text-align: center;
line-height: 60px;
background-color: #123456;
color: #ffffff;
}
</style>
如何在vue中使用animate.css
- 安装animate.css
npm install animate.css --save
- 在main.js中引入animate.css
import ‘animate.css’
案例
<template>
<button type="button" @click="isShow=!isShow">显示隐藏</button>
<transition
enter-active-class="animate__animated animate__rollIn"
leave-active-class="animate__animated animate__rollOut">
<div class="lrj" v-if="isShow"></div>
</transition>
</template>
<script>
export default {
name: "LrjAnimate",
data() {
return {
isShow: true
}
},
}
</script>
<style scoped>
.lrj {
width: 600px;
height: 600px;
background-color: #00aa00;
}
button {
width: 300px;
height: 300px;
font-size: 66px;
}
</style>
如何在vue中使用gsap
- 安装gsap
终端输入
npm install gsap --save
案例
<template>
<button type="button" @click="isShow=!isShow">显示隐藏</button>
<transition @enter="fromTo" @leave="to" :duration="{enter:3000,leave:3000}">
<div v-if="isShow"></div>
</transition>
</template>
<script>
//引入gsap函数
import {gsap} from "gsap";
export default {
name: "LrjGsap",
data() {
return {
isShow: false
}
}, methods: {
from(element) {
//第一个参数是要操作的dom元素、
//第二个参数是动画的参数属性
gsap.from(element, {
x: 300,
backgroundColor: '#ff0000',
duration: 3
})
}, to(element) {
gsap.to(element, {
x: 300,
backgroundColor: '#ff0000',
duration: 3
})
}, fromTo(element) {
第一个参数是要操作的dom元素、
//第二,三个参数是进入/离开动画的参数属性
gsap.fromTo(element, {
x: 300,
backgroundColor: '#ff0000',
duration: 3,
width: 100,
height: 100
}, {
x: 600,
backgroundColor: '#00ffff',
duration: 3,
width: 300,
height: 300
})
}
}
}
</script>
<style scoped>
.lrj {
width: 300px;
height: 300px;
background-color: #00aa00;
}
</style>
gsap在vue中的基本应用
<template>
<button @click="add">添加</button>
<button @click="del">删除</button>
<transition-group
@enter="enter"
@leave="leave" :duration="{enter:1000,leave:1000}">
<div class="lrj" v-for="num in nums" :key="num" v-text="num"></div>
</transition-group>
</template>
<script>
import {gsap} from "gsap";
export default {
name: "LrjA",
data() {
return {
nums: [1, 2, 4, 5, 6, 7, 8, 9],
//参考值
reference: 10,
}
}, methods: {
add() {
//向下取整
this.nums.splice(Math.floor(Math.random() * this.nums.length), 0, this.reference++)
},
del() {
//向下取整
this.nums.splice(Math.floor(Math.random() * this.nums.length), 1)
},
enter(el) {
gsap.from(el, {
width: 0,
height: 0,
fontSize: 0,
duration: 1
})
},
leave(el){
gsap.to(el,{
width: 0,
height: 0,
fontSize: 0,
duration: 1
})
}
}
}
</script>
<style scoped>
button {
width: 200px;
height: 200px;
font-size: 66px;
}
.lrj {
float: left;
margin-top: 115px;
margin-left: 15px;
width: 60px;
height: 60px;
text-align: center;
line-height: 60px;
background-color: #123456;
color: #ffffff;
}
</style>
veu中gsap综合案例
<template>
<div class="main">
<div class="box" ref="box" v-for="n in count" :key="n"></div>
</div>
</template>
<script>
import {gsap} from "gsap";
export default {
name: "LrjC",
data() {
return {
count: 170
}
},
mounted() {
let box = this.$refs['box'];
gsap.to(box, {
//缩放为0.1
scale: 0.1,
y: 60,
yoyo: true,//如果该值为true,则每隔一次重复补间将朝相反的方向运行。(像溜溜球一样)默认false,
repeat :-1 ,//数值是几重复几次 0 不重复 1 一次 -1 一直重复,
delay: 1, //延迟多长时间执行 (在这个案例为1秒)
//每个目标动画开始之间的事件(以秒为单位)(如果提供了多个目标)
stagger: {
amount: 1.5,//补的时间差
grid:"auto",//运动的方式
from:"center"//(中心)从那开始运动
}
})
}
}
</script>
<style scoped>
html,
body{
height: 100%;
}
body{
background-color: #1d1d1d;
font-family: "Signika Negative",sans-serif;
color: #989898;
margin: 0 10px;
font-size: 17px;
text-align: center;
}
#app{
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
.main{
max-width: 1200px;
height: 100%;
position: relative;
display: inline-block;
}
.box{
width: 50px;
height: 50px;
position: relative;
border-radius: 0px;
margin-top: 4px;
display: inline-block;
margin: 0px 1.5% 11.5% 0px;
background-color: #6fb936;
}
</style>
Vite 下一代的前端工具链 为开发提供极速响应
搭建第一个Vite项目
兼容性注意
Vite 需要 Node.js 版本 14.18+,16+。然而,有些模板需要依赖更高的 Node 版本才能正常运行,当你的包管理器发出警告时,请注意升级你的 Node 版本。
使用nmp搭建
npm create vite@latest+ 项目名称
选择Vue 按enter键
选择语言 JavaScript 按enter键
根据提示 一步步操作
cd mtVue-vite 进入项目
npm install 下载安装依赖
npm run dev 运行项目
http://127.0.0.1:5173/ 访问
WebStrom配置Vite项目
- WebStrom 打开一个Vite
- 配置npm 脚本输入 dev
vite项目引入子组件
- 定义子组件
<template>
<H1>孤独患者请自愈</H1>
</template>
<script>
export default {
name: "LrjA"
}
</script>
<style scoped>
</style>
- 引入子组件
import LrjA from "./components/LrjA.vue";
</script>
<template>
<LrjA></LrjA>
</template>
setup函数
<template>
<H1>孤独患者请自愈</H1>
<h1 v-text="dataSlogan"></h1>
<button type="button" @click="changeDataSlogan">改变dataSlogan</button>
</template>
<script>
export default {
name: "LrjA",
data() {
return {
dataSlogan: 'dataSlogan'
}
}, methods: {
changeDataSlogan() {
this.dataSlogan = 'newDataSlogan'
}
}
}
</script>
<style scoped>
</style>
<template>
<H1>孤独患者请自愈</H1>
<h1 v-text="setupSlogan"></h1>
<button type="button" @click="changeSetupSlogan">改变setupSlogan</button>
</template>
<script>
import {ref} from "vue";
export default {
name: "LrjA",
setup() {
const setupSlogan = ref('setupSlogan') //此时setupSlogan是一个对象
const changeSetupSlogan = () => {
setupSlogan.value = 'newSetSlogan' //为对象的value赋值
}
return { //返回对象
setupSlogan,
changeSetupSlogan
}
}
}
</script>
<style scoped>
</style>
引用类型操作
setup操作引用类型
<template>
<H1>孤独患者请自愈</H1>
<h1 v-text="obj.name"></h1>
<h1 v-text="obj.slogan"></h1>
<button type="button" @click="changeObj">改变Obj</button>
</template>
<script>
//导入ref组件
import {ref} from "vue";
export default {
name: "LrjA",
setup() {
const obj = ref({
name: '烟雨过客',
slogan: '她说彩礼八十万'
})
const changeObj = () => {
obj.value.name = '天下无双'
obj.value.slogan = '只是过往,是过往'
}
return { //返回对象
obj,
changeObj
}
}
}
</script>
<style scoped>
</style>
recative操作应用类型
<template>
<H1>孤独患者请自愈</H1>
<h1 v-text="obj.name"></h1>
<h1 v-text="obj.slogan"></h1>
<button type="button" @click="changeObj">改变Obj</button>
</template>
<script>
//导入ref和recative组件
import {ref,reactive} from "vue";
export default {
name: "LrjA",
setup() {
const obj = reactive({
name: '烟雨过客',
slogan: '她说彩礼八十万'
})
const changeObj = () => {
obj.name = '天下无双'
obj.slogan = '只是过往,是过往'
}
return { //返回对象
obj,
changeObj
}
}
}
</script>
setup函数的props传值
第一种方法 setup利用props传值
<template>
<LrjC :msg="msg" :person="person"></LrjC>
</template>
<script>
import {ref, reactive} from "vue";
import LrjC from "./LrjC.vue";
export default {
name: "LrjB",
components:{
LrjC
},
setup() {
const msg = ref('我爱你')
const person = reactive({
raleName: 'AJIE',
slogan: '残情'
})
return{
msg,person
}
}
}
</script>
<style scoped>
</style>
<template>
<h1 v-text="msg"></h1>
<h1 v-text="person.slogan"></h1>
<h1 v-text="person.raleName"></h1>
</template>
<script>
export default {
name: "LrjC",
props: ['msg', 'person'],
setup(props) {
console.log(props.msg)
console.log(props.person.slogan)
console.log(props.person.raleName)
}
}
</script>
<style scoped>
</style>
第二种 setup函数利用defineProps传值
<template>
<LrjC :msg="msg" :person="person"></LrjC>
</template>
<script setup>
import LrjC from "./LrjC.vue";
const msg = '我爱你'
const person = {
raleName: 'AJIE',
slogan: '残情'
}
</script>
<script>
export default {
name: "LrjB",
}
</script>
<style scoped>
</style>
<template>
<h1 v-text="msg"></h1>
<h1 v-text="person.slogan"></h1>
<h1 v-text="person.raleName"></h1>
</template>
<script setup>
defineProps(['msg','person'])
</script>
<script>
export default {
name: "LrjC",
}
</script>
<style scoped>
</style>
setup函数context_attrs传值
<template>
<LrjC :msg="msg" :person="person"></LrjC>
</template>
<script>
import {ref, reactive} from "vue";
import LrjC from "./LrjC.vue";
export default {
name: "LrjB",
components:{
LrjC
},
setup() {
const msg = ref('我爱你')
const person = reactive({
raleName: 'AJIE',
slogan: '残情'
})
return{
msg,person
}
}
}
</script>
<style scoped>
</style>
<template>
<h1 v-text="attrs.msg"></h1>
<h1 v-text="attrs.person.slogan"></h1>
<h1 v-text="attrs.person.raleName"></h1>
</template>
<script>
export default {
name: "LrjC",
// props: ['msg', 'person'],
setup(props,context) {
// console.log(context.attrs)
//解构赋值的方式取值
let {attrs} = context;
return{
attrs
}
}
}
</script>
<style scoped>
</style>
setup函数 context_emit 传值
<template>
<h1 v-text="attrs.msg"></h1>
<h1 v-text="attrs.person.slogan"></h1>
<h1 v-text="attrs.person.raleName"></h1>
<button type="button" @click="updateName">子组件传值</button>
</template>
<script>
import {ref} from "vue";
export default {
name: "LrjC",
// props: ['msg', 'person'],
setup(props,context) {
// console.log(context.attrs)
//解构赋值的方式取值
let {attrs,emit} = context;
const myName = ref('老K')
const updateName = function () {
emit('updateName',myName)
}
return{
attrs,updateName
}
}
}
</script>
<style scoped>
</style>
子组件点击按钮调用自定义方法,父组件捕获动作,调用父组件自定义方法 ,将传过来的参数赋值给父组件属性
<template>
<LrjC :msg="msg" :person="person" @updateName="updateName"></LrjC>
</template>
<script>
import {ref, reactive} from "vue";
import LrjC from "./LrjC.vue";
export default {
name: "LrjB",
components:{
LrjC
},
setup() {
const msg = ref('我爱你')
const person = reactive({
raleName: 'AJIE',
slogan: '残情'
})
const updateName = function (value){
person.raleName=value;
}
return{
msg,person,updateName
}
}
}
</script>
<style scoped>
</style>
setup函数 defineEmits 传值
<template>
<h1 v-text="msg"></h1>
<h1 v-text="person.raleName"></h1>
<h1 v-text="person.slogan"></h1>
<button type="button" @click="updateName">点击改变</button>
</template>
<script setup>
import {ref} from "vue";
defineProps(['msg','person']);
//自定义发送动作
const emit = defineEmits(['update']);
//自定义发送参数
const myName = ref('老K')
const updateName=function (){
//发射自定义动作,并携带参数
emit('update',myName)
}
</script>
<script>
export default {
name: "LrjE",
}
</script>
<style scoped>
</style>
执行的操作:子组件点击事件调用自定义方法,自定义方法将自定义动作并携带发射给父组件,父组件捕获自定义动作,并调用自身方法,将发射过来的参数,赋值给父组件属性
<template>
<h1 v-text="person.raleName"></h1>
<LrjE :msg="msg" :person="person" @update="updateName"></LrjE>
</template>
<script setup>
import {ref,reactive} from "vue";
import LrjE from "./LrjE.vue";
const msg = ref('我爱你')
const person = reactive({
raleName: 'AJIE',
slogan: '残情'
})
const updateName=function (value){
person.raleName=value
}
</script>
<script>
export default {
name: "LrjD",
}
</script>
<style scoped>
</style>
setup函数context_slots插槽传值
<template>
<h1 v-text="slogan"></h1>
<LrjG>
<template #lrjAA>
<h1>lrj-aa</h1>
</template>
<template #lrjBB>
<h1>lrj-bb</h1>
</template>
<template #lrjCC>
<h1 v-text="slogan"></h1>
</template>
</LrjG>
<button type="button" @click="changeSlogan">改变slogan</button>
</template>
<script>
import LrjG from "./LrjG.vue";
import {ref} from "vue";
export default {
name: "LrjF",
setup(){
const slogan = ref('孤独患者请自愈');
const changeSlogan = function (){
this.slogan='她说彩礼八十万'
}
return{
slogan,changeSlogan
}
},components:{
LrjG
}
}
</script>
<style scoped>
</style>
<template>
<h1>LrjG</h1>
<slot name="lrjAA"></slot>
<slot name="lrjBB"></slot>
<slot name="lrjCC"></slot>
</template>
<script>
import {ref} from "vue";
export default {
name: "LrjG",
setup(props,context){
const {slots}=context;
//用函数的方式取slots
//以下表的方式将内容取出
// console.log(slots.lrjAA()[0].children)
console.log(slots.lrjBB()[0].children)
//修改slots.lrjBB()[0].children的值
slots.lrjBB()[0].children='烟雨过客'
console.log(slots.lrjBB()[0].children)
}
}
</script>
<style scoped>
</style>
父组件属性值修改 context_slots插槽传的值也会修改