Vue基础4

动态组件

`:is 用于绑定动态组件`
被传给 :is 的值可以是以下几种:
    被注册的组件名
    导入的组件对象

<component :is="name"></component>
// 点击按钮切换组件
<button @click="names='ChildA'">按钮</button>
data() {
      return {
        //name: "ChildA",
        name: "ChildB",
      }
//给组件设置了一个名字,通过更改名字中的组件名,实现动态组件
    //name 中是ChildA 则上面就是ChildA  反之是ChildB
    


KeepAlive组件

1.一般组件在动态改变时,会被销毁
使用<KeepAlive> 包裹动态组件时,这个组件在改变后不会销毁,会被放在缓存中,再次切换回来的时候数据仍然存在

`任何时候都只能有一个活跃组件实例作为 <KeepAlive> 的直接子节点`

2.KeepAlive 起作用的前提,动态载入的子组件必须有name,否则不会缓存

3.<KeepAlive> 中只能写入<component>

4.activated 进入时激活	deactivated 离开时失活
//当进入该组件时就会执行activated
//当离开该组件时就会执行deactivated 执行下一个进入的组件的activated

5.当一个组件在 <KeepAlive> 中被切换时,它的 activated 和 deactivated 生命周期钩子将被调用,用来替代 mounted 和 unmounted

<div>
    <KeepAlive>
       <component :is="names">{{ content }}</component>
    </KeepAlive>
</div>

6.使用include/exclude(不包含)可以设置哪些组件被缓存,使用 max可以设定最多缓存多少个
    1)include 可以使用字符串,正则表达式,数组
    2)如果是字符串 include  如果是正则或者数组 :include

    //设置只有ChildA和ChildC可以被缓存
<KeepAlive :include="['ChildA', 'ChildC']">
        <component :is="names">{{ content }}</component>
</KeepAlive>

7.`<component>用于渲染动态组件或元素的“元组件”`
	//这样会在页面中放入一个 div标签
 <component :is="'div'"></component>

8.可以使用vue的组件替换当前原生的html标签
	//把div 渲染成立 ChildA组件
<div is="vue:ChildA"></div>

切换案例

//父组件
<template>
  <div>
    <!-- <ul class="clear"> -->
    //<!-- 通过 v-for 遍历list 把 name做为内容 -->
    //<!-- 通过点击动态设置组件名 跳转到不同的组件 -->
     <li v-for="item in list" :key="item.id" :class="item.name === content ? 'select-tab' : ''" @click="names = item.tab, content = item.name">{{ item.name }}</li>
    </ul>
    <div>
      <KeepAlive :include="['ChildA', 'ChildC']">
        <component :is="names">{{ content }}</component>
      </KeepAlive> 
    <!-- </div> -->
  </div>
</template>
<script>
import ChildA from "@/components/dynamicComponent/ChildA.vue"
import ChildB from "@/components/dynamicComponent/ChildB.vue"
import ChildC from "@/components/dynamicComponent/ChildC.vue"

export default {
  name: 'DynamicComponent',
  components: {
    ChildA,
    ChildB,
    ChildC
  },
  data() {
    return {
      names: "ChildA",
      content: "水果",
      list: [
        { id: 1001, name: "水果", tab: "ChildA" },
        { id: 1002, name: "蔬菜", tab: "ChildB" },
        { id: 1003, name: "粮油", tab: "ChildC" },
      ]
    }
  }
}
</script>

<style>
ul {
  list-style: none;
  margin: 0;
  padding: 0;
}
li {
  float: left;
  padding: 5px 20px;
  border: 1px solid #000;
  border-left: none;
}
li:first-child {
  border-left: 1px solid #000;
}
.clear::after {
  content: "";
  display: block;
  height: 0;
  visibility: hidden;
  clear: both;
}
.select-tab {
  background-color: orange;
}
</style>

// 三个子组件
<template>
  <div>
    A 上次停留的时间:{{this.time }}
    <hr />
    <slot name="default"></slot>
    <hr />
    {{ count }}
    <button @click="count++">按钮</button>
  </div>
</template>
<script>
export default {
  name: "ChildA",
  data() {
    return {
      count: 1,
      time: 0,
      date: 0
    }
  },
  activated() {
    console.log("A进入时,激活")
    this.date = Date.now();
  },
  deactivated() {
    console.log("A离开时,失活")
    this.time = Date.now() - this.date + this.time;
    this.date = null
  }
}
</script>


<template>
  <div>
    B
    <hr />
    <slot name="default"></slot>
    <hr />
    {{ count }}
    <button @click="count++">按钮</button>
  </div>
</template>

<script>
export default {
  name: "ChildB",
  data() {
    return {
      count: 1
    }
  },
  activated() {
    console.log("B进入时,激活")
  },
  deactivated() {
    console.log("B离开时,失活")
  }
}
</script>


