往期文章:
前言
好久没关注 vue 了,记得上次写vue的文章还是在去年,vue-beta版本,当时就掉坑了,果断躺下,不出来了,爱咋咋滴~
今早起床,也不知道自己哪根筋搭错了,居然想看看vue的东西,废话不多说,开始正文~
安装
@vitejs/app 提供了 js 和 ts 版本,先从 js 入手 yarn create @vitejs/app
- 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>
配置 typescript
1.修改index.html
<script type="module" src="/src/main.ts"></script>
2.修改package.json > scripts
"scripts": {
"build": "vue-tsc --noEmit && vite build",
}
- 创建 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