vue3学习之Typescript对vue3的加持

我爱海鲸 2023-01-15 18:12:06 ts、vue、前端

简介Typescript对vue3的加持、ts、teleport(瞬间移动)

链接上一篇文章:vue3学习之模块化(三)结合ts、泛型改造

vue2对于typescript的支持非常的有限 

1、现在我们来看一下vue3对typescript的支持

<script lang="ts">
  import { defineComponent } from 'vue'
  const component =
          defineComponent({
            name: 'HelloWorld',
            props: {
              msg: {
                required: true,
                type: String
              }
            },
            setup(props, context) {
              console.log(props)
              console.log(context)
            }
          })
  export default component;
</script>

2、遇到的问题:

Dialog被包裹在其他组件之中,容易被干扰

样式也在其他组件中,容易变得非常混乱

希望的解决方案

现在我们来看一下teleport

在components中添加Modal.vue

添加一个组件的时候可能会出现报错,注意修改一下配置

module.exports = {
  root: true,
  env: {
    node: true
  },
  'extends': [
    'plugin:vue/vue3-essential',
    'eslint:recommended',
    '@vue/typescript/recommended'
  ],
  parserOptions: {
    ecmaVersion: 2020
  },
  rules: {
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    //在rules中添加自定义规则
    //关闭组件命名规则
    "vue/multi-word-component-names":"off",
  },
  overrides: [
    {
      files: [
        '**/__tests__/*.{j,t}s?(x)',
        '**/tests/unit/**/*.spec.{j,t}s?(x)'
      ],
      env: {
        jest: true
      }
    }
  ]
}

如图:

如下:

<template>
<teleport to="#modal">
  <div id="center" v-if="isOpen">
    <h2><slot>this is a modal</slot></h2>
    <button @click="buttonClick">Close</button>
  </div>
</teleport>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
  props: {
    isOpen: Boolean,
  },
  emits: {
    'close-modal': null
  },
  setup(props, context) {
    const buttonClick = () => {
      context.emit('close-modal')
    }
    return {
      buttonClick
    }
  }
})
</script>
<style>
  #center {
    width: 200px;
    height: 200px;
    border: 2px solid black;
    background: white;
    position: fixed;
    left: 50%;
    top: 50%;
    margin-left: -100px;
    margin-top: -100px;
  }
</style>

to="#model"表示的是将该组件移动到id为model下面去,这就是瞬间移动的含义,将一个组件渲染到另一个dom节点中

在index.html文件中添加

<div id="modal"></div>
如图:


然后在app.vue中添加相关的案件事件,代码如下:

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <h1>{{count}}</h1>
    <h1>{{double}}</h1>
    <h1>x:{{x}}</h1>
    <h1>y:{{y}}</h1>
    <ul>
      <li v-for="number in numbers" :key="number">
        <h1>{{number}}</h1>
      </li>
    </ul>
    <h1>{{person.name}}</h1>
    <button @click="openModal">Open Modal</button><br/>
    <modal :isOpen="modalIsOpen" @close-modal="onModalClose"> My Modal !!!!</modal>
    <h1 v-if="loading">Loading!...</h1>
    <img v-if="loaded" :src="result[0].url" style="width: 100px;height: 100px"  alt="">
    <button @click="increase">赞+1</button><br/>
    <button @click="updateGreeting">Update Title</button>
  </div>
</template>

<script lang="ts">
  // 响应式对象引入,计算函数引入
import { ref,computed,reactive,toRefs,onMounted,onUpdated,watch,onUnmounted } from 'vue'
import useMousePosition from './hooks/useMousePosition'
import useURLLoader from './hooks/useURLLoader'
import Modal from './components/Modal.vue'

interface DataProps {
  count: number;
  double: number;
  increase: () => void;
  numbers: Array<number>,
  person: {name ? :string}
}

  interface DogResult {
    message: string;
    status: string;
  }

  interface CatResult {
    id: string;
    url: string;
    width: number;
    height: number;
  }
export default{
  name: 'App',
  components: {
    Modal
  },
  setup() {

    onUpdated(() => {
      // console.log('onUpdated');
    })
    // onRenderTracked((event) => {
    //   console.log(event);
    // })

    const data: DataProps  = reactive({
      count: 0,
      increase: () => { data.count++},
      double: computed(() => data.count * 2),
      numbers: [0,1,2],
      person: {}
    })
    const { x, y } = useMousePosition()
    const { result, loading, loaded } = useURLLoader<CatResult[]>('https://api.thecatapi.com/v1/images/search?limit=1')
    const greetings = ref('')
    const updateGreeting = () => {
      greetings.value += 'Hello! '
    }
    watch(result, () => {
      if (result.value) {
        console.log('value', result.value)
      }
    })

    data.numbers[0] = 5;
    data.person.name = 'haijin';
    const refData = toRefs(data)
    const modalIsOpen = ref(false)
    const openModal = () => {
      modalIsOpen.value = true
    }
    const onModalClose = () => {
      modalIsOpen.value = false
    }
    return {
      ...refData,
      greetings,
      updateGreeting,
      x,
      y,
      result,
      loading,
      loaded,
      modalIsOpen,
      openModal,
      onModalClose
    }
  }
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

结果如图:

 

 

你好:我的2025