├── .gitignore
├── README.md
├── package.json
├── public
└── index.html
├── src
├── App.vue
├── components
│ ├── Menu.js
│ ├── MyButton.vue
│ ├── Position.js
│ └── child.vue
├── main.js
├── router
│ └── index.js
└── views
│ ├── About.vue
│ ├── Computed.vue
│ ├── Dad.vue
│ ├── Father.vue
│ ├── Home.vue
│ ├── Life.vue
│ └── Parent.vue
└── webpack.config.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | dist/
4 | tmp/
5 | log/
6 | static/upfiles/*
7 | npm-debug.log*
8 | yarn-debug.log*
9 | yarn-error.log*
10 | **/*.log
11 |
12 | tests/**/coverage/
13 | tests/e2e/reports
14 | selenium-debug.log
15 |
16 | # Editor directories and files
17 | .idea
18 | .vscode
19 | *.suo
20 | *.ntvs*
21 | *.njsproj
22 | *.sln
23 | *.local
24 |
25 | package-lock.json
26 | yarn.lock
27 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vue3.0 Composition API 入门教程
2 |
3 | 光阴荏苒,vue3.0已经进入了 beta 版本了。很多朋友说,你该出个系列的教程了,毕竟当年我写得 vue 2.0 的系列的博文在网上影响并不小。那就写吧,我力求简洁明了的把新的知识点都覆盖到。
4 |
5 | ## 安装以及运行
6 |
7 | ```bash
8 | # clone 项目
9 | git clone https://github.com/fengcms/vue3-demo
10 | # 进入项目文件夹
11 | cd vue3-demo
12 | # 安装依赖
13 | npm i
14 | # 运行开发环境
15 | npm run dev
16 | # 编译代码
17 | npm run build
18 | ```
19 |
20 | 文章目录地址 https://blog.csdn.net/fungleo/category_10020552.html
21 |
22 | ## 文章目录:
23 |
24 | 1. [vue3.0 Composition API 上手初体验 构建基本项目开发环境](https://blog.csdn.net/FungLeo/article/details/106208252)
25 | 2. [vue3.0 Composition API 上手初体验 构建 vue 基础代码](https://blog.csdn.net/FungLeo/article/details/106208323)
26 | 3. [vue3.0 Composition API 上手初体验 使用 vue-router 构建多页面应用](https://blog.csdn.net/FungLeo/article/details/106208378)
27 | 4. [vue3.0 Composition API 上手初体验 神奇的 setup 函数 (一) 响应数据的绑定](https://blog.csdn.net/FungLeo/article/details/106208437)
28 | 5. [vue3.0 Composition API 上手初体验 神奇的 setup 函数 (二) 响应对象数据的绑定](https://blog.csdn.net/FungLeo/article/details/106208494)
29 | 6. [vue3.0 Composition API 上手初体验 神奇的 setup 函数 (三) 生命周期函数](https://blog.csdn.net/FungLeo/article/details/106208514)
30 | 7. [vue3.0 Composition API 上手初体验 神奇的 setup 函数 (四) 计算属性 computed](https://blog.csdn.net/FungLeo/article/details/106208574)
31 | 8. [vue3.0 Composition API 上手初体验 普通组件的开发与使用](https://blog.csdn.net/FungLeo/article/details/106208611)
32 | 9. [vue3.0 Composition API 上手初体验 vue组件的具名插槽 slot 的变化](https://blog.csdn.net/FungLeo/article/details/106215722)
33 | 10. [vue3.0 Composition API 上手初体验 函数组件的开发与使用](https://blog.csdn.net/FungLeo/article/details/106208639)
34 | 11. [vue3.0 Composition API 上手初体验 用路由循环,做个导航菜单](https://blog.csdn.net/FungLeo/article/details/106211657)
35 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue3-demo",
3 | "version": "1.0.0",
4 | "description": "一个基于vue3的demo演示",
5 | "main": "webpack.config.js",
6 | "scripts": {
7 | "dev": "webpack-dev-server",
8 | "build": "webpack --env.prod"
9 | },
10 | "keywords": [
11 | "vue3"
12 | ],
13 | "author": "FungLeo",
14 | "license": "MIT",
15 | "dependencies": {
16 | "vue": "^3.0.0-beta.13",
17 | "vue-router": "^4.0.0-alpha.11"
18 | },
19 | "devDependencies": {
20 | "@vue/compiler-sfc": "^3.0.0-beta.13",
21 | "clean-webpack-plugin": "^3.0.0",
22 | "css-loader": "^3.5.3",
23 | "html-webpack-plugin": "^4.3.0",
24 | "node-sass": "^4.14.1",
25 | "sass-loader": "^8.0.2",
26 | "style-loader": "^1.2.1",
27 | "vue-loader": "^16.0.0-beta.2",
28 | "webpack": "^4.43.0",
29 | "webpack-cli": "^3.3.11",
30 | "webpack-dev-server": "^3.11.0"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | VUE 3.0 Demo
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 | {{ item.name }}
6 |
7 |
8 |
9 |
10 |
11 |
12 |
26 |
--------------------------------------------------------------------------------
/src/components/Menu.js:
--------------------------------------------------------------------------------
1 | // 引入路由
2 | import router from '@/router'
3 | // 导出为函数
4 | export default () => {
5 | // 通过 getRoutes() 函数,获取所有的路由信息
6 | const routes = router.getRoutes()
7 | console.log(routes)
8 | const links = []
9 | // 循环路由信息,将数据整理并 push 到 links 数组
10 | routes.forEach((route, index) => {
11 | links.push({
12 | name: route.meta.title || `未命名${index}`,
13 | link: route.path
14 | })
15 | })
16 | // 将 links 数组返回
17 | return links
18 | }
19 |
--------------------------------------------------------------------------------
/src/components/MyButton.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
15 |
52 |
91 |
--------------------------------------------------------------------------------
/src/components/Position.js:
--------------------------------------------------------------------------------
1 | // 函数式组件, 该组件会返回鼠标在屏幕上的坐标值
2 | // toFefs 是将 reactive 对象的所有 key 都转化为 ref 值
3 | // 这样,在引入使用的组件中,就可以 用 const { x, y } = xx 来使用这些 key 对应的 value 了
4 | import { onMounted, onUnmounted, reactive, toRefs } from 'vue'
5 |
6 | // 这里导出,就不是对象,而是一个函数了。
7 | export default () => {
8 | // 定义一个准备导出的对象数据
9 | const position = reactive({
10 | x: 0,
11 | y: 0
12 | })
13 | // 定义一个会改变数据的函数
14 | const update = page => {
15 | position.x = page.pageX
16 | position.y = page.pageY
17 | }
18 | // 使用生命周期,绑定和移除事件
19 | onMounted (() => {
20 | window.addEventListener('mousemove', update)
21 | })
22 | onUnmounted (() => {
23 | window.removeEventListener('mousemove', update)
24 | })
25 | // 将 reactive 对象 转化为 ref 响应式的值,并返回
26 | return toRefs(position)
27 | }
28 |
--------------------------------------------------------------------------------
/src/components/child.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 默认插槽: |
5 | |
6 |
7 |
8 | 具名插槽: |
9 | |
10 |
11 |
12 | 传参插槽: |
13 | |
14 |
15 |
16 | 传对象参插槽: |
17 | |
18 |
19 |
20 | 换个语法传参: |
21 |
22 | |
23 |
24 |
25 |
26 |
37 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import App from './App.vue'
3 | import router from './router'
4 |
5 | // 将创建的 App 搞个别名
6 | const app = createApp(App)
7 |
8 | // 使用路由配置
9 | app.use(router)
10 |
11 | // 挂载运行
12 | app.mount('#app')
13 |
--------------------------------------------------------------------------------
/src/router/index.js:
--------------------------------------------------------------------------------
1 | // 可以根据路由模式的不同,后面俩可以只引用一个
2 | import { createRouter, createWebHistory, createWebHashHistory } from 'vue-router'
3 | import Home from '@/views/Home.vue'
4 |
5 | // 构建我们的页面路由配置,可以看到,这里和原来的写法并无二致。
6 | const routes = [
7 | {
8 | path: '/',
9 | component: Home,
10 | meta: { title: '首页-响应式数据计数器 Demo' }
11 | }, {
12 | path: '/about',
13 | component: () => import('@/views/About.vue'),
14 | meta: { title: '关于我们-响应式对象数据 Demo' }
15 | }, {
16 | path: '/life',
17 | component: () => import('@/views/Life.vue'),
18 | meta: { title: '生命周期 Demo' }
19 | }, {
20 | path: '/computed',
21 | component: () => import('@/views/Computed.vue'),
22 | meta: { title: '计算属性 Demo' }
23 | }, {
24 | path: '/parent',
25 | component: () => import('@/views/Parent.vue'),
26 | meta: { title: '普通组件 Demo' }
27 | }, {
28 | path: '/father',
29 | component: () => import('@/views/Father.vue'),
30 | meta: { title: '函数组件 Demo' }
31 | }, {
32 | path: '/dad',
33 | component: () => import('@/views/Dad.vue'),
34 | meta: { title: '具名插槽组件 Demo' }
35 | }
36 | ]
37 |
38 | // 用 history 模式构建路由
39 | // const routerHistory = createWebHistory()
40 |
41 | const router = createRouter({
42 | // 使用 hash 模式构建路由( url中带 # 号的那种)
43 | history: createWebHashHistory(),
44 | // 使用 history 模式构建路由 ( url 中没有 # 号,但生产环境需要特殊配置)
45 | // history: createWebHistory(),
46 | routes
47 | })
48 | export default router
49 |
--------------------------------------------------------------------------------
/src/views/About.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | - {{state.name}}
4 | - 性别:{{state.sex}}
5 | - 地址:{{state.address}}
6 |
7 |
8 |
9 |
34 |
--------------------------------------------------------------------------------
/src/views/Computed.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 这里是一个计数器 >>> {{count}}
4 | 右边的数字是上面的数字的十倍 >>> {{bigCount}}
5 | 右边的数字是上面的数字的一百倍 >>> {{computeCount['100x']}}
6 | 右边的数字是上面的数字的一千倍 >>> {{computeCount['1000x']}}
7 |
8 |
9 |
10 |
11 |
44 |
--------------------------------------------------------------------------------
/src/views/Dad.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 这些文字将显示在组件默认插槽内
4 |
5 | 这里的文字会显示在组件的具名插槽内
6 |
7 |
8 | 文字右边会有个颜色值 >>> {{scope.color}}
9 |
10 |
11 | 文字右边会有多个数据 >>> 名字:{{scope.name}},年龄:{{scope.old}}
12 |
13 |
14 |
15 |
21 |
--------------------------------------------------------------------------------
/src/views/Father.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 鼠标 x 轴 坐标 >>> {{ x }}
4 | 鼠标 y 轴 坐标 >>> {{ y }}
5 |
6 |
7 |
19 |
--------------------------------------------------------------------------------
/src/views/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 这里是一个计数器 >>> {{count}}
4 |
5 |
6 |
7 |
8 |
31 |
42 |
--------------------------------------------------------------------------------
/src/views/Life.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 这里是一个计数器 >>> {{count}}
4 |
5 |
6 |
7 |
58 |
--------------------------------------------------------------------------------
/src/views/Parent.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 这里是一个计数器 >>> {{count}}
4 |
5 |
6 | 点这个按钮上面的数字会变
7 |
8 |
9 |
10 |
35 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const { VueLoaderPlugin } = require('vue-loader')
3 | const HtmlWebpackPlugin = require('html-webpack-plugin')
4 | const { CleanWebpackPlugin } = require('clean-webpack-plugin')
5 |
6 | module.exports = (env = {}) => ({
7 | mode: env.prod ? 'production' : 'development',
8 | devtool: env.prod ? 'source-map' : 'inline-source-map',
9 | entry: path.resolve(__dirname, './src/main.js'),
10 | output: {
11 | path: path.resolve(__dirname, './dist'),
12 | publicPath: '/'
13 | },
14 | resolve: {
15 | alias: {
16 | 'vue': '@vue/runtime-dom',
17 | '@': path.resolve(__dirname, './src')
18 | }
19 | },
20 | module: {
21 | rules: [
22 | {
23 | test: /\.vue$/,
24 | use: 'vue-loader'
25 | }, {
26 | test: /\.css$/,
27 | use: ['style-loader', 'css-loader']
28 | }, {
29 | test: /\.scss$/,
30 | use: ['style-loader', 'css-loader', 'sass-loader']
31 | }
32 | ]
33 | },
34 | plugins: [
35 | new VueLoaderPlugin(),
36 | new CleanWebpackPlugin(),
37 | new HtmlWebpackPlugin({
38 | template: path.resolve(__dirname, './public/index.html'),
39 | filename: 'index.html'
40 | })
41 | ],
42 | devServer: {
43 | publicPath: '/',
44 | inline: true,
45 | hot: true,
46 | stats: 'minimal',
47 | contentBase: __dirname,
48 | overlay: true,
49 | historyApiFallback: true
50 | }
51 | })
52 |
--------------------------------------------------------------------------------