Vue3 – 高级语法补充

1 Vue中自定义指令

2 Vue内置组件Teleport

3 Vue内置组件Suspense

4 Vue中安装插件的方式

5 Vue中渲染函数的使用

6 Vue中编写jsx的语法

Vue中自定义指令

自定义指令的绑定方法有两种,一种是局部的,一种是全局的。

指令可以将部分js代码转换成指令的方式来使用,js功能的代码可以分成直接在单独页面设置使用,还可以抽取成hooks函数调用。下面这个js代码的功能是进入这个页面的时候马上获取输入框焦点。

直接在页面创建的方法:

<template>
  <div class="app">
    <!-- <input type="text" ref="inputRef"> -->
    <input type="text" v-focus>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue';
function useInput() {
  const inputRef = ref()

  onMounted(() => {
    inputRef.value?.focus()
  })
}

</script>

<style scoped>

</style>

抽取成hooks:放在了./hooks/useInput里面

import { ref, onMounted } from 'vue';

export default function useInput() {
  const inputRef = ref()

  onMounted(() => {
    inputRef.value?.focus()
  })

  return { inputRef }
}
<template>
  <div class="app">
    <input type="text" ref="inputRef"> 
  </div>
</template>

<script setup>
 1.方式一: 定义ref绑定到input中, 调用focus
 import useInput from "./hooks/useInput"
 const { inputRef } = useInput()
</script>

<style scoped>

</style>

使用指令的方式来实现上述的功能:

局部指令:可以用vue2的options api方法写,也可以是vue3的setup写法

在setup里面写指令一定要用v+大写字母才能是指令

<template>
  <div class="app">
    <!-- <input type="text" ref="inputRef"> -->
    <input type="text" v-focus>
  </div>
</template>

 <script>
  // 1.方式一:
  export default {
    directives: {
      focus: {
        // 生命周期的函数(自定义指令)
        mounted(el) {
          // console.log("v-focus应用的元素被挂载了", el)
          el?.focus()
        }
      }
    }
  }

</script> 

<script setup>


 2.方式二: 自定义指令(局部指令)这里一定要用v+大写字母才能是指令
 const vFocus = {
  // 生命周期的函数(自定义指令)
   mounted(el) {
     // console.log("v-focus应用的元素被挂载了", el)
     el?.focus()
   }
 }

</script>

<style scoped>

</style>

全局指令的使用是在main.js里面编写:

import { createApp } from 'vue'

// 自定义指令的方式一:
// const app = createApp(App)

// 全局指令1:
  app.directive("focus", {
    // 生命周期的函数(自定义指令)
    mounted(el) {
      // console.log("v-focus应用的元素被挂载了", el)
      el?.focus()
    }
  })
createApp(App).mount("#app")

注意:直接写在main。js里面会让main。js变得很庞大,我们可以抽取出来做成一个directive的文件夹2中写法:

focus.js代码:

export default function directiveFocus(app) {
  app.directive("focus", {
    // 生命周期的函数(自定义指令)
    mounted(el) {
      // console.log("v-focus应用的元素被挂载了", el)
      el?.focus()
    }
  })
}

main.js和index.js代码:

1、

index.js:

2、

index.js:

 

自定义指令有自己每个阶段的生命周期。

指令的修饰符

<template>
  <div class="app">
    <button @click="counter++">+1</button>

    <!-- 1.参数-修饰符-值 -->
    <!-- <h2 v-why:kobe.abc.cba="message">哈哈哈哈</h2> -->

    <!-- 2.价格拼接单位符号 -->
    <h2 v-unit> {
    
    { 111 }} </h2>
  </div>
</template>

<script setup>
import { ref } from 'vue';

const counter = ref(0)

const message = '你好啊, 李银河'

const vWhy = {
  mounted(el, bindings) {
    console.log(bindings)
    el.textContent = bindings.value
  }
}

</script>

<style scoped>

</style>

自定义指令小案例一

想要给数字添加对应的符号

在指令文件夹里面创建unit.js并输入

这个指令可以输入默认值,也可以直接设置用户输入的值。用户输入的时候直接在指令后面添加冒号和值。  例如:   v-unit="参数"

 在指令文件夹的入口文件添加指令

 main.js

想要使用指令的地方

自定义指令小案例二

将时间戳转换成MM-MM-DD等等的格式

<template>
  <div class="app">
    <button @click="counter++">+1</button>

    <!-- 1.参数-修饰符-值 -->
    <!-- <h2 v-why:kobe.abc.cba="message">哈哈哈哈</h2> -->

    <!-- 2.价格拼接单位符号 -->
    <h2 v-unit> {
    
    { 111 }} </h2>
  </div>
</template>

<script setup>
import { ref } from 'vue';

const counter = ref(0)

const message = '你好啊, 李银河'

const vWhy = {
  mounted(el, bindings) {
    console.log(bindings)
    el.textContent = bindings.value
  }
}

</script>

<style scoped>

</style>

