当前位置:   article > 正文

vue3.3新特性解析

vue3.3新特性

vue3.3新特性解析

在这里插入图片描述

新特性列表

  1. Composition API:这是一个新的编写组件的方式,可以让我们更好地复用和组织代码,避免了mixins和scoped slots的一些缺陷。

  2. **SFC Composition API Syntax Sugar (script setup) **:这是一个简化了Composition API的语法糖,可以让我们在单文件组件中更方便地使用Composition API。

  3. Teleport:这是一个新的内置组件,可以让我们将子组件渲染到任意位置,而不受父组件的影响,可以让我们更容易地处理一些弹窗、模态框、通知等场景。

  4. Fragments:这是一个新的特性,可以让我们在组件中返回多个根节点,而不需要包裹在一个额外的元素中,可以让我们的模板更加灵活和自由。

  5. Filters:这是一个被移除的特性,因为它与JavaScript本身的管道运算符有冲突,而且它也不是响应式的,我们可以用其他方式来实现过滤器的功能,比如计算属性或者方法。

  6. Experimental Suspense feature:这是一个实验性的特性,可以让我们更好地处理异步组件的加载状态。

  7. Experimental state-driven CSS variables (v-bind in ):这是一个实验性的特性,可以让我们在单文件组件中使用v-bind来绑定CSS变量,从而实现动态样式。

  8. Single file component changes:这是一个改变了单文件组件中 (style scoped) 行为的特性,可以让我们在 (style scoped) 中包含全局规则或者只针对插槽内容的规则。

  9. Multiple v-models:这是一个新的特性,可以让我们在同一个组件上使用多个v-model来绑定多个属性。

  10. Lifecycle naming changes:这是一个改变了部分生命周期钩子名称的特性,以便于与Composition API保持一致。

新特性详细介绍及其代码示例:

Composition API

<template>
  <div>
    <h1>{{ state.title }}</h1>
    <p>{{ state.count }}</p>
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
  </div>
</template>

<script>
import { reactive, computed } from "vue";

export default {
  setup() {
    // 创建一个响应式对象
    const state = reactive({
      title: "Hello Vue 3",
      count: 0,
    });

    // 创建一个计算属性
    const doubleCount = computed(() => state.count * 2);

    // 创建一个方法
    const increment = () => {
      state.count++;
    };

    const decrement = () => {
      state.count--;
    };

    // 返回需要在模板中使用的数据和方法
    return {
      state,
      doubleCount,
      increment,
      decrement,
    };
  },
};
</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

这个示例代码展示了如何使用Composition API来编写一个简单的计数器组件。我们可以看到,我们在setup函数中使用reactive函数来创建一个响应式对象state,它包含了我们需要的数据title和count。然后我们使用computed函数来创建一个计算属性doubleCount,它根据state.count的变化而变化。接着我们定义了两个方法increment和decrement,它们分别用于增加和减少state.count的值。最后我们将需要在模板中使用的数据和方法返回,这样我们就可以在模板中绑定它们。这样我们就实现了一个简单的计数器组件,而且我们可以看到,我们的代码是按照逻辑关注点来组织的,而不是按照组件选项来组织的,这样可以让我们更好地复用和组织代码。


SFC Composition API Syntax Sugar (script setup)

<template>
  <div>
    <h1>{{ title }}</h1>
    <p>{{ count }}</p>
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
  </div>
</template>

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

// 创建一个响应式引用
const title = ref("Hello Vue 3");

// 创建一个响应式引用
const count = ref(0);

// 创建一个方法
const increment = () => {
  count.value++;
};

// 创建一个方法
const decrement = () => {
  count.value--;
};
</script>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

这个示例代码展示了如何使用SFC Composition API Syntax Sugar来编写一个简单的计数器组件。我们可以看到,我们在


Teleport

<template>
  <div class="container">
    <h1>Teleport Demo</h1>
    <button @click="showModal = true">Show Modal</button>

    <!-- 使用teleport组件将modal渲染到body元素下 -->
    <teleport to="body">
      <!-- 使用v-if控制modal的显示 -->
      <div v-if="showModal" class="modal">
        <div class="modal-content">
          <h2>Modal Title</h2>
          <p>Modal Content</p>
          <button @click="showModal = false">Close Modal</button>
        </div>
      </div>
    </teleport>
  </div>
</template>

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

// 创建一个响应式引用
const showModal = ref(false);
</script>

<style scoped>
.container {
  margin: 20px;
}