<template>
  <div>
    C
    <hr />
    <slot name="default"></slot>
    <hr />
    {{ count }}
    <button @click="count++">按钮</button>
  </div>
</template>

<script>
export default {
  name: "ChildC",
  data() {
    return {
      count: 1
    }
  },
  activated() {
    console.log("C进入时,激活")
  },
  deactivated() {
    console.log("C离开时,失活")
  }
}
</script>

异步组件

异步组件-->用到时再加载,尤其针对首页和部分主页面
// 组件名:() => import()  加载函数		异步要搭配这个使用
// 其中import 是一个promise类型

`标准写法`
<template>
  <div>
    <ChildA/>
  </div>
</template>

<script>
//异步组件的引入
import { defineAsyncComponent } from "vue";

export default {
  name: "AsyncComponent",
  //异步组件的注册
  components: {
    ChildA: defineAsyncComponent({
      loader: () => import("@/components/asyncComponent/ChildA.vue")
    })
  }
}
</script>


`<Suspense>组件`
是一个内置组件,让我们可以在组件树上层等待下层的多个嵌套异步依赖项解析完成,并可以在等待时渲染一个加载状态
// 使用
<Suspense>
      <ChildA />
    // 如果当前异步组件没有加载完成,就会显示下面template中的内容
    // #fallback 是固定的
      <template #fallback>
        加载中...
      </template>
</Suspense>

自定义指令

1.自定义的指令要放在directives中使用
2.在directives当中设置的指令属性名,在标签中必须使用v-指令名
3.自定义指令中mounted中的参数
		1)第一个参数 el就是真实的DOM,是被设置当前指令的元素
		2)第二个参数的 $.instance 当前组件的实例化,可以调用data中的属性
		3)第三个参数 vNode 就是虚拟DOM

<template>
  <div>
    //<!-- 给div设置一个自定义指令叫做 color -->
    <div v-color="'green'">阿边</div>
  </div>
</template>

<script>
import ChildA from "@/components/commandView/ChildA.vue"

export default {
  name: "CommandView",
  components: {
    ChildA
  },
  data() {
    return {
      count: 1
    }
  },
  `directives`: {
    color: {
      mounted(el, $, vNode) {
        // 第一个参数el就是真实的DOM,是被设置当前指令的元素
        console.log(el)

        // $.instance 当前组件的实例化,可以调用data中的属性
        console.log($.instance)

        console.log($.instance.count)//1

        // vNode 就是虚拟DOM
        // 第二个参数的value就是这个指令给的值
        // 这样可以在上面任意写入值
        el.style.color=$.value
      }
    }
  }
}
</script>

案例 验证号码

<template>
  <div>
    // <!-- 设置一个自定义指令叫做 tel -->
    // <!-- v-tel.cn 设置不同的地区 -->
    // v-tel 是自定义的指令
    <input type="text" v-model="tel" v-tel.cn>
  </div>
</template>
<script>
import ChildA from "@/components/commandView/ChildA.vue"
export default {
  name: "CommandView",
  components: {
    ChildA
  },
  data() {
    return {
      count: 1,
      tel: ""
    }
  },
  directives: {
    tel: {
      updated(el, $) {
        console.log($.modifiers)//指令后面的 .的内容
        var header = "";
        // 当$.modifiers.cn为真 且不是+086开头时 进入
        if ($.modifiers.cn && !/^\+086/.test($.instance.tel)) {
          // 设置中国地区正确的电话号码
          $.instance.tel = "+086" + $.instance.tel;
          header = "^\\+086";
        } else if ($.modifiers.hk && !/^\+00852/.test($.instance.tel)) {
          // 设置香港地区正确的电话号码
          $.instance.tel = "+00852" + $.instance.tel;
          header = "^\\+00852";
        }
        //  判断电话号码是否正确 通过颜色进行提示
        if (new RegExp(header + "1[3-9]\\d{9}$").test($.instance.tel)) {
          el.style.color = "green"
        } else {
          el.style.color = "red"
        }}}}}
</script>

全局注册指令

指令中的内容放在单独放在一个文件夹下 引入到main.js中进行使用

vue1

vue3过渡效果和传送门

<Transition> 它可以将进入和离开动画应用到通过默认插槽传递给它的元素或组
<Transition> 仅支持单个元素或组件作为其插槽内容。如果内容是一个组件,这个组件必须仅有一个根元素
//进入或离开可以由以下的条件之一触发
● 由 v-if 所触发的切换
● 由 v-show 所触发的切换
● 由特殊元素 <component> 切换的动态组件


` CSS 过渡`
1. v-enter-from:进入动画的起始状态。在元素插入之前添加,在元素插入完成后的下一帧移除。

