689 vue3自定义指令,Teleport组件,插件编写,nexttick

认识自定义指令


实现方式一:聚焦的默认实现


实现方式二:局部自定义指令


方式三:自定义全局指令


指令的生命周期


指令的参数和修饰符


自定义指令练习


时间格式化指令


main.js

import { createApp } from 'vue'
import App from './04_teleport内置组件/App.vue'
import registerDirectives from './directives'
import pluginObject from './plugins/plugins_object'
import pluginFunction from './plugins/plugins_function'

const app = createApp(App)

registerDirectives(app)

// 使用插件,use传入插件对象即可自动安装,即内部执行插件对象pluginObject.install(app)
app.use(pluginObject)
app.use(pluginFunction)

app.directive('focus', {
  mounted(el, bindings, vnode, preVnode) {
    console.log('focus mounted')
    el.focus()
  },
})

app.mount('#app')

01_默认的实现.vue

<template>
  <div>
    <input type="text" ref="input" />
  </div>
</template>

<script>
  import { ref, onMounted } from 'vue'

  export default {
    setup() {
      // 开始传空值,最开始去里面取到的是空值,自动绑定后,元素就会作为它的值
      const input = ref(null)

      // onMounted是函数,需要导入,directives中的mounted是属性
      onMounted(() => {
        input.value.focus()
      })

      return {
        input,
      }
    },
  }
</script>

<style scoped></style>

02_局部自定义指令.vue

<template>
  <div>
    <input type="text" v-focus />
  </div>
</template>

<script>
  export default {
    // 局部指令
    directives: {
      // 指令名称,不需要在前面加-
      focus: {
        // 当上面的input挂载到DOM元素上,就会执行mounted生命周期
        // 参数是自动传入的,binding.value 是我们传递给指令的值
        // onMounted是函数,需要导入,directives中的mounted是属性
        mounted(el, bindings, vnode, preVnode) {
          console.log('focus mounted')
          el.focus()
        },
      },
    },
  }
</script>

<style scoped></style>

03_生命周期和参数-修饰符.vue

<template>
  <div>
    <!-- haha要用双层引号包裹 -->
    <button v-if="counter < 2" v-why.aaaa.bbbb="'haha'" @click="increment">
      当前计数: {{ counter }}
    </button>
  </div>
</template>

<script>
  import { ref } from 'vue'

  export default {
    // 局部指令
    directives: {
      why: {
        created(el, bindings, vnode, preVnode) {
          console.log('why created', el, bindings, vnode, preVnode)
          console.log(bindings.value)
          console.log(bindings.modifiers)
        },
        beforeMount() {
          console.log('why beforeMount')
        },
        mounted() {
          console.log('why mounted')
        },
        beforeUpdate(el) {
          console.log('why beforeUpdate')
          console.log(el.innerHTML)
        },
        updated(el) {
          console.log('why updated')
          console.log(el.innerHTML)
        },
        beforeUnmount() {
          console.log('why beforeUnmount')
        },
        unmounted() {
          console.log('why unmounted')
        },
      },
    },
    setup() {
      const counter = ref(0)
      const increment = () => counter.value++

      return {
        counter,
        increment,
      }
    },
  }
</script>

<style scoped></style>

04.时间格式化指令.vue

<template>
  <h2 v-format-time="'YYYY/MM/DD'">{{ timestamp }}</h2>
</template>

<script>
  export default {
    setup() {
      const timestamp = 1624452193

      return {
        timestamp,
      }
    },
    mounted() {
      console.log('app mounted')
    },
  }
</script>

<style scoped></style>


index.js

import registerFormatTime from './format-time';

export default function registerDirectives(app) {
  registerFormatTime(app);
}

format-time.js

import dayjs from 'dayjs'

export default function (app) {
  // DD:大写,否则显示星期几;HH:大写是24小时制,小写是12小时制
  let formatString = 'YYYY-MM-DD HH:mm:ss'

  app.directive('format-time', {
    // 初始化
    created(el, bindings) {
      if (bindings.value) {
        formatString = bindings.value
      }
    },
    mounted(el) {
      console.log('format mounted')
      const textContent = el.textContent
      let timestamp = parseInt(textContent)

      if (textContent.length === 10) {
        timestamp = timestamp * 1000
      }
      el.textContent = dayjs(timestamp).format(formatString)
    },
  })
}

认识Teleport


下面代码的效果


和组件结合使用


多个teleport


App.vue

<template>
  <div class="app">
    <teleport to="#why">
      <h2>当前计数</h2>
      <button>+1</button>
      <hello-world></hello-world>
    </teleport>

    <teleport to="#why">
      <span>呵呵呵呵</span>
    </teleport>
  </div>
</template>

<script>
  import { getCurrentInstance } from 'vue'

  import HelloWorld from './HelloWorld.vue'

  export default {
    components: {
      HelloWorld,
    },
    setup() {
      const instance = getCurrentInstance() // 拿到组件实例
      // appContext:app上下文,就相当于app了
      console.log(instance.appContext.config.globalProperties.$name)
    },
    mounted() {
      console.log(this.$name)
    },
    methods: {
      foo() {
        console.log(this.$name)
      },
    },
  }
</script>

<style scoped></style>

HelloWorld.vue

<template>
  <div>
    <h2>Hello World</h2>
  </div>
</template>

<script>
  export default {}
</script>

<style scoped></style>

认识Vue插件


插件的编写方式


plugins_object.js

export default {
  // app是默认传递过来的参数
  install(app) {
    // 【这样的话,$name就全局可用。】
    app.config.globalProperties.$name = 'haha'
  },
}

plugins_function.js

export default function (app) {
  console.log(app)
}

nexttick


App_nexttick.vue

<template>
  <div>
    <h2>{{ counter }}</h2>
    <button @click="increment">+1</button>
    <h2 class="title" ref="titleRef">{{ message }}</h2>
    <button @click="addMessageContent">添加内容</button>
  </div>
</template>

<script>
  import { ref, onUpdated, nextTick } from 'vue'

  export default {
    setup() {
      const message = ref('')
      const titleRef = ref(null)
      const counter = ref(0)

      const addMessageContent = () => {
        message.value += '哈哈哈哈哈哈哈哈哈哈'

        // 更新DOM 【更新DOM后,再回头执行nextTick里面的回调函数,相当于延迟。】
        nextTick(() => {
          console.log(titleRef.value.offsetHeight)
        })
      }

      const increment = () => {
        for (let i = 0; i < 100; i++) {
          counter.value++
        }
      }

      onUpdated(() => {}) // 【只要组件界面有更新都会执行onUpdated。】

      return {
        message,
        counter,
        increment,
        titleRef,
        addMessageContent,
      }
    },
  }
</script>

<style scoped>
  .title {
    width: 120px;
  }
</style>

posted on 2021-06-26 10:12  冲啊!  阅读(316)  评论(0编辑  收藏  举报

导航