init
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
node_modules
|
||||||
|
dist
|
||||||
12
README.md
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
## 笔记
|
||||||
|
## 使用VuePress搭建github在线blog
|
||||||
|
- 创建一个远程仓库 xxx_ts_study
|
||||||
|
- 修改docs/.vuepress/config.js: base: '/xxx_ts_study/'
|
||||||
|
- 打包文档: npm run doc:build
|
||||||
|
- 将项目推送到github
|
||||||
|
- git init
|
||||||
|
- git add .
|
||||||
|
- git commit -m "init"
|
||||||
|
- git push origin master
|
||||||
|
- 发布文档: npm run doc:deploy
|
||||||
|
- 访问在线文档: https://zxfjd3g.github.io/xxx_ts_study/ (可能要等待一定的时间)
|
||||||
53
build/webpack.config.js
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
const {CleanWebpackPlugin} = require('clean-webpack-plugin')
|
||||||
|
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
const isProd = process.env.NODE_ENV === 'production' // 是否生产环境
|
||||||
|
|
||||||
|
function resolve (dir) {
|
||||||
|
return path.resolve(__dirname, '..', dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
mode: isProd ? 'production' : 'development',
|
||||||
|
entry: {
|
||||||
|
app: './src/main.ts'
|
||||||
|
},
|
||||||
|
|
||||||
|
output: {
|
||||||
|
filename: '[name].[contenthash:8].js'
|
||||||
|
},
|
||||||
|
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.tsx?$/,
|
||||||
|
use: 'ts-loader',
|
||||||
|
include: [resolve('src')]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
plugins: [
|
||||||
|
new CleanWebpackPlugin({
|
||||||
|
}),
|
||||||
|
|
||||||
|
new HtmlWebpackPlugin({
|
||||||
|
template: './public/index.html'
|
||||||
|
})
|
||||||
|
],
|
||||||
|
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.ts', '.tsx', '.js']
|
||||||
|
},
|
||||||
|
|
||||||
|
devtool: isProd ? 'cheap-module-source-map' : 'cheap-module-eval-source-map',
|
||||||
|
|
||||||
|
devServer: {
|
||||||
|
contentBase: './dist', // 服务器加载资源的基础路径
|
||||||
|
host: 'localhost', // 主机名
|
||||||
|
stats: 'errors-only', // 打包日志输出输出错误信息
|
||||||
|
port: 8081,
|
||||||
|
open: true
|
||||||
|
},
|
||||||
|
}
|
||||||
43
docs/.vuepress/config.js
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
module.exports = {
|
||||||
|
base: '/vue3-docs/', /* 基础虚拟路径 */
|
||||||
|
dest: 'docs/dist', /* 打包文件基础路径, 在命令所在目录下 */
|
||||||
|
title: '尚硅谷前端: Vue3入门', // 标题
|
||||||
|
description: '学习使用 Vue3', // 标题下的描述
|
||||||
|
themeConfig: { // 主题配置
|
||||||
|
sidebar: [ // 左侧导航
|
||||||
|
{
|
||||||
|
title: '初识 Vue3', // 标题
|
||||||
|
collapsable: false, // 下级列表不可折叠
|
||||||
|
children: [ // 下级列表
|
||||||
|
'chapter1/01_认识TS',
|
||||||
|
'chapter1/02_创建vue3项目',
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Composition(组合) API',
|
||||||
|
collapsable: false,
|
||||||
|
children: [
|
||||||
|
'chapter2/01_Composition API_常用部分',
|
||||||
|
'chapter2/02_Composition API_其它部分',
|
||||||
|
'chapter2/03_手写组合API',
|
||||||
|
'chapter2/04_Composition VS Option',
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '其它新语法',
|
||||||
|
collapsable: false,
|
||||||
|
children: [
|
||||||
|
'chapter3/01_新组件',
|
||||||
|
'chapter3/02_全局API更新',
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Vue3版 TODO LIST',
|
||||||
|
collapsable: false,
|
||||||
|
children: [
|
||||||
|
'chapter4/',
|
||||||
|
]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
docs/.vuepress/public/logo.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
docs/.vuepress/public/vue3_logo.png
Normal file
|
After Width: | Height: | Size: 59 KiB |
10
docs/README.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
#首页
|
||||||
|
home: true
|
||||||
|
# 图标
|
||||||
|
heroImage: /vue3_logo.png
|
||||||
|
# 按钮文本
|
||||||
|
actionText: 开始学习 →
|
||||||
|
# 按钮点击跳转路径
|
||||||
|
actionLink: /chapter1/01_认识TS.md
|
||||||
|
---
|
||||||
38
docs/chapter1/01_认识TS.md
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# 1. 认识Vue3
|
||||||
|
|
||||||
|
## 1) 了解相关信息
|
||||||
|
|
||||||
|
- Vue.js 3.0 "One Piece" 正式版在今年9月份发布
|
||||||
|
- 2年多开发, 100+位贡献者, 2600+次提交, 600+次PR
|
||||||
|
- ***Vue3支持vue2的大多数特性***
|
||||||
|
- ***更好的支持Typescript***
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 2) 性能提升:
|
||||||
|
|
||||||
|
- 打包大小减少41%
|
||||||
|
- 初次渲染快55%, 更新渲染快133%
|
||||||
|
- 内存减少54%
|
||||||
|
- ***使用Proxy代替defineProperty实现数据响应式***
|
||||||
|
- ***重写虚拟DOM的实现和Tree-Shaking***
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 3) *Composition(组合) API* Option API
|
||||||
|
|
||||||
|
- setup
|
||||||
|
- ref 和 reactive
|
||||||
|
- computed 和 watch
|
||||||
|
- 新的生命周期函数
|
||||||
|
- provide与inject
|
||||||
|
- ...
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 4) 其它新增特性
|
||||||
|
|
||||||
|
- Fragment - 文档碎片
|
||||||
|
- Teleport - 瞬移组件的位置
|
||||||
|
- Suspense - 异步加载组件的loading界面
|
||||||
|
- 全局API的修改
|
||||||
45
docs/chapter1/02_创建vue3项目.md
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
# 2. 创建vue3项目
|
||||||
|
|
||||||
|
## 1) 使用 vue-cli 创建
|
||||||
|
|
||||||
|
文档: https://cli.vuejs.org/zh/guide/creating-a-project.html#vue-create
|
||||||
|
|
||||||
|
```bash
|
||||||
|
## 安装或者升级
|
||||||
|
npm install -g @vue/cli
|
||||||
|
## 保证 vue cli 版本在 4.5.0 以上
|
||||||
|
vue --version
|
||||||
|
## 创建项目
|
||||||
|
vue create my-project
|
||||||
|
```
|
||||||
|
|
||||||
|
然后的步骤
|
||||||
|
|
||||||
|
- Please pick a preset - 选择 ***Manually select features***
|
||||||
|
- Check the features needed for your project - 选择上 ***TypeScript*** ,特别注意点空格是选择,点回车是下一步
|
||||||
|
- Choose a version of Vue.js that you want to start the project with - 选择 ***3.x (Preview)***
|
||||||
|
- Use class-style component syntax - 直接回车
|
||||||
|
- Use Babel alongside TypeScript - 直接回车
|
||||||
|
- Pick a linter / formatter config - 直接回车
|
||||||
|
- Use history mode for router? - 直接回车
|
||||||
|
- Pick a linter / formatter config - 直接回车
|
||||||
|
- Pick additional lint features - 直接回车
|
||||||
|
- Where do you prefer placing config for Babel, ESLint, etc.? - 直接回车
|
||||||
|
- Save this as a preset for future projects? - 直接回车
|
||||||
|
|
||||||
|
## 2) 使用 vite 创建
|
||||||
|
|
||||||
|
- 文档: https://v3.cn.vuejs.org/guide/installation.html
|
||||||
|
|
||||||
|
- vite 是一个由原生 ESM 驱动的 Web 开发构建工具。在开发环境下基于浏览器原生 ES imports 开发,
|
||||||
|
- 它做到了***本地快速开发启动***, 在生产环境下基于 Rollup 打包。
|
||||||
|
- 快速的冷启动,不需要等待打包操作;
|
||||||
|
- 即时的热模块更新,替换性能和模块数量的解耦让更新飞起;
|
||||||
|
- 真正的按需编译,不再等待整个应用编译完成,这是一个巨大的改变。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm init vite-app <project-name>
|
||||||
|
cd <project-name>
|
||||||
|
npm install
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
1026
docs/chapter2/01_Composition API_常用部分.md
Normal file
464
docs/chapter2/02_Composition API_其它部分.md
Normal file
@@ -0,0 +1,464 @@
|
|||||||
|
# 2. Composition API(其它部分)
|
||||||
|
|
||||||
|
## 1) shallowReactive 与 shallowRef
|
||||||
|
|
||||||
|
- shallowReactive : 只处理了对象内最外层属性的响应式(也就是浅响应式)
|
||||||
|
- shallowRef: 只处理了value的响应式, 不进行对象的reactive处理
|
||||||
|
|
||||||
|
- 什么时候用浅响应式呢?
|
||||||
|
- 一般情况下使用ref和reactive即可
|
||||||
|
- 如果有一个对象数据, 结构比较深, 但变化时只是外层属性变化 ===> shallowReactive
|
||||||
|
- 如果有一个对象数据, 后面会产生新的对象来替换 ===> shallowRef
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<h2>App</h2>
|
||||||
|
|
||||||
|
<h3>m1: {{m1}}</h3>
|
||||||
|
<h3>m2: {{m2}}</h3>
|
||||||
|
<h3>m3: {{m3}}</h3>
|
||||||
|
<h3>m4: {{m4}}</h3>
|
||||||
|
|
||||||
|
<button @click="update">更新</button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { reactive, ref, shallowReactive, shallowRef } from 'vue'
|
||||||
|
/*
|
||||||
|
shallowReactive与shallowRef
|
||||||
|
shallowReactive: 只处理了对象内最外层属性的响应式(也就是浅响应式)
|
||||||
|
shallowRef: 只处理了value的响应式, 不进行对象的reactive处理
|
||||||
|
总结:
|
||||||
|
reactive与ref实现的是深度响应式, 而shallowReactive与shallowRef是浅响应式
|
||||||
|
什么时候用浅响应式呢?
|
||||||
|
一般情况下使用ref和reactive即可,
|
||||||
|
如果有一个对象数据, 结构比较深, 但变化时只是外层属性变化 ===> shallowReactive
|
||||||
|
如果有一个对象数据, 后面会产生新的对象来替换 ===> shallowRef
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default {
|
||||||
|
|
||||||
|
setup () {
|
||||||
|
|
||||||
|
const m1 = reactive({a: 1, b: {c: 2}})
|
||||||
|
const m2 = shallowReactive({a: 1, b: {c: 2}})
|
||||||
|
|
||||||
|
const m3 = ref({a: 1, b: {c: 2}})
|
||||||
|
const m4 = shallowRef({a: 1, b: {c: 2}})
|
||||||
|
|
||||||
|
const update = () => {
|
||||||
|
// m1.b.c += 1
|
||||||
|
// m2.b.c += 1
|
||||||
|
|
||||||
|
// m3.value.a += 1
|
||||||
|
m4.value.a += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
m1,
|
||||||
|
m2,
|
||||||
|
m3,
|
||||||
|
m4,
|
||||||
|
update,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 2) readonly 与 shallowReadonly
|
||||||
|
|
||||||
|
- readonly:
|
||||||
|
- 深度只读数据
|
||||||
|
- 获取一个对象 (响应式或纯对象) 或 ref 并返回原始代理的只读代理。
|
||||||
|
- 只读代理是深层的:访问的任何嵌套 property 也是只读的。
|
||||||
|
- shallowReadonly
|
||||||
|
- 浅只读数据
|
||||||
|
- 创建一个代理,使其自身的 property 为只读,但不执行嵌套对象的深度只读转换
|
||||||
|
- 应用场景:
|
||||||
|
- 在某些特定情况下, 我们可能不希望对数据进行更新的操作, 那就可以包装生成一个只读代理对象来读取数据, 而不能修改或删除
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<h2>App</h2>
|
||||||
|
<h3>{{state}}</h3>
|
||||||
|
<button @click="update">更新</button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { reactive, readonly, shallowReadonly } from 'vue'
|
||||||
|
/*
|
||||||
|
readonly: 深度只读数据
|
||||||
|
获取一个对象 (响应式或纯对象) 或 ref 并返回原始代理的只读代理。
|
||||||
|
只读代理是深层的:访问的任何嵌套 property 也是只读的。
|
||||||
|
shallowReadonly: 浅只读数据
|
||||||
|
创建一个代理,使其自身的 property 为只读,但不执行嵌套对象的深度只读转换
|
||||||
|
应用场景:
|
||||||
|
在某些特定情况下, 我们可能不希望对数据进行更新的操作, 那就可以包装生成一个只读代理对象来读取数据, 而不能修改或删除
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default {
|
||||||
|
|
||||||
|
setup () {
|
||||||
|
|
||||||
|
const state = reactive({
|
||||||
|
a: 1,
|
||||||
|
b: {
|
||||||
|
c: 2
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// const rState1 = readonly(state)
|
||||||
|
const rState2 = shallowReadonly(state)
|
||||||
|
|
||||||
|
const update = () => {
|
||||||
|
// rState1.a++ // error
|
||||||
|
// rState1.b.c++ // error
|
||||||
|
|
||||||
|
// rState2.a++ // error
|
||||||
|
rState2.b.c++
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
state,
|
||||||
|
update
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 3) toRaw 与 markRaw
|
||||||
|
|
||||||
|
- toRaw
|
||||||
|
- 返回由 `reactive` 或 `readonly` 方法转换成响应式代理的普通对象。
|
||||||
|
- 这是一个还原方法,可用于临时读取,访问不会被代理/跟踪,写入时也不会触发界面更新。
|
||||||
|
- markRaw
|
||||||
|
- 标记一个对象,使其永远不会转换为代理。返回对象本身
|
||||||
|
- 应用场景:
|
||||||
|
- 有些值不应被设置为响应式的,例如复杂的第三方类实例或 Vue 组件对象。
|
||||||
|
- 当渲染具有不可变数据源的大列表时,跳过代理转换可以提高性能。
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<h2>{{state}}</h2>
|
||||||
|
<button @click="testToRaw">测试toRaw</button>
|
||||||
|
<button @click="testMarkRaw">测试markRaw</button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
/*
|
||||||
|
toRaw: 得到reactive代理对象的目标数据对象
|
||||||
|
*/
|
||||||
|
import {
|
||||||
|
markRaw,
|
||||||
|
reactive, toRaw,
|
||||||
|
} from 'vue'
|
||||||
|
export default {
|
||||||
|
setup () {
|
||||||
|
const state = reactive<any>({
|
||||||
|
name: 'tom',
|
||||||
|
age: 25,
|
||||||
|
})
|
||||||
|
|
||||||
|
const testToRaw = () => {
|
||||||
|
const user = toRaw(state)
|
||||||
|
user.age++ // 界面不会更新
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const testMarkRaw = () => {
|
||||||
|
const likes = ['a', 'b']
|
||||||
|
// state.likes = likes
|
||||||
|
state.likes = markRaw(likes) // likes数组就不再是响应式的了
|
||||||
|
setTimeout(() => {
|
||||||
|
state.likes[0] += '--'
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
state,
|
||||||
|
testToRaw,
|
||||||
|
testMarkRaw,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 4) toRef
|
||||||
|
|
||||||
|
- 为源响应式对象上的某个属性创建一个 ref对象, 二者内部操作的是同一个数据值, 更新时二者是同步的
|
||||||
|
- 区别ref: 拷贝了一份新的数据值单独操作, 更新时相互不影响
|
||||||
|
- 应用: 当要将 某个prop 的 ref 传递给复合函数时,toRef 很有用
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<h2>App</h2>
|
||||||
|
<p>{{state}}</p>
|
||||||
|
<p>{{foo}}</p>
|
||||||
|
<p>{{foo2}}</p>
|
||||||
|
|
||||||
|
<button @click="update">更新</button>
|
||||||
|
|
||||||
|
<Child :foo="foo"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
/*
|
||||||
|
toRef:
|
||||||
|
为源响应式对象上的某个属性创建一个 ref对象, 二者内部操作的是同一个数据值, 更新时二者是同步的
|
||||||
|
区别ref: 拷贝了一份新的数据值单独操作, 更新时相互不影响
|
||||||
|
应用: 当要将某个 prop 的 ref 传递给复合函数时,toRef 很有用
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
reactive,
|
||||||
|
toRef,
|
||||||
|
ref,
|
||||||
|
} from 'vue'
|
||||||
|
import Child from './Child.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
|
||||||
|
setup () {
|
||||||
|
|
||||||
|
const state = reactive({
|
||||||
|
foo: 1,
|
||||||
|
bar: 2
|
||||||
|
})
|
||||||
|
|
||||||
|
const foo = toRef(state, 'foo')
|
||||||
|
const foo2 = ref(state.foo)
|
||||||
|
|
||||||
|
const update = () => {
|
||||||
|
state.foo++
|
||||||
|
// foo.value++
|
||||||
|
// foo2.value++ // foo和state中的数据不会更新
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
state,
|
||||||
|
foo,
|
||||||
|
foo2,
|
||||||
|
update,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
components: {
|
||||||
|
Child
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<h2>Child</h2>
|
||||||
|
<h3>{{foo}}</h3>
|
||||||
|
<h3>{{length}}</h3>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { computed, defineComponent, Ref, toRef } from 'vue'
|
||||||
|
|
||||||
|
const component = defineComponent({
|
||||||
|
props: {
|
||||||
|
foo: {
|
||||||
|
type: Number,
|
||||||
|
require: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
setup (props, context) {
|
||||||
|
const length = useFeatureX(toRef(props, 'foo'))
|
||||||
|
|
||||||
|
return {
|
||||||
|
length
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
function useFeatureX(foo: Ref) {
|
||||||
|
const lenth = computed(() => foo.value.length)
|
||||||
|
|
||||||
|
return lenth
|
||||||
|
}
|
||||||
|
|
||||||
|
export default component
|
||||||
|
</script>
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 5) customRef
|
||||||
|
|
||||||
|
- 创建一个自定义的 ref,并对其依赖项跟踪和更新触发进行显式控制
|
||||||
|
- 需求: 使用 customRef 实现 debounce 的示例
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<h2>App</h2>
|
||||||
|
<input v-model="keyword" placeholder="搜索关键字"/>
|
||||||
|
<p>{{keyword}}</p>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
/*
|
||||||
|
customRef:
|
||||||
|
创建一个自定义的 ref,并对其依赖项跟踪和更新触发进行显式控制
|
||||||
|
|
||||||
|
需求:
|
||||||
|
使用 customRef 实现 debounce 的示例
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
ref,
|
||||||
|
customRef
|
||||||
|
} from 'vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
|
||||||
|
setup () {
|
||||||
|
const keyword = useDebouncedRef('', 500)
|
||||||
|
console.log(keyword)
|
||||||
|
return {
|
||||||
|
keyword
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
实现函数防抖的自定义ref
|
||||||
|
*/
|
||||||
|
function useDebouncedRef<T>(value: T, delay = 200) {
|
||||||
|
let timeout: number
|
||||||
|
return customRef((track, trigger) => {
|
||||||
|
return {
|
||||||
|
get() {
|
||||||
|
// 告诉Vue追踪数据
|
||||||
|
track()
|
||||||
|
return value
|
||||||
|
},
|
||||||
|
set(newValue: T) {
|
||||||
|
clearTimeout(timeout)
|
||||||
|
timeout = setTimeout(() => {
|
||||||
|
value = newValue
|
||||||
|
// 告诉Vue去触发界面更新
|
||||||
|
trigger()
|
||||||
|
}, delay)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 6) provide 与 inject
|
||||||
|
|
||||||
|
- provide` 和 `inject` 提供依赖注入,功能类似 2.x 的 `provide/inject
|
||||||
|
|
||||||
|
- 实现跨层级组件(祖孙)间通信
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<h1>父组件</h1>
|
||||||
|
<p>当前颜色: {{color}}</p>
|
||||||
|
<button @click="color='red'">红</button>
|
||||||
|
<button @click="color='yellow'">黄</button>
|
||||||
|
<button @click="color='blue'">蓝</button>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<Son />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { provide, ref } from 'vue'
|
||||||
|
/*
|
||||||
|
- provide` 和 `inject` 提供依赖注入,功能类似 2.x 的 `provide/inject
|
||||||
|
- 实现跨层级组件(祖孙)间通信
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Son from './Son.vue'
|
||||||
|
export default {
|
||||||
|
name: 'ProvideInject',
|
||||||
|
components: {
|
||||||
|
Son
|
||||||
|
},
|
||||||
|
setup() {
|
||||||
|
|
||||||
|
const color = ref('red')
|
||||||
|
|
||||||
|
provide('color', color)
|
||||||
|
|
||||||
|
return {
|
||||||
|
color
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h2>子组件</h2>
|
||||||
|
<hr>
|
||||||
|
<GrandSon />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import GrandSon from './GrandSon.vue'
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
GrandSon
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<h3 :style="{color}">孙子组件: {{color}}</h3>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { inject } from 'vue'
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
const color = inject('color')
|
||||||
|
|
||||||
|
return {
|
||||||
|
color
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 7) 响应式数据的判断
|
||||||
|
|
||||||
|
- isRef: 检查一个值是否为一个 ref 对象
|
||||||
|
- isReactive: 检查一个对象是否是由 `reactive` 创建的响应式代理
|
||||||
|
- isReadonly: 检查一个对象是否是由 `readonly` 创建的只读代理
|
||||||
|
- isProxy: 检查一个对象是否是由 `reactive` 或者 `readonly` 方法创建的代理
|
||||||
|
|
||||||
259
docs/chapter2/03_手写组合API.md
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
# 3. 手写组合API
|
||||||
|
|
||||||
|
## 1) shallowReactive 与 reactive
|
||||||
|
|
||||||
|
```js
|
||||||
|
const reactiveHandler = {
|
||||||
|
get (target, key) {
|
||||||
|
|
||||||
|
if (key==='_is_reactive') return true
|
||||||
|
|
||||||
|
return Reflect.get(target, key)
|
||||||
|
},
|
||||||
|
|
||||||
|
set (target, key, value) {
|
||||||
|
const result = Reflect.set(target, key, value)
|
||||||
|
console.log('数据已更新, 去更新界面')
|
||||||
|
return result
|
||||||
|
},
|
||||||
|
|
||||||
|
deleteProperty (target, key) {
|
||||||
|
const result = Reflect.deleteProperty(target, key)
|
||||||
|
console.log('数据已删除, 去更新界面')
|
||||||
|
return result
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
自定义shallowReactive
|
||||||
|
*/
|
||||||
|
function shallowReactive(obj) {
|
||||||
|
return new Proxy(obj, reactiveHandler)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
自定义reactive
|
||||||
|
*/
|
||||||
|
function reactive (target) {
|
||||||
|
if (target && typeof target==='object') {
|
||||||
|
if (target instanceof Array) { // 数组
|
||||||
|
target.forEach((item, index) => {
|
||||||
|
target[index] = reactive(item)
|
||||||
|
})
|
||||||
|
} else { // 对象
|
||||||
|
Object.keys(target).forEach(key => {
|
||||||
|
target[key] = reactive(target[key])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const proxy = new Proxy(target, reactiveHandler)
|
||||||
|
return proxy
|
||||||
|
}
|
||||||
|
|
||||||
|
return target
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 测试自定义shallowReactive */
|
||||||
|
const proxy = shallowReactive({
|
||||||
|
a: {
|
||||||
|
b: 3
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
proxy.a = {b: 4} // 劫持到了
|
||||||
|
proxy.a.b = 5 // 没有劫持到
|
||||||
|
|
||||||
|
|
||||||
|
/* 测试自定义reactive */
|
||||||
|
const obj = {
|
||||||
|
a: 'abc',
|
||||||
|
b: [{x: 1}],
|
||||||
|
c: {x: [11]},
|
||||||
|
}
|
||||||
|
|
||||||
|
const proxy = reactive(obj)
|
||||||
|
console.log(proxy)
|
||||||
|
proxy.b[0].x += 1
|
||||||
|
proxy.c.x[0] += 1
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 2) shallowRef 与 ref
|
||||||
|
|
||||||
|
```js
|
||||||
|
/*
|
||||||
|
自定义shallowRef
|
||||||
|
*/
|
||||||
|
function shallowRef(target) {
|
||||||
|
const result = {
|
||||||
|
_value: target, // 用来保存数据的内部属性
|
||||||
|
_is_ref: true, // 用来标识是ref对象
|
||||||
|
get value () {
|
||||||
|
return this._value
|
||||||
|
},
|
||||||
|
set value (val) {
|
||||||
|
this._value = val
|
||||||
|
console.log('set value 数据已更新, 去更新界面')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
自定义ref
|
||||||
|
*/
|
||||||
|
function ref(target) {
|
||||||
|
if (target && typeof target==='object') {
|
||||||
|
target = reactive(target)
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = {
|
||||||
|
_value: target, // 用来保存数据的内部属性
|
||||||
|
_is_ref: true, // 用来标识是ref对象
|
||||||
|
get value () {
|
||||||
|
return this._value
|
||||||
|
},
|
||||||
|
set value (val) {
|
||||||
|
this._value = val
|
||||||
|
console.log('set value 数据已更新, 去更新界面')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 测试自定义shallowRef */
|
||||||
|
const ref3 = shallowRef({
|
||||||
|
a: 'abc',
|
||||||
|
})
|
||||||
|
ref3.value = 'xxx'
|
||||||
|
ref3.value.a = 'yyy'
|
||||||
|
|
||||||
|
|
||||||
|
/* 测试自定义ref */
|
||||||
|
const ref1 = ref(0)
|
||||||
|
const ref2 = ref({
|
||||||
|
a: 'abc',
|
||||||
|
b: [{x: 1}],
|
||||||
|
c: {x: [11]},
|
||||||
|
})
|
||||||
|
ref1.value++
|
||||||
|
ref2.value.b[0].x++
|
||||||
|
console.log(ref1, ref2)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 3) shallowReadonly 与 readonly
|
||||||
|
|
||||||
|
```js
|
||||||
|
const readonlyHandler = {
|
||||||
|
get (target, key) {
|
||||||
|
if (key==='_is_readonly') return true
|
||||||
|
|
||||||
|
return Reflect.get(target, key)
|
||||||
|
},
|
||||||
|
|
||||||
|
set () {
|
||||||
|
console.warn('只读的, 不能修改')
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
|
||||||
|
deleteProperty () {
|
||||||
|
console.warn('只读的, 不能删除')
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
自定义shallowReadonly
|
||||||
|
*/
|
||||||
|
function shallowReadonly(obj) {
|
||||||
|
return new Proxy(obj, readonlyHandler)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
自定义readonly
|
||||||
|
*/
|
||||||
|
function readonly(target) {
|
||||||
|
if (target && typeof target==='object') {
|
||||||
|
if (target instanceof Array) { // 数组
|
||||||
|
target.forEach((item, index) => {
|
||||||
|
target[index] = readonly(item)
|
||||||
|
})
|
||||||
|
} else { // 对象
|
||||||
|
Object.keys(target).forEach(key => {
|
||||||
|
target[key] = readonly(target[key])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const proxy = new Proxy(target, readonlyHandler)
|
||||||
|
|
||||||
|
return proxy
|
||||||
|
}
|
||||||
|
|
||||||
|
return target
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 测试自定义readonly */
|
||||||
|
/* 测试自定义shallowReadonly */
|
||||||
|
const objReadOnly = readonly({
|
||||||
|
a: {
|
||||||
|
b: 1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const objReadOnly2 = shallowReadonly({
|
||||||
|
a: {
|
||||||
|
b: 1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
objReadOnly.a = 1
|
||||||
|
objReadOnly.a.b = 2
|
||||||
|
objReadOnly2.a = 1
|
||||||
|
objReadOnly2.a.b = 2
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 4) isRef, isReactive 与 isReadonly
|
||||||
|
|
||||||
|
```js
|
||||||
|
/*
|
||||||
|
判断是否是ref对象
|
||||||
|
*/
|
||||||
|
function isRef(obj) {
|
||||||
|
return obj && obj._is_ref
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
判断是否是reactive对象
|
||||||
|
*/
|
||||||
|
function isReactive(obj) {
|
||||||
|
return obj && obj._is_reactive
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
判断是否是readonly对象
|
||||||
|
*/
|
||||||
|
function isReadonly(obj) {
|
||||||
|
return obj && obj._is_readonly
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
是否是reactive或readonly产生的代理对象
|
||||||
|
*/
|
||||||
|
function isProxy (obj) {
|
||||||
|
return isReactive(obj) || isReadonly(obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 测试判断函数 */
|
||||||
|
console.log(isReactive(reactive({})))
|
||||||
|
console.log(isRef(ref({})))
|
||||||
|
console.log(isReadonly(readonly({})))
|
||||||
|
console.log(isProxy(reactive({})))
|
||||||
|
console.log(isProxy(readonly({})))
|
||||||
|
```
|
||||||
23
docs/chapter2/04_Composition VS Option.md
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# 4. Composition API VS Option API
|
||||||
|
|
||||||
|
## 1) Option API的问题
|
||||||
|
|
||||||
|
- 在传统的Vue OptionsAPI中,新增或者修改一个需求,就需要分别在data,methods,computed里修改 ,滚动条反复上下移动
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 2) 使用Compisition API
|
||||||
|
|
||||||
|
我们可以更加优雅的组织我们的代码,函数。让相关功能的代码更加有序的组织在一起
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|

|
||||||
194
docs/chapter3/01_新组件.md
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
# 1. 新组件
|
||||||
|
|
||||||
|
## 1) Fragment(片断)
|
||||||
|
|
||||||
|
- 在Vue2中: 组件必须有一个根标签
|
||||||
|
- 在Vue3中: 组件可以没有根标签, 内部会将多个标签包含在一个Fragment虚拟元素中
|
||||||
|
- 好处: 减少标签层级, 减小内存占用
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<h2>aaaa</h2>
|
||||||
|
<h2>aaaa</h2>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 2) Teleport(瞬移)
|
||||||
|
|
||||||
|
- Teleport 提供了一种干净的方法, 让组件的html在父组件界面外的特定标签(很可能是body)下插入显示
|
||||||
|
|
||||||
|
ModalButton.vue
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<button @click="modalOpen = true">
|
||||||
|
Open full screen modal! (With teleport!)
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<teleport to="body">
|
||||||
|
<div v-if="modalOpen" class="modal">
|
||||||
|
<div>
|
||||||
|
I'm a teleported modal!
|
||||||
|
(My parent is "body")
|
||||||
|
<button @click="modalOpen = false">
|
||||||
|
Close
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</teleport>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
export default {
|
||||||
|
name: 'modal-button',
|
||||||
|
setup () {
|
||||||
|
const modalOpen = ref(false)
|
||||||
|
return {
|
||||||
|
modalOpen
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.modal {
|
||||||
|
position: absolute;
|
||||||
|
top: 0; right: 0; bottom: 0; left: 0;
|
||||||
|
background-color: rgba(0,0,0,.5);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal div {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background-color: white;
|
||||||
|
width: 300px;
|
||||||
|
height: 300px;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
```
|
||||||
|
|
||||||
|
App.vue
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<h2>App</h2>
|
||||||
|
<modal-button></modal-button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import ModalButton from './ModalButton.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
return {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
components: {
|
||||||
|
ModalButton
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 3) Suspense(不确定的)
|
||||||
|
|
||||||
|
- 它们允许我们的应用程序在等待异步组件时渲染一些后备内容,可以让我们创建一个平滑的用户体验
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<Suspense>
|
||||||
|
<template v-slot:default>
|
||||||
|
<AsyncComp/>
|
||||||
|
<!-- <AsyncAddress/> -->
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-slot:fallback>
|
||||||
|
<h1>LOADING...</h1>
|
||||||
|
</template>
|
||||||
|
</Suspense>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
/*
|
||||||
|
异步组件 + Suspense组件
|
||||||
|
*/
|
||||||
|
// import AsyncComp from './AsyncComp.vue'
|
||||||
|
import AsyncAddress from './AsyncAddress.vue'
|
||||||
|
import { defineAsyncComponent } from 'vue'
|
||||||
|
const AsyncComp = defineAsyncComponent(() => import('./AsyncComp.vue'))
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
return {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
components: {
|
||||||
|
AsyncComp,
|
||||||
|
AsyncAddress
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
- AsyncComp.vue
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<h2>AsyncComp22</h2>
|
||||||
|
<p>{{msg}}</p>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'AsyncComp',
|
||||||
|
setup () {
|
||||||
|
// return new Promise((resolve, reject) => {
|
||||||
|
// setTimeout(() => {
|
||||||
|
// resolve({
|
||||||
|
// msg: 'abc'
|
||||||
|
// })
|
||||||
|
// }, 2000)
|
||||||
|
// })
|
||||||
|
return {
|
||||||
|
msg: 'abc'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
- AsyncAddress.vue
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<h2>{{data}}</h2>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import axios from 'axios'
|
||||||
|
export default {
|
||||||
|
async setup() {
|
||||||
|
const result = await axios.get('/data/address.json')
|
||||||
|
return {
|
||||||
|
data: result.data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
22
docs/chapter3/02_全局API更新.md
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# 2. 全局API更新
|
||||||
|
## 全新的全局API
|
||||||
|
- createApp()
|
||||||
|
- defineProperty()
|
||||||
|
- defineAsyncComponent()
|
||||||
|
- nextTick()
|
||||||
|
|
||||||
|
## 将原来的全局API转移到应用对象
|
||||||
|
- app.component()
|
||||||
|
- app.config()
|
||||||
|
- app.directive()
|
||||||
|
- app.mount()
|
||||||
|
- app.unmount()
|
||||||
|
- app.use()
|
||||||
|
|
||||||
|
## 模板语法变化
|
||||||
|
- v-model的本质变化
|
||||||
|
- prop:value -> modelValue;
|
||||||
|
- event:input -> update:modelValue;
|
||||||
|
- .sync修改符已移除, 由v-model代替
|
||||||
|
- <ChildComponent v-model:title="pageTitle" v-model:content="pageContent" />
|
||||||
|
- v-if优先v-for解析
|
||||||
1
docs/chapter4/README.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# TODO LIST
|
||||||
BIN
docs/images/composition API VS Option API_r.jpg
Normal file
|
After Width: | Height: | Size: 123 KiB |
BIN
docs/images/lifecycle_2.png
Normal file
|
After Width: | Height: | Size: 49 KiB |
BIN
docs/images/lifecycle_3.png
Normal file
|
After Width: | Height: | Size: 399 KiB |
BIN
docs/images/option API.gif
Normal file
|
After Width: | Height: | Size: 2.4 MiB |
BIN
docs/images/option API2.gif
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
docs/images/基于函数组合的API.gif
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
docs/images/基于函数组合的API2.gif
Normal file
|
After Width: | Height: | Size: 1004 KiB |
12861
package-lock.json
generated
Normal file
30
package.json
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"name": "vue3-docs",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "cross-env NODE_ENV=development webpack-dev-server --config build/webpack.config.js",
|
||||||
|
"build": "cross-env NODE_ENV=production webpack --config build/webpack.config.js",
|
||||||
|
"doc:dev": "vuepress dev docs",
|
||||||
|
"doc:build": "vuepress build docs",
|
||||||
|
"doc:deploy": "gh-pages -d docs/dist"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/jquery": "^3.5.1",
|
||||||
|
"clean-webpack-plugin": "^3.0.0",
|
||||||
|
"cross-env": "^7.0.0",
|
||||||
|
"gh-pages": "^2.2.0",
|
||||||
|
"html-webpack-plugin": "^3.2.0",
|
||||||
|
"ts-loader": "^6.2.1",
|
||||||
|
"typescript": "^3.7.5",
|
||||||
|
"webpack": "^4.41.5",
|
||||||
|
"webpack-cli": "^3.3.10",
|
||||||
|
"webpack-dev-server": "^3.10.2",
|
||||||
|
"vuepress": "1.3.0"
|
||||||
|
},
|
||||||
|
"dependencies": {}
|
||||||
|
}
|
||||||
12
public/index.html
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||||
|
<title>TS App</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script src="../node_modules/jquery/dist/jquery.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
1
src/main.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
document.write('Hello Vue3')
|
||||||
66
tsconfig.json
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
/* Basic Options */
|
||||||
|
// "incremental": true, /* Enable incremental compilation */
|
||||||
|
"target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
|
||||||
|
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
||||||
|
// "lib": [], /* Specify library files to be included in the compilation. */
|
||||||
|
// "allowJs": true, /* Allow javascript files to be compiled. */
|
||||||
|
// "checkJs": true, /* Report errors in .js files. */
|
||||||
|
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
||||||
|
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||||
|
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||||
|
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
||||||
|
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||||
|
"outDir": "./js", /* Redirect output structure to the directory. */
|
||||||
|
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||||
|
// "composite": true, /* Enable project compilation */
|
||||||
|
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
||||||
|
// "removeComments": true, /* Do not emit comments to output. */
|
||||||
|
// "noEmit": true, /* Do not emit outputs. */
|
||||||
|
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||||
|
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||||
|
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||||
|
|
||||||
|
/* Strict Type-Checking Options */
|
||||||
|
"strict": false, /* Enable all strict type-checking options. */
|
||||||
|
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||||
|
// "strictNullChecks": true, /* Enable strict null checks. */
|
||||||
|
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
|
||||||
|
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
|
||||||
|
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
||||||
|
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
||||||
|
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||||
|
|
||||||
|
/* Additional Checks */
|
||||||
|
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
||||||
|
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||||
|
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||||
|
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||||
|
|
||||||
|
/* Module Resolution Options */
|
||||||
|
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||||
|
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
||||||
|
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||||
|
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||||
|
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||||
|
// "types": [], /* Type declaration files to be included in compilation. */
|
||||||
|
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||||
|
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||||
|
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||||
|
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||||
|
|
||||||
|
/* Source Map Options */
|
||||||
|
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
||||||
|
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||||
|
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
||||||
|
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
||||||
|
|
||||||
|
/* Experimental Options */
|
||||||
|
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||||
|
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||||
|
|
||||||
|
/* Advanced Options */
|
||||||
|
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
|
||||||
|
}
|
||||||
|
}
|
||||||