2. v-enter-active:进入动画的生效状态。应用于整个进入动画阶段。在元素被插入之前添加,在过渡或动画完成之后移除。这个 class 可以被用来定义进入动画的持续时间、延迟与速度曲线类型。
    
3. v-enter-to:进入动画的结束状态。在元素插入完成后的下一帧被添加 (也就是 v-enter-from 被移除的同时),在过渡或动画完成之后移除。
4. v-leave-from:离开动画的起始状态。在离开过渡效果被触发时立即添加,在一帧后被移除。

5. v-leave-active:离开动画的生效状态。应用于整个离开动画阶段。在离开过渡效果被触发时立即添加,在过渡或动画完成之后移除。这个 class 可以被用来定义离开动画的持续时间、延迟与速度曲线类型。
    
6. v-leave-to:离开动画的结束状态。在一个离开动画被触发后的下一帧被添加 (也就是 v-leave-from 被移除的同时),在过渡或动画完成之后移除


`为过渡效果命名`
<Transition name="fade">
      <!-- <p v-if="show">这个文本需要动画</p> -->
      <div v-if="show" class="div1">显示的容器</div>
</Transition>

//下面的更改为  把其中的 v 换成起的名字
.fade-enter-from,
.fade-leave-to {
    opacity: 0;
    transform: translate(-50%, -300px);
    transition: all 0.5s cubic-bezier(0,.41,1,-0.36);
}
.fade-enter-to,.fade-leave-from {
    opacity: 1;
    transform: translate(-50%, 0);
    transition: all 0.5s cubic-bezier(0,.41,1,-0.36);
}

案例 div动画显示

<template>
  <div>
    <button @click="show = !show">按钮</button>
    <Transition>
      <!-- <p v-if="show">这个文本需要动画</p> -->
      <div v-if="show" class="div1">显示的容器</div>
    </Transition>
  </div>
</template>

<script>
import ModelView from "@/components/transitionView/ModalView.vue"

export default {
  name: "TransitionView",
  data() {
    return {
      show: false,
    }
  }
}
</script>

<style>
.div1 {
  width: 500px;
  height: 300px;
  border: 1px solid #000;
  background-color: tomato;
  position: fixed;
  left: 50%;
  transform: translate(-50%, 0);
}

.v-enter-from,
.v-enter-active,
.v-leave-active,
.v-leave-to {
  opacity: 0;
  transform: translate(-50%, -300px);
  transition: all 1s;
}

.v-enter-to,
.v-leave-from {
  opacity: 1;
  transform: translate(-50%, 0);
  transition: all 1s;
}
</style>

Teleport传送门

是一个内置组件,它可以将一个组件内部的一部分模板“传送”到该组件的 DOM 结构外层的位置去
常用于全屏的模态窗


// <Teleport> 接收一个 to prop 来指定传送的目标。to 的值可以是一个 CSS 选择器字符串,也可以是一个 DOM 元素对象。
// 这段代码的作用就是告诉 Vue“把以下模板片段传送到 body 标签下”。
<button @click="open = true">Open Modal</button>
<Teleport to="body">
  <div v-if="open" class="modal">
    <p>Hello from the modal!</p>
    <button @click="open = false">Close</button>
  </div>
</Teleport>
`案例`

// 父组件
<template>
  <div>
    <Teleport to="body">
      <div class="mask" v-if="show" @click="show = false"></div>
      <Transition>
        <ModelView v-if="show" title="添加新用户" @close="show = false">
          <template #content>
            <label>用户名:</label> <input type="text"><br>
            <label>密码:</label> <input type="password" autocomplete>
          </template>
          <template #footer>
            <button type="submit">登录</button>
            <button type="reset">重置</button>
          </template>
        </ModelView>
      </Transition>
    </Teleport>
  </div>
  <button @click="show = true">按钮</button>
</template>

<script>
import ModelView from "@/components/transitionView/ModelView.vue"

export default {
  name: "TransitionView",
  components: {
    ModelView
  },
  data() {
    return {
      show: false,
    }
  }
}
</script>

<style>
.div1 {
  width: 500px;
  height: 300px;
  border: 1px solid #000;
  background-color: tomato;
  position: fixed;
  left: 50%;
  transform: translate(-50%, 0);
}

.v-enter-from,
/* .v-enter-active,
.v-leave-active, 
这两个中间效果可以不写
*/
.v-leave-to {
  opacity: 0;
  transform: translate(-50%, -300px);
  transition: all 0.2s cubic-bezier(0, .41, 1, -0.36);
}

.v-enter-to,
.v-leave-from {
  opacity: 1;
  transform: translate(-50%, 0);
  transition: all 0.2s cubic-bezier(0, .41, 1, -0.36);
}

