关于此分类

关于初识 vue3分类主要是记录一些通过 vue3 进行的实践与学习记录。

此文主要记录一些在 vue3 中的一些语法改变(只记录composition api语法),当然使用@vue/composition-api插件也可以令vue2适用本文所记录的语法。

本文会随着作者日常使用进行补充及内容修正

数据相关(data)

<template>
  <div>
    <!-- vue模式下展示ref数据不需要加.value -->
    <div>当前title:{{ title }}</div>
    <input v-model="title" type="text" />
    <div>当前用户名:{{ form.name }}</div>
    <div>当前用户名:{{ form.password }}</div>
    <div>
      <input v-model="form.name" type="text" />
      <input v-model="form.password" type="text" />
    </div>
  </div>
</template>

<script lang="ts">
import { ref, reactive } from 'vue'
export default {
  setup() {
    // 定义响应式普通数据
    const title = ref<string>('小康')
    // 定义响应式引用数据
    const form = reactive({
      name: '小康',
      password: '12334'
    })
    // 需要将变量或方法return视图中才可以使用
    return { title, form }
  }
}
</script>

<style></style>
<template>
  <div>
    <!-- vue模式下展示ref数据不需要加.value -->
    <div>当前title:{{ title }}</div>
    <input v-model="title" type="text" />
    <div>当前用户名:{{ form.name }}</div>
    <div>当前用户名:{{ form.password }}</div>
    <div>
      <input v-model="form.name" type="text" />
      <input v-model="form.password" type="text" />
    </div>
  </div>
</template>

<script lang="ts" setup>
// script setup 模式下视图可以直接使用定义的变量
import { ref, reactive } from 'vue'
// 定义响应式普通数据
const title = ref<string>('小康')
// 定义响应式引用数据
const form = reactive({
  name: '小康',
  password: '12334'
})
</script>
import { defineComponent, ref, reactive } from 'vue'
export default defineComponent({
  setup() {
    // 定义响应式普通数据
    const title = ref('小康')
    // 定义响应式引用数据
    const form = reactive({
      name: '小康',
      password: '12334'
    })

    return () => {
      return (
        <div>
          <div>当前title:{title.value}</div>
          <input type='text' v-model={title.value} />
          <div>当前用户名:{form.name}</div>
          <div>当前用户名:{form.password}</div>
          <div>
            <input type='text' v-model={form.name} />
            <input type='text' v-model={form.password} />
          </div>
        </div>
      )
    }
  }
})

自定义 v-model

父组件调用子组件并通过 v-model 绑定一个值,在子组件中直接触发事件进行修改。

emit 使用参考下文

<div>
  <span> v-model-setup 当前title:{{ title }}</span>
  <v-model-setup v-model:title="title" />
</div>
<script setup lang="ts">
  import { ref } from 'vue'
  const title = ref('父组件的标题')
</script>
<template>
  <button @click="changeTitle">修改传入title值</button>
</template>
<script lang="ts">
  export default {
    emits: ['update:title'],
    // setup参数参考 https://v3.cn.vuejs.org/guide/composition-api-setup.html#%E5%8F%82%E6%95%B0
    setup(props, context) {
      const changeTitle = () => {
        context.emit('update:title', '子组件修改的值')
      }
      return { changeTitle }
    }
  }
</script>
<template>
  <button @click="changeTitle">修改传入title值</button>
</template>
<script setup lang="ts">
  // script setup模式下需要使用defineEmits进行定义emit
  const emit = defineEmits(['update:title'])
  const changeTitle = () => {
    emit('update:title', 'script setup子组件修改的值')
  }
</script>
import { defineComponent } from 'vue'
export default defineComponent({
  emits: ['update:title'],
  // setup参数参考 https://v3.cn.vuejs.org/guide/composition-api-setup.html#%E5%8F%82%E6%95%B0
  setup(props, context) {
    const changeTitle = () => {
      context.emit('update:title', 'tsx子组件修改的值')
    }
    return () => {
      return <button onClick={changeTitle}>修改父组件的的值</button>
    }
  }
})

接收父组件的值(props)

import { PropType } from 'vue'
export default {
  props: {
    title: {
      type: String as PropType<string>,
      required: false,
      default: '没有传入title'
    }
  },
  // setup 第一个参数可以取到props
  setup(props, context) {
    return { props }
  }
}
<script setup lang="ts">
  import { PropType } from 'vue'
  // script setup模式下需要使用defineProps进行定义emit
  const props = defineProps({
    title: {
      type: String as PropType<string>,
      required: false,
      default: '没有传入title'
    }
  })