.modal {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
}

.modal-content {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 300px;
  height: 200px;
  background-color: white;
  border-radius: 10px;
}
</style>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52

这个示例代码展示了如何使用teleport组件来实现一个简单的模态框组件。我们可以看到,我们在模板中使用teleport组件将modal渲染到body元素下,这样就可以避免modal被父组件的样式或者其他元素影响。然后我们使用v-if指令来控制modal的显示,根据showModal的值来决定是否渲染modal。最后我们在modal-content中定义了模态框的标题、内容和关闭按钮,并且给关闭按钮绑定了一个点击事件,用于将showModal设置为false。这样我们就实现了一个简单的模态框组件,而且我们可以看到,teleport组件让我们更容易地处理一些弹窗、模态框、通知等场景


Fragments

<template>
<!-- 返回多个根节点 -->
<h1>Hello Vue 3</h1>
<p>This is a fragment component.</p>
</template>

<script setup></script>

<style scoped></style>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

这个示例代码展示了如何使用fragments特性来返回多个根节点。我们可以看到,在模板中,我们直接返回了两个元素:h1和p,并没有将它们包裹在一个额外的元素中。这样就可以让我们在组件中返回多个根节点,而不需要添加多余的标签或者数组。这样可以让我们的模板更加灵活和自由。


Filters

<template>
<!-- 在Vue2中使用过滤器 -->
<h1>{{ title | capitalize }}</h1>

<!-- 在Vue3中使用计算属性或者方法 -->
<h1>{{ capitalizedTitle }}</h1>

<!-- 或者 -->

<h1>{{ capitalize(title) }}</h1>

</template>

<script setup>
import { ref, computed } from "vue";

// 创建一个响应式引用
const title = ref("hello vue");

// 创建一个计算属性
const capitalizedTitle = computed(() => {
 return title.value.charAt(0).toUpperCase() + title.value.slice(1);
});

// 创建一个方法
const capitalize = (str) => {
 return str.charAt(0).toUpperCase() + str.slice(1);
};
</script>

<style scoped></style>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

这个示例代码展示了如何在Vue3中替代过滤器的功能。我们可以看到,在Vue2中,我们可以使用过滤器来对数据进行一些格式化或者转换,比如将title转换为首字母大写。但是在Vue3中,过滤器被移除了,因为它与JavaScript本身的管道运算符有冲突,而且它也不是响应式的。所以在Vue3中,我们可以使用计算属性或者方法来实现过滤器的功能,比如创建一个capitalizedTitle计算属性或者capitalize方法来将title转换为首字母大写。这样就可以让我们用其他方式来实现过滤器的功能,比如计算属性或者方法。


Experimental Suspense feature

<template>
<!-- 使用suspense组件包裹异步组件 -->
<suspense :timeout="3000">
<!-- 定义异步加载成功时显示的内容 -->
<template #default> 
<hello-world />
</template>

<!-- 定义异步加载失败时显示的内容 -->
<template #fallback> 
<p>Loading...</p> 
</template>

<!-- 定义异步加载超时时显示的内容 -->
<template #timeout> 
<p>Timeout!</p> 
</template>
</suspense>
</template>

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

// 定义一个异步组件
const HelloWorld = defineAsyncComponent(() => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(import("./HelloWorld.vue"));
    }, 2000);
  });
});
</script>

<style scoped></style>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

这个示例代码展示了如何使用suspense组件来处理异步组件的加载状态。我们可以看到,我们在模板中使用suspense组件来包裹一个异步组件HelloWorld,它是通过defineAsyncComponent函数来定义的,它返回一个Promise,用于延迟加载HelloWorld.vue文件。然后我们在suspense组件中定义了三个插槽:default、fallback和timeout,分别用于定义异步加载成功、失败和超时时显示的内容。我们还给suspense组件绑定了一个timeout属性,用于设置异步加载的超时时间。这样就可以让我们更好地处理异步组件的加载状态,而且我们可以自定义不同状态下显示的内容。


Experimental state-driven CSS variables (v-bind in style)

<template>
<div class="container">
<h1>Hello Vue 3</h1>
<button @click="toggleTheme">Toggle Theme</button>
</div>
</template>

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

// 创建一个响应式引用
const theme = ref("light");

// 创建一个方法
const toggleTheme = () => {
  theme.value = theme.value === "light" ? "dark" : "light";
};
</script>

