vue3实验性功能的探索

4,250 阅读2分钟

前言

版本:vue 3.0.3

最近vue3偷偷的在3.0.3的版本中支持了的实验性的新特性<script setup>ref:语法糖css v-bind,现在我们就来尝试一下这几个新特性,最后总结一下目前这几个新特性的问题和优点。

初始化环境

执行命令vue create vue-new-feat

然后选择预设 Default (Vue 3 Preview) ([Vue 3] babel, eslint)

然后cd vue-new-feat

因为eslint-plugin-vue目前还没有支持新特性的语法检查,所以我们先设置一下eslint来保证执行的时候不会报错

打开package.json找到eslintConfig.rules然后填入以下内容

      "no-unused-vars": "off",
      "no-unused-labels": "off",
      "no-const-assign": "off",
      "no-undef": "off",
      "vue/no-unused-components": "off"

然后执行npm run serve

探索

script setup

github.com/vuejs/rfcs/…

我们先来试试script setup,首先我们在script标签上写一个setup

绑定变量

我们可以直接在当前的script标签里声明一个ref变量,然后两秒后让他变一个内容

<template>
  <img alt="Vue logo" src="./assets/logo.png" />

  <span>{{ test }}</span>
</template>

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

const test = ref("new feat");

setTimeout(() => {
  test.value = "hello";
}, 2000);
</script>

导入组件并使用

接下来我们试试导入HelloWorld组件并且使用这个组件

<template>
  <img alt="Vue logo" src="./assets/logo.png" />
  <HelloWorld :msg="test"></HelloWorld>
  <span>{{ test }}</span>
</template>

<script setup>
import HelloWorld from "@/components/HelloWorld";
import { ref } from "vue";

const test = ref("new feat");
</script>

我们发现,我们不需要注册组件就可以直接使用,这波操作还是非常nice的

事件绑定

我们试一下新特性的事件绑定方式

<template>
  <img alt="Vue logo" src="./assets/logo.png" />
  <HelloWorld :msg="test"></HelloWorld>
  <button @click="onClick">点我</button>
</template>

<script setup>
import HelloWorld from "@/components/HelloWorld";
import { ref } from "vue";

const test = ref("new feat");

function onClick() {
  alert(123);
}
</script>

点击后成功弹出alert

封装一个组件

接下来我们封装一个MyInput组件看看

MyInput.vue
<template>
  <input :value="props.modelValue" @input="onInput" type="text" />
</template>

<script setup>
import { defineEmit, defineProps } from "vue";

const props = defineProps({
  modelValue: {
    type: String,
  },
});
// 这里使用defineProps来实现Options.props的功能
// 并且这个函数的返回值props与setup(props)一样,
// 我们可以在props里访问到用户传来的数据

const emit = defineEmit(["update:modelValue"]);
// 事件的定义使用的是defineEmit来实现Options.emits
// 的功能,他的返回值emit就是ctx.emit,我们可以使用
// emit这个函数发生事件

function onInput(e) {
  emit("update:modelValue", e.target.value);
}

console.log(props); // 父组件传来的值
console.log(emit); // 这个和ctx.emit一样,也是用来发事件的
</script>

这个组件的功能是封装的一个输入框来实现双向绑定

我们来使用这个组件

App.vue
<template>
  <img alt="Vue logo" src="./assets/logo.png" />
  <MyInput v-model="test"></MyInput>
  <span>{{ test }}</span>
</template>

<script setup>
import MyInput from "@/components/MyInput";
import { ref } from "vue";

const test = ref("new feat");
</script>

script与script setup一起使用

如果你有想使用script有想使用script setup你可以使用以下的方式,他最后和合并选项

<template>
  <input :value="props.modelValue" @input="onInput" type="text" />
</template>

<script>
export default {
  name: "MyInput",
};
</script>

<script setup>
import { defineComponent, defineEmit, defineProps } from "vue";

const props = defineProps({
  modelValue: {
    type: String,
  },
});

const emit = defineEmit(["update:modelValue"]);

function onInput(e) {
  emit("update:modelValue", e.target.value);
}
</script>

暴露一个属性或方法

新的特性里可以使用ctx.expose(之后可能可以直接到vue里导入expose)来暴露一些方法和属性来供父组件调用。

<template>
  <input :value="props.modelValue" @input="onInput" type="text" />
</template>

<script>
export default {
  name: "MyInput",
};
</script>

<script setup>
import { defineComponent, defineEmit, defineProps, useContext } from "vue";

const { expose } = useContext();

const props = defineProps({
  modelValue: {
    type: String,
  },
});

const emit = defineEmit(["update:modelValue"]);

function onInput(e) {
  emit("update:modelValue", e.target.value);
}

function clear() {
  emit("update:modelValue", "");
}

expose({ clear });
//将clear暴露出去
</script>

ref: 语法糖

github.com/vuejs/rfcs/…

<template>
  <img alt="Vue logo" src="./assets/logo.png" />
  <MyInput v-model="test" ref="myInput"></MyInput>
  <span>{{ test }}</span>
</template>

<script setup>
import { default as MyInput } from "@/components/MyInput";
import { ref, useContext } from "vue";
ref: myInput = null;
ref: test = "hello";

setTimeout(() => {
  myInput.clear();
}, 1000);
</script>

我们可以直接使用ref:来声明一个Ref类型的变量

在访问的时候可以不使用.value

CSS v-bind

github.com/vuejs/rfcs/…

<template>
  <img alt="Vue logo" src="./assets/logo.png" />
  <div id="app">
    <div>{{ test }}</div>
    <button @click="color = 'blue'">Blue</button>
    <button @click="color = 'red'">Red</button>
  </div>
</template>

<script setup>
import { default as MyInput } from "@/components/MyInput";
import { ref, useContext } from "vue";
ref: test = "hello";
ref: color = "red";
ref: mTop = 10;

setTimeout(() => {
  mTop = 100;
}, 3000);
</script>

<style>
#app {
  text-align: center;
  color: v-bind(color);
  margin-top: v-bind('mTop + "px"');
}
</style>

我们可以使用v-bind绑定一个变量或者表达式,注意表达式必须上引号.

总结

经历了一下午的探索,vue3新的特性虽然好用,但还是有一些问题的,如:

script setup 开始就已经说了目前官方的eslint-plugin-vue还没有支持,所以在团队开发方面目前还是不能使用,所以团队开发不是太推荐,不过个人开发可以用一下,这种新的写法是真的方便

ref: 语法糖 目前在函数作用域内是无法使用的,具体原因请看他的文档,不过未来会支持,而且ref的语法糖可能在未来换另外一种方案,所以不推荐

v-bind目前感觉不会有太大的变化,在短暂使用后如果项目内想实现主题更换的效果还是比较推荐的

虽然目前还有一些问题没有解决但是我相信在未来时间内vue会越做越好。

最后目前elment3正在处于beta阶段,如果有小伙伴想加入我们,可以访问下面的链接。

github.com/hug-sun/ele…