Vue3 还没入门-就想放弃

497 阅读2分钟

往期文章:

前言

好久没关注 vue 了,记得上次写vue的文章还是在去年,vue-beta版本,当时就掉坑了,果断躺下,不出来了,爱咋咋滴~

今早起床,也不知道自己哪根筋搭错了,居然想看看vue的东西,废话不多说,开始正文~

安装

@vitejs/app 提供了 js 和 ts 版本,先从 js 入手 yarn create @vitejs/app

image.png

  • App.vue
<template>
  <img alt="Vue logo" src="./assets/logo.png" />
  <HelloWorld msg="Hello Vue 3 + Vite" />
</template>

<script setup>
import HelloWorld from './components/HelloWorld.vue'
</script>
  • HelloWorld
<script setup>
import { defineProps, reactive } from 'vue'

defineProps({
  msg: String
})

const state = reactive({ count: 0 })
</script>

What's this???懵逼了,我记得没错的话,vue不是应该这么写么:

// App.vue
<script>
import { defineComponent } from 'vue';
import HelloWorld from './components/HelloWorld.vue';

export default defineComponent({
  name: 'App',
  components: {
    HelloWorld,
  },
});

// HelloWorld
<script>
import { defineComponent, reactive } from 'vue';
export default defineComponent({
  name: 'HelloWorld',
  props: {
    msg: {
      type: String,
      required: true,
    },
  },
  setup: () => {
    const state = reactive({ count: 1 });
    return { state };
  },
});
</script>

查了一下资料,原来是vue3正在实验性的新语法糖,通过给 script 设置 setupsh属性,就可以简写内容,也不必return,引入的组件不必显式地注册,import 引入就算注册组件了,NB呀,不过太甜了,有点呴得慌😓

试玩新语法糖 setup

  • 无需显式引入并使用defineComponent来包裹组件
  • ref简写语法:ref: num = 1;代替 const num = ref(1);
  • 显式使用defineProps,代替props,defineEmit代替emit
  • useContext代替setup(context)中的context
  • onMounted 简写方式

App.vue

<template>
  <button @click="getChild">获取子组件信息</button>
  <HelloWorld ref="foo" msg="Hello Vue 3 + TypeScript + Vite" @app-click="clickFn" />
</template>

<script setup>
import HelloWorld from './components/HelloWorld.vue';

ref: foo = null;

const clickFn = (count: number) => {
  console.log('app-click', count);
};

const getChild = () => {
  console.log(foo.name); // hello-world
  console.log(foo.getData()); // world
};
</script>

HelloWorld

<template>
  <h1>{{ msg }}</h1>
  <h2>{{ state.count }}</h2>
  <button @click="handleClick">+</button>
  <div>{{ num }}</div>
  <button @click="test">向父组件emit</button>
</template>

<script setup>
import { defineProps, defineEmit, reactive, useContext } from 'vue';

const ctx = useContext();

defineProps({
  msg: String,
});

// 这种方式需要引入 reactive
const state = reactive({ count: 0 });

ref: num = 100;

// 这种方式需要引入 onMounted
// onMounted(() => {
//   console.log('挂载');
// });

onMounted: {
  num = 200;
  console.log('挂载');
}

const handleClick = () => {
  state.count++;
  num++;
};

// emit父组件方法
defineEmit(['app-click']);
const test = () => {
  // emit('app-click', state.count);
  ctx.emit('app-click', state.count);
};

// 导出给组件实例,给伏父组件调用
ctx.expose({
  name: 'hello-world',
  getData() {
    return 'world';
  },
});
</script>

image.png

配置 typescript

1.修改index.html

<script type="module" src="/src/main.ts"></script>

2.修改package.json > scripts

"scripts": {
  "build": "vue-tsc --noEmit && vite build",
}
  1. 创建 tsconfig.json
{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "moduleResolution": "node",
    "strict": true,
    "noImplicitAny": true,
    "noImplicitThis": true,
    "strictNullChecks": true,
    "allowSyntheticDefaultImports": true,
    "jsx": "preserve",
    "sourceMap": true,
    "resolveJsonModule": true,
    "lib": ["esnext", "dom"]
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
}

4.增加script属性

<scripnt setup lang="ts">
 // ....
</script>

5.src目录下 增加vue声明文件 shims-vue.d.ts

declare module '*.vue' {
  import { defineComponent, FunctionalComponent } from 'vue';
  // const component: DefineComponent<{}, {}, any>
  const component: ReturnType<typeof defineComponent> | FunctionalComponent;
  export default component;
}

尾声

实在是整不进去了,老了、学不动了

❤️ 加入我们

字节跳动 · 幸福里团队

Nice Leader:高级技术专家、掘金知名专栏作者、Flutter中文网社区创办者、Flutter中文社区开源项目发起人、Github社区知名开发者,是dio、fly、dsBridge等多个知名开源项目作者

期待您的加入,一起用技术改变生活!!!

招聘链接: job.toutiao.com/s/JHjRX8B

WechatIMG4.jpeg