ftime.js:

import dayjs from 'dayjs'

export default function directiveFtime(app) {
  app.directive("ftime", {
    mounted(el, bindings) {
      // 1.获取时间, 并且转化成毫秒
      let timestamp = el.textContent
      if (timestamp.length === 10) {
        timestamp = timestamp * 1000
      }

      timestamp = Number(timestamp)

      // 2.获取传入的参数
      let value = bindings.value
      if (!value) {
        value = "YYYY-MM-DD HH:mm:ss"
      }

      // 3.对时间进行格式化
      const formatTime = dayjs(timestamp).format(value)
      el.textContent = formatTime
    }
  })
}

还有一些关于管理员登录后权限的问题,普通管理员能够操作的功能少,可以通过指令来判断和限制显示的结果。

Vue内置组件Teleport

将你写的组件(也可以是普通标签)传输到其他位置,是真的挂载过去了,页面会有变化。

大概主要是用在js控制的。

<template>
  <div class="app">
    <div class="hello">
      <p class="content">
        <!-- <teleport to="body">
          <hello-world/>
        </teleport> -->
        <teleport to="#abc">
          <hello-world/>
        </teleport>
      </p>
    </div>

    <div class="content">
      <teleport to="#abc">
        <h2>哈哈哈哈哈</h2>
      </teleport>
    </div>
  </div>
</template>

<script setup>

import HelloWorld from "./HelloWorld.vue"

</script>

<style scoped>

</style>

Vue内置组件Suspense

将组件变成一个异步的,当页面加载时,页面需要去加载这个组件,在没加载出来之前可以先显示默认的提示,等加载好之后把提示清除替换成指定组件。

<template>
  <div class="app">
    <suspense>
      <template #default>
        <async-home/>
      </template>
      <template #fallback>
        <h2>Loading</h2>
      </template>
    </suspense>
  </div>
</template>

<script setup>
import { defineAsyncComponent } from 'vue';

const AsyncHome = defineAsyncComponent(() => import("./AsyncHome.vue"))

</script>

<style scoped>

</style>

Vue中安装插件的方式

作用之一是用在app里面

可以将本来分开的app传入的到函数里面转变成链式调用的写法
类似于createApp(App).use(directives).mount("#app")

import { createApp } from 'vue'
import directives from "./01_自定义指令/directives/index"
import router from "./router"


// 自定义指令的方式一:
// const app = createApp(App)
// // useDirectives(app)
// directives(app)
// app.mount('#app')

// 自定义指令的方式二:使用插件
createApp(App).use(directives).use(router).mount("#app")

Vue中渲染函数的使用

template模板会执行render函数,把标签转换成虚拟DOM。

h函数就是createVNode函数:

我们可以把template删除掉,改用render来自己渲染,而render函数需要返回一个createVNode,此时可以用h函数来代替,使用方法一样的。

基本使用: 

_render函数计数器实现:

<script>
  import { h } from 'vue'
  import Home from "./Home.vue"

  export default {
    data() {
      return {
        counter: 0
      }
    },

    render() {
      return h("div", { className: "app" }, [
        h("h2", null, `当前计数: ${this.counter}`),
        h("button", { onClick: this.increment }, "+1"),
        h("button", { onClick: this.decrement }, "-1"),
        h(Home)
      ])
    },
    methods: {
      increment() {
        this.counter++
      },
      decrement() {
        this.counter--
      }
    }
  }
</script>

<style scoped>

</style>

render渲染组件:

<script>
  import { h } from 'vue'
  import Home from "./Home.vue"

  export default {
   

    render() {
      return h("div", { className: "app" }, [
        h(Home)
      ])
    }
   
  }
</script>

<style scoped>

</style>

使用vue3来实现上面的功能:

// 这个template里面的render标签是setup语法糖的要求的写法。setup函数不用写这个。
<template>
  <render/>
  <h2 class="">内容</h2>
</template>

<!-- <script>
  import { h, ref } from 'vue'
  import Home from "./Home.vue"

  export default {
    setup() {
      const counter = ref(0)

      const increment = () => {
        counter.value++
      }
      const decrement = () => {
        counter.value--
      }

      return () => h("div", { className: "app" }, [
        h("h2", null, `当前计数: ${counter.value}`),
        h("button", { onClick: increment }, "+1"),
        h("button", { onClick: decrement }, "-1"),
        h(Home)
      ])
    }
  }
</script> -->

<script setup>

import { ref, h } from 'vue';
import Home from './Home.vue'

const counter = ref(0)

const increment = () => {
  counter.value++
}
const decrement = () => {
  counter.value--
}

const render = () => h("div", { className: "app" }, [
  h("h2", null, `当前计数: ${counter.value}`),
  h("button", { onClick: increment }, "+1"),
  h("button", { onClick: decrement }, "-1"),
  h(Home)
])

</script>

<style scoped>

</style>

猜你喜欢

转载自blog.csdn.net/weixin_56663198/article/details/131748533