</script>
import { defineComponent, PropType } from 'vue'
export default defineComponent({
  props: {
    title: {
      type: String as PropType<string>,
      required: false,
      default: '没有传入title'
    }
  },
  // setup 第一个参数可以取到props
  setup(props, context) {
    return () => {
      return <div>子组件接收的title的值为:{props.title}</div>
    }
  }
})

如果需要将props中的值解构,则需要使用toRefs函数

const { title } = toRefs(props)

方法相关(methods)

事件相关无太大变化,@eventName="eventFun"即可。

自定义监听事件(emit)

export default {
  // 为了便于维护,定义好触发的emits
  emits: ['test'],
  // setup参数参考 https://v3.cn.vuejs.org/guide/composition-api-setup.html#%E5%8F%82%E6%95%B0
  setup(props, context) {
    const changeTitle = () => {
      context.emit('test', '子组件修改的值')
    }
    return { changeTitle }
  }
}
// script setup模式下需要使用defineEmits进行定义emit
const emit = defineEmits(['test'])
const changeTitle = () => {
  emit('test', 'script setup子组件修改的值')
}
import { defineComponent } from 'vue'
export default defineComponent({
  // 为了便于维护,定义好触发的emits
  emits: ['test'],
  // setup参数参考 https://v3.cn.vuejs.org/guide/composition-api-setup.html#%E5%8F%82%E6%95%B0
  setup(props, context) {
    const changeTitle = () => {
      context.emit('test', 'tsx子组件修改的值')
    }
    return () => {
      return <button onClick={changeTitle}>修改父组件的的值</button>
    }
  }
})

计算属性(computed)和监听器(watch)

更过细节参考

计算属性

<template>
  <div>当前value原值{{ val }}</div>
  <div>当前计算属性newVal的值{{ newVal }}</div>
  <button @click="change">val+1</button>
</template>
<script lang="ts">
  import { ref, computed } from 'vue'
  export default {
    // setup参数参考 https://v3.cn.vuejs.org/guide/composition-api-setup.html#%E5%8F%82%E6%95%B0
    setup() {
      const val = ref(1)
      const newVal = computed(() => {
        // 返回val加10的结果
        return val.value + 10
      })
      const change = () => {
        val.value += 1
      }
      return { val, newVal, change }
    }
  }
</script>
<template>
  <div>当前value原值{{ val }}</div>
  <div>当前计算属性newVal的值{{ newVal }}</div>
  <button @click="change">val+1</button>
</template>
<script setup lang="ts">
  import { ref, computed } from 'vue'

  const val = ref(1)
  const newVal = computed(() => {
    // 返回val加10的结果
    return val.value + 10
  })
  const change = () => {
    val.value += 1
  }
</script>
import { ref, computed, defineComponent } from 'vue'
export default defineComponent({
  // setup参数参考 https://v3.cn.vuejs.org/guide/composition-api-setup.html#%E5%8F%82%E6%95%B0
  setup() {
    const val = ref(1)
    const newVal = computed(() => {
      // 返回val加10的结果
      return val.value + 10
    })
    const change = () => {
      val.value += 1
    }
    return () => {
      return (
        <div>
          <div>当前value原值{val.value}</div>
          <div>当前计算属性newVal的值{newVal.value}</div>
          <button onClick={change}>val+1</button>
        </div>
      )
    }
  }
})

监听器(watch)

基础用法(监听单个值)

import { ref, watch } from 'vue'
export default {
  // setup参数参考 https://v3.cn.vuejs.org/guide/composition-api-setup.html#%E5%8F%82%E6%95%B0
  setup() {
    const val = ref(1)

    watch(val, () => {
      console.log(val.value + '发生了变化')
    })
    const change = () => {
      val.value += 1
    }
    return { val, change }
  }
}
import { ref, watch } from 'vue'

const val = ref(1)
watch(val, () => {
  console.log(val.value + '发生了变化')
})
const change = () => {
  val.value += 1
}
import { ref, watch, defineComponent } from 'vue'
export default defineComponent({
  // setup参数参考 https://v3.cn.vuejs.org/guide/composition-api-setup.html#%E5%8F%82%E6%95%B0
  setup() {
    const val = ref(1)
    watch(val, () => {
      console.log(val.value + '发生了变化')
    })
    const change = () => {
      val.value += 1
    }
    return () => {
      return (
        <div>
          <div>当前value原值{val.value}</div>
          <button onClick={change}>val+1</button>
        </div>
      )
    }
  }
})

获取组件引用

在 vue2 中获取引用通过this.$ref,然后 vue3 中并没有this,因此获取 ref 时的方式也发生了变化。

<div ref="wrapper"></div>
const wrapper = ref<HTMLElement | null>(null)

在 vue3.2 更新中,引用子组件需要在子组件中进行``

<script>
const r = ref('test')
defineExpose({ r })
</script>