• 赚钱入口【需求资源】限时招募流量主、渠道主,站长合作;【合作模式】CPS长期分成,一次推广永久有收益。主动打款,不扣量;

Vue3教程详解

CSS/HTML rin, seun 4个月前 (06-26) 102次浏览 0个评论

Vue 3尚未正式发布,但维护人员已经发布了Beta版本,供开发者尝试并提供反馈。

如果您想知道Vue 3的新特性,我将在本文中通过使用Vue 3 beta 9引导您创建一个简单的应用程序来突出显示它们。

我将介绍尽可能多的新内容,包括片段,传送,Composition API和其他一些晦涩的更改。我将尽力解释该功能或更改的原理。

我们将建立什么

我们将构建一个带有模式窗口功能的简单应用。我之所以选择它,是因为它方便地展示了Vue 3的许多变化。

这是该应用在打开和关闭状态下的外观,因此您可以在脑海中描绘出我们正在做什么:Vue3教程详解

Vue 3安装和设置

让我们克隆项目vue-next-webpack-preview,而不是直接安装Vue 3,这将为我们提供最少的Webpack设置,包括Vue 3。

$ git clone https://github.com/vuejs/vue-next-webpack-preview.git vue3-experiment
$ cd vue3-experiment
$ npm i

克隆完并安装NPM模块后,我们要做的就是删除样板文件并创建一个新main.js文件,以便我们可以从头开始创建Vue 3应用程序。