<style scoped>
.container {
  /* 使用v-bind绑定CSS变量 */
  v-bind: {
    "--bg-color": theme === "light" ? "white" : "black",
    "--text-color": theme === "light" ? "black" : "white",
  }
}

h1 {
  /* 使用CSS变量设置样式 */
  color: var(--text-color);
}

button {
  /* 使用CSS变量设置样式 */
  background-color: var(--bg-color);
  color: var(--text-color);
}
</style>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

这个示例代码展示了如何使用v-bind在


Single file component (style scoped) changes

<template>
<div class="container">
<h1>Hello Vue 3</h1>
<slot></slot>
</div>
</template>

<script setup></script>

<style scoped>
.container {
  border: 1px solid black;
}

/* 使用::v-deep选择器来定义全局规则 */
::v-deep p {
  color: red;
}

/* 使用::v-slotted选择器来定义只针对插槽内容的规则 */
::v-slotted span {
  font-weight: bold;
}
</style>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

这个示例代码展示了如何在


Multiple v-models

<template>
<div class="container">
<h1>Hello Vue 3</h1>
<custom-input v-model:title="title" v-model:content="content" />
<p>Title: {{ title }}</p>
<p>Content: {{ content }}</p>
</div>
</template>

<script setup>
import { ref } from "vue";
import CustomInput from "./CustomInput.vue";

// 创建两个响应式引用
const title = ref("");
const content = ref("");
</script>

<style scoped></style>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
<template>
<div class="custom-input">
<label for="title">Title:</label>
<input id="title" type="text" v-model="title" />

<label for="content">Content:</label>
<textarea id="content" v-model="content"></textarea>
</div>
</template>

<script setup>
import { computed } from "vue";

// 获取父组件传入的props
const props = defineProps({
  title: String,
  content: String,
});

// 获取父组件传入的emit函数
const emit = defineEmits(["update:title", "update:content"]);

// 创建两个计算属性
const title = computed({
  get: () => props.title,
  set: (value) => emit("update:title", value),
});

const content = computed({
  get: () => props.content,
  set: (value) => emit("update:content", value),
});
</script>

<style scoped></style>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

这个示例代码展示了如何在同一个组件上使用多个v-model来绑定多个属性。我们可以看到,在父组件中,我们引入了一个自定义组件CustomInput,并且给它绑定了两个v-model:title和content,分别对应两个响应式引用title和content。然后我们在模板中显示这两个数据。在子组件中,我们定义了两个props:title和content,并且定义了两个emit函数:update:title和update:content,分别用于更新父组件中的数据。然后我们创建了两个计算属性title和content,并且将它们与props和emit函数关联起来。最后我们在模板中使用v-model指令将这两个计算属性绑定到input和textarea元素上。这样就可以让我们在同一个组件上使用多个v-model来绑定多个属性。


Lifecycle naming changes

<template>
<h1>Hello Vue 3</h1>
</template>

<script setup>
import { onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted } from "vue";

// 在Vue2中使用beforeCreate和created钩子,在Vue3中使用setup函数替代

// 在Vue2中使用beforeMount钩子,在Vue3中使用onBeforeMount函数替代
onBeforeMount(() => {
  console.log("before mount");
});

// 在Vue2中使用mounted钩子,在Vue3中使用onMounted函数替代
onMounted(() => {
  console.log("mounted");
});

// 在Vue2中使用beforeUpdate钩子,在Vue3中使用onBeforeUpdate函数替代
onBeforeUpdate(() => {
  console.log("before update");
});

// 在Vue2中使用updated钩子,在Vue3中使用onUpdated函数替代
onUpdated(() => {
  console.log("updated");
});

// 在Vue2中使用beforeDestroy钩子,在Vue3中使用onBeforeUnmount函数替代
onBeforeUnmount(() => {
  console.log("before unmount");
});

// 在Vue2中使用destroyed钩子,在Vue3中使用onUnmounted函数替代
onUnmounted(() => {
  console.log("unmounted");
});
</script>

<style scoped></style>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

这个示例代码展示了如何在Vue3中使用新的生命周期函数。我们可以看到,我们从vue模块中导入了一些以on开头的函数,它们分别对应了Vue2中的一些生命周期钩子,只是名称有所变化,以便于与Composition API保持一致。然后我们在setup函数中调用这些函数,并传入一个回调函数,用于执行一些逻辑。这样就可以让我们更清楚地区分不同类型的生命周期函数。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/494318
推荐阅读
相关标签
  

闽ICP备14008679号