vue(李仁杰)

什么是 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”
事件处理器的值可以是:

  1. 内联事件处理器:事件被触发时执行的内联 JavaScript 语句 (与 onclick 类似)。
  2. 方法事件处理器:一个指向组件上定义的方法的属性名或是路径。

事件处理

常用:
:::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 用法提供了特殊的功能增强。除了字符串外,表达式的值也可以是对象或数组。

  1. 绑定对象绑定对象

我们可以给 :class (v-bind:class 的缩写) 传递一个对象来动态切换 class:

 <div :class="{ active: isActive }"></div>

上面的语法表示 active 是否存在取决于数据属性 isActive 的真假值

  1. 绑定数组

我们可以给 :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 搭配使用。
注意:

  1. v-show 控制css样式是否displat
  2. 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 划分为独立的、可重用的部分,并且可以对每个部分进行单独的思考。在实际应用中,组件常常被组织成层层嵌套的树状结构:
image.png
这和我们嵌套 HTML 元素的方式类似,Vue 实现了自己的组件模型,使我们可以在每个组件内封装自定义内容与逻辑。Vue 同样也能很好地配合原生 Web Component

1. 如何导入组件

  1. 定义组件
<template>
 <h1 v-text="slogan"></h1>
</template>
<script>
 export default {
 name: "Demo",
 data(){
 return{
 slogan:'孤独患者请自愈'
 }
 },
 }
</script>
  1. 引入组件
<template>
 <Demo></Demo>
</template>
<script>
 //引⼊组件
 import Demo from "@/components/demo/Demo";
 export default {
 name: 'App',
 components:{
 Demo
 }
 }
</script>

组件传值

父传子

  1. 在⽗组件定义⼀个值
<Demo msg="她说彩礼⼋⼗万"></Demo>
  1. 接收值
props:{
  msg:{
    type:String,
      //必须接收值
      request:true,
      //没有值的情况下 设置默认值
      default:'她说彩礼八十万'
  }
}

子传父

  1. 定义⼀个⼦组件
<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>

  1. 接收
<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

  1. 安装animate.css

npm install animate.css --save

  1. 在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

  1. 安装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键

img

选择语言 JavaScript 按enter键

img

根据提示 一步步操作

img

cd mtVue-vite 进入项目

npm install 下载安装依赖

npm run dev 运行项目

http://127.0.0.1:5173/ 访问

WebStrom配置Vite项目

  1. WebStrom 打开一个Vite
  2. 配置npm 脚本输入 dev

img

vite项目引入子组件

  1. 定义子组件
<template>
  <H1>孤独患者请自愈</H1>
</template>

<script>
  export default {
    name: "LrjA"
  }
</script>

<style scoped>

</style>
  1. 引入子组件
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插槽传的值也会修改

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值