.mask {
  position: absolute;
  width: 100%;
  height: 100%;
  background-image: url('/public/img/鬼灭1.webp');
  left: 0;
  top: 0;
}
</style>

// 子组件
<template>
  <div class="modal">
    <div>
      <h3>{{ title }}</h3>
      <button class="close" @click="clickhandler">&times;</button>
    </div>
    <form>
      <div class="content">
        <slot name="content"></slot>
      </div>
      <hr />
      <div class="footer">
        <slot name="footer"></slot>
      </div>
    </form>
  </div>
</template>

<script>
export default {
  name: "ModelView",
  props: ["title"],
  emits: ["close"],
  methods: {
    clickhandler() {
      this.$emit("close");
    }
  }
}
</script>

<style scoped>
.modal {
  width: 500px;
  position: absolute;
  border: 1px solid #000;
  background-color: #fff;
  left: 50%;
  transform: translate(-50%, 0);
}
.modal h3 {
  text-align: center;
}
.modal .close {
  position: absolute;
  right: 10px;
  top: 10px;
}
.modal .content {
  text-align: center;
}
.modal .footer {
  text-align: right;
}
</style>

其他函数

1.$forceUpdate()
在vue2中 对象以及数组的操作,在数据改变时,视图没有更新,使用$forceUpdate()进行强制更新视图

2.$nextTick()
用于在DOM更新之后执行延迟回调函数
它的主要作用是在当前数据变化后等待DOM更新完成,然后执行特定的操作
比如获取更新后的DOM元素或执行一些需要在DOM渲染完成后进行的操作

3.渲染函数  h()	创建虚拟DOM节点
// h(标签名,标签的标签属性,标签里的内容)
// h(标签名,标签的标签属性,[标签内子节点])
<template>
  <div>
    <ChildA />
  </div>
</template>
<script>
import { h } from "vue";
// 动态创建一个p标签
var ChildA = h("p", {}, "内容")
export default {
  name: "OtherView",
  components: {
    ChildA
  }
}
</script>

4.渲染函数mergeProps()
// 合并多个 props 对象,用于处理含有特定的 props 参数的情况
// 可以合并class、style、onXxx 事件监听器——多个同名的事件监听器将被合并到一个数组
// 当有相同的属性时,会覆盖;不同的就合并
<template>
  <div>
    <ChildA />
    {{ d }} 
    // 打印出来是
    `{ "class": "div0 div1 div2", "onClick": [ null, null ] }`
    // 把 A与B的class合并在了一起
  </div>
</template>

<script>
import { h, mergeProps } from "vue";
const A = {
  class: "div0",
  onClick: () => {
    console.log("1");
  }
}
const B = {
  class: ["div1", "div2"],
  onClick: () => {
    console.log("2");
  }
}
export default {
  name: "OtherView",
  components: {
    ChildA
  },
  data(){
    return{
        // 合并对象
      d:mergeProps(A,B)
    }
  },
  ,
  mounted() {
    console.log(this.d);
//Proxy(Object) {class: 'div0 div1 div2', onClick: Array(2)}
  }
}
</script>

5.渲染函数cloneVNode()
// 克隆一个 vnode,返回一个克隆的 vnode,可在原有基础上添加一些额外的 prop
// Vnode 被认为是一旦创建就不能修改的,你不应该修改已创建的 vnode 的 prop,而应该附带不同的或额外的 prop 来克隆它

var ChildA = h("div", {}, "内容")
var ChildB = cloneVNode(ChildA, { class: "div3" })
console.log(ChildA)
console.log(ChildB)

6.mixins 混入
允许我们在`多个组件之间共享重复的逻辑`,将公用的功能以对象的方式传入 mixins 选项中,当组件使用 mixins 对象,所有 mixins 对象的选项都将被扩展到该组件本身的选项中来,这样就可以`提高代码的重用性,并易于后期的代码维护`
<template>
  <div>
    <ChildA />
    <ChildB />
  </div>
</template>


<script>
import { cloneVNode, h, mergeProps } from "vue";
var ChildA = h("div", {}, "内容")
var ChildB = cloneVNode(ChildA, { class: "div3" })
const A1 = {
  components: {
    ChildA,
  },
  data() {
    return {
      count: 1
    }
  },
  created() {
    console.log("aa")
  }
}

const B1 = {
  components: {
    ChildB,
  },
  data() {
    return {
      sum: 2
    }
  },
  methods: {
    click() {
      console.log("NIHAO")
    }
  },
  mounted() {
    console.log("bb")
  }
}
export default {
  name: "OtherView",
  mixins: [A1, B1],
  components: {
  },
  mounted() {
   console.log(this)
      // 混入之后 可以调用A1或B1中的值或方法
   console.log(this.sum);//2
   console.log(this.count);//1
   this.click()//NIHAO
  }
}
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值