$ rm -rf src/*
$ touch src/main.js

现在,我们将运行开发服务器:

$ npm run dev

创建一个新的Vue 3应用

和vue2中的方式不一样,我们创建新的Vue应用程序的方式已经改变,以前是new Vue(),现在我们需要导入新createApp方法。

src / main.js

import { createApp } from "vue";

const app = createApp({
  // root instance definition
});

app.mount("#app");

我们调用此方法,传递我们的Vue实例定义对象,并将返回对象分配给一个变量app。然后,我们调用mount方法,app并传递一个CSS选择器来指示我们的mount元素,就像$mount在Vue 2中使用实例方法一样。

变化的原因

使用旧的API,我们添加的任何全局配置(插件,mixins,原型属性等)都将永久更改全局状态。例如:

src / main.js

// Affects both instances
Vue.mixin({ ... })

const app1 = new Vue({ el: '#app-1' })
const app2 = new Vue({ el: '#app-2' })

在单元测试中,这确实是一个问题,因为要确保将每个测试都与上一个测试隔离是很棘手的。

在新的API下,调用createApp将返回一个新的应用程序实例,该实例不会受到应用于其他实例的任何全局配置的污染。

添加状态属性

我们的模态窗口可以处于两种状态之一-打开或关闭。让我们用一个布尔型状态属性modalOpen来管理它,我们将给它一个初始值false

在Vue 2下,我们可以通过data在我们的应用程序实例上创建一个属性,然后为要在其中modalOpen声明我们属性的对象分配一个对象来做到这一点,即:

src / main.js

const app = createApp({
  data: {
    modalOpen: false
  }
});

vue3不再允许这样做,而是data必须为其分配一个返回状态对象的工厂函数(factory function)。这里以前是对Vue组件执行的操作,但是现在它也要求对Vue应用程序实例施行。

src/main.js

const app = createApp({
  data: () => ({
    modalOpen: false
  })
});

变化的原因

使用对象而不是工厂函数来存储数据的优点是,首先,它在语法上更简单,其次,您可以在多个根实例之间共享顶级状态,例如:

src / main.js

const state = {
  sharedVal: 0
};

const app1 = new Vue({ state });
const app2 = new Vue({ state });

// Affects both instances
app1._data.sharedVal = 1;

由于具有两种类型的声明不适合初学者使用,因此决定删除此功能。

在继续之前,我们还添加一个方法来切换modalOpen值。这与Vue 2没什么不同。

src / main.js

const app = createApp({
  data: () => ({
    modalOpen: true  
  }),
  methods: {
    toggleModalState() {
      this.modalOpen = !this.modalOpen;
    }
  }
});

使用根组件

如果现在转到浏览器并检查控制台,则会看到警告“组件缺少渲染功能”,因为我们尚未为根实例定义模板。

Vue 2的最佳实践是为根实例创建一个最小的模板,并创建一个App将声明主应用程序标记的组件。

我们在这里也这样做。

$ touch src/App.vue

现在我们可以获取根实例来渲染该组件。区别在于,对于Vue 2,我们通常会使用render函数来执行此操作:

src / main.js

import App from "./App.vue";

const app = createApp({
  ...
  render: h => h(App)
});

app.mount("#app");

我们仍然可以做到这一点,但Vue公司3有一个更简单的方法-把App当做一个根组件。为此,我们可以删除根实例定义,然后传递App组件。

src / main.js

import App from "./App.vue";

const app = createApp(App);

app.mount("#app");

这意味着该App组件不仅由根实例呈现,而且根实例。

在此过程中,我们通过删除app变量来简化语法:

src / main.js

createApp(App).mount("#app");

现在移至根组件,让我们向该组件重新添加状态和方法:

src / App.vue

<script>
export default {
  data: () => ({
    modalOpen: true  
  }),
  methods: {
    toggleModalState() {
      this.modalOpen = !this.modalOpen;
    }
  }
};
</script>

我们还为模态功能创建一个新组件:

$ touch src/Modal.vue

目前,我们将提供一个最小的模板,其中包含内容的广告位。这确保了我们的modal是可重用的。稍后我们将向此组件添加更多内容。

src / Modal.vue

<template>
  <div class="modal">
    <slot></slot>
  </div>
</template>

多根模板

现在让我们为根组件创建模板。我们将创建一个按钮来打开将触发该toggleModalState方法的模态。

我们还将使用刚刚创建的modal组件,该组件将根据的值作为条件modalOpen。我们还要在内容栏中插入一段文本。

src / App.vue

<template>
  <button @click="toggleModalState">Open modal</button>
  <modal v-if="modalOpen">
    <p>Hello, I'm a modal window.</p>
  </modal>
</template>
<script>
import Modal from "./Modal.vue";
export default {
  components: {
    Modal
  },
  ...
}
</script>

注意这个模板有什么奇怪的地方吗?再看一遍。

是的-有两个根本要素。在Vue 3中,由于有了一个称为fragments的功能,不再必须具有单个root元素!

使用Composition API进行重构

Vue 3的旗舰功能是Composition API。这个新的API允许您使用setup函数而不是添加到组件定义对象的属性来定义组件功能。

现在,让我们重构App组件以使用Composition API。

在解释代码之前,请清楚我们所做的只是重构 -组件的功能将相同。还要注意,模板不会更改,因为Composition API仅会影响我们定义组件功能的方式,而不会影响我们渲染组件的方式。

src / App.vue

<template>
  <button @click="toggleModalState">Open modal</button>
  <modal v-if="modalOpen">
    <p>Hello, I'm a modal window.</p>
  </modal>
</template>
<script>
import Modal from "./Modal.vue";
import { ref } from "vue";
export default {
  setup () {
    const modalOpen = ref(false);
    const toggleModalState = () => {
      modalOpen.value = !modalOpen.value;
    };
    return {
      modalOpen,
      toggleModalState
    }
  },
  components: {
    Modal
  }
};
</script>

setup 方法

首先,请注意,我们导入了ref函数允许定义变量modalOpen。此变量等效于this.modalOpen

toggleModalState方法只是一个普通的JavaScript函数。但是,请注意,要更改modalOpen方法主体中的值,我们需要更改其子属性value。这是因为使用ref创建的变量包装在一个对象中,这对于保持它们的反应性是必要的。

如果要详细了解工作方式,最好查阅Vue Composition API文档refs

最后,我们通过setup方法返回modalOpen以及toggleModalState,并在render时传到模板。

变化的原因

请记住,Composition API并不是更改,因为它纯粹是可选的。主要动机是允许更好的代码组织和组件之间的代码重用(因为mixin本质上是一种反模式)。

您认为App在此示例中重构组件以使用Composition API是正确的。但是,如果这是一个更大的组件,或者我们需要与其他组件共享其功能,那么您就会发现它的用处。

传送内容

如果您曾经创建过modal,您将知道它通常位于结束</body>标记之前。

<body>
  <div>
    <!--main page content here-->
  </div>
  <!--modal here-->
</body>

这样做是因为modal通常具有覆盖页面的背景(如果您不明白我的意思,请参阅开头的图片)。要使用CSS来实现此目的,您不需要处理父元素定位和z-index堆栈上下文,因此最简单的解决方案是将modal放在DOM的最底部。

不过,这会导致Vue.js出现问题,并假定UI将作为单个组件树构建。为了允许将树的各部分移动到DOM中的其他位置,在Vue 3中添加了一个新组件teleport

要使用teleport,我们首先要在页面上添加一个元素,然后将modal内容移动到该页面。我们将转到ID index.html,设置一个divID为 modal-wrapper并调整到与Vue的安装元件相邻放置

index.html

<body>
  ...
  <div id="app"></div><!--Vue mounting element-->
  <div id="modal-wrapper">
    <!--modal should get moved here-->
  </div>
</body>

现在,回到App.vue,我们将modal内容包装在teleport组件中。我们还需要指定一个to属性,为该属性分配一个查询选择器,以标识目标元素(在本例中为)#modal-wrapper

src/App.vue

<template>
  <button @click="toggleModalState">Open modal</button>
  <teleport to="#modal-wrapper">
    <modal v-if="modalOpen">
      <p>Hello, I'm a modal window.</p>
    </modal>
  </teleport>
</template>

任何在teleport中的内容都会被呈现在目标元素. 但是,它仍然会像在层次结构中的原始位置一样工作(类似道具,事件等)。

发出事件

现在让我们在modal中添加一个按钮以使其关闭。为此,我们将button添加到模式模板中并在点击时发送close事件。

src / Modal.vue

<template>
  <div class="modal">
    <slot></slot>
    <button @click="$emit('close')">Dismiss</button>
  </div>
</template>

然后,该事件将由父组件捕获,并将切换的值modalOpenwfalse从而关闭窗口。

src / App.vue

<template>
  ...
    <modal 
      v-if="modalOpen" 
      @close="toggleModalState"
    >
      <p>Hello, I'm a modal window.</p>
    </modal>
  </teleport>
</template>

到目前为止,此功能与Vue 2中的功能相同。但是,现在建议在Vue 3中使用new emitscomponent选项显式声明组件的事件。就像道具一样,您可以简单地创建一个字符串数组来命名组件将发出的每个事件。

src / Modal.vue

<template>...</template>
<script>
export default {
  emits: [ "close" ]
}
</script>

变化的原因

想象一下打开其他人编写的组件文件,并看到其道具和事件已明确声明。马上,您将了解此组件的接口,即发送和接收的含义。

除了提供自说明代码之外,您还可以使用事件声明来验证事件有效负载,尽管在此示例中我找不到这样做的理由。

样式插槽内容

为了使modal可重用,我们提供了一个内容插槽。让我们开始通过style为组件添加标签来设置内容的样式。

最好在我们的组件中使用scoped CSS以确保我们提供的规则不会对页面中的其他内容产生意外影响。

继续,让我们把放入该广告位的所有段落文本都变成斜体。为此,我们将使用p选择器创建一个新的CSS规则。

src / Modal.vue

<template>...</template>
<script>...</script>
<style scoped>
  p {
    font-style: italic;
  }
</style>

如果尝试这样做,您会发现它不起作用。原因在于,如果插槽内容仍属于父级,则在编译时确定范围样式。

Vue 3提供的解决方案是提供一个伪选择器,::v-slotted()使您可以使用提供插槽的组件中的范围规则将插槽内容作为目标。

这是我们的用法:

src / Modal.vue

<style scoped>
  ::v-slotted(p) {
    font-style: italic;
  }
</style>

Vue3还包括一些其他新的局部造型选择::v-deep::v-global您可以了解更多关于此处作用域样式RFC

好了,这是我所了解的vue3的新变化,觉得有帮助的话请点下下面的💖,谢谢~~

喜欢 (2)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址