DC's blog DC's blog
首页
  • 计算机基础
  • linux基础
  • mysql
  • git
  • 数据结构与算法
  • axure
  • english
  • docker
  • opp
  • oop
  • 网络并发编程
  • 不基础的py基础
  • 设计模式
  • html
  • css
  • javascript
  • jquery
  • UI
  • 第一次学vue
  • 第二次学vue
  • Django
  • drf
  • drf_re
  • 温故知新
  • flask
  • 前后端不分离

    • BBS
    • 订单系统
    • CRM
  • 前后端部分分离

    • pear-admin-flask
    • pear-admin-django
  • 前后端分离

    • 供应链系统
  • 理论基础
  • py数据分析包
  • 机器学习
  • 深度学习
  • 华中科大的网课
  • cursor
  • deepseek
  • 杂文
  • 罗老师语录
  • 关于我

    • me
  • 分类
  • 归档
GitHub (opens new window)

DC

愿我一生欢喜,不为世俗所及.
首页
  • 计算机基础
  • linux基础
  • mysql
  • git
  • 数据结构与算法
  • axure
  • english
  • docker
  • opp
  • oop
  • 网络并发编程
  • 不基础的py基础
  • 设计模式
  • html
  • css
  • javascript
  • jquery
  • UI
  • 第一次学vue
  • 第二次学vue
  • Django
  • drf
  • drf_re
  • 温故知新
  • flask
  • 前后端不分离

    • BBS
    • 订单系统
    • CRM
  • 前后端部分分离

    • pear-admin-flask
    • pear-admin-django
  • 前后端分离

    • 供应链系统
  • 理论基础
  • py数据分析包
  • 机器学习
  • 深度学习
  • 华中科大的网课
  • cursor
  • deepseek
  • 杂文
  • 罗老师语录
  • 关于我

    • me
  • 分类
  • 归档
GitHub (opens new window)
  • html

  • css

  • javascript

  • jquery

  • UI库

  • 第一次学vue

    • 基础语法(1)
    • 基础语法(2)
    • Vue生命期钩子
    • 基础语法(3)
    • Vue-cli
      • vue-cli
        • 搭建nodejs环境
        • 安装vue-cli
        • 创建vue项目
        • 方式一 cmd里
        • 方式二 浏览器里
        • 运行vue项目
        • 终端运行命令
        • 绿箭头
      • Vue项目目录
      • 如何运作的?
        • main.js与index.html
        • 组件的三部分
      • vue项目中组件通信
        • 示例代码
        • 代码逻辑
        • 执行结果
        • props配置项
      • es6导入导出
      • mixin混入
        • 最初的代码
        • 使用混入
        • 全局注册
        • 局部注册
      • 插槽的使用
      • 存储数据
      • vue3的变化
        • 创建vue3的项目
        • webstorm里
        • 使用vite
        • 组合式API
        • 生命周期
        • toRefs
    • 插件的使用(1)
    • 插件的使用(2)
    • 总结
  • 第二次学vue

  • 前端
  • 第一次学vue
DC
2023-11-29
目录

Vue-cli

# vue-cli

vue-cli脚手架 - 可以帮助我们快速搭建出Vue项目.

注意: vue2中,都是使用vue-cli ; vue3中,可以使用vue-cli搭建,但官方更推荐使用vite来搭建,因为它更快更小巧.

# 搭建nodejs环境

Vue-cli依赖一门后端解释性语言nodejs, So, 需要先安装解释器!!

下载nodejs的解释器地址: https://nodejs.org/en/download (LTS长期支持的版本,Current最新版本 - 选LTS)
一路点击下一步,无需额外的操作.
"""
This package has installed:
	•	Node.js v18.18.0 to /usr/local/bin/node
	•	npm v9.8.1 to /usr/local/bin/npm
Make sure that /usr/local/bin is in your $PATH.
""" Node相当于python,npm相当于pip!!

dengchuan@MacBook-Air ~ % node -v
v18.18.0
dengchuan@MacBook-Air ~ % node
Welcome to Node.js v18.18.0.
Type ".help" for more information.
> console.log("Hello World!")
Hello World!
undefined
> .exit
dengchuan@MacBook-Air ~ % npm -v
9.8.1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

有些时候给npm或node命令升级后可能会导致node和npm版本不对应. 解决办法, 重新搭建node环境!!

该网址可查看nodejs版本相对应的node版本 -- https://nodejs.org/en/download/releases/
  
若想更新node.js的版本到最新,mac需要这么做:
1.先查看本机node.js版本: node -v
2.清除node.js的cache: sudo npm cache clean -f
3.安装 n 工具,这个工具是专门用来管理node.js版本的, 别怀疑这个工具的名字,是他是他就是他,他的名字就是"n"
	sudo npm install -g n
4.安装最新版本的node.js
	sudo n stable
5.再次查看本机的node.js版本:
	node -v
  
若想更新npm的版本到最新,mac需要这么做:
1. sudo npm install npm@latest -g
2. 为了提高速度,你可以这样做:
   npm config set registry https://registry.npm.taobao.org
   npm install -g cnpm --registry=https://registry.npm.taobao.org
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

image-20231013191337400

# 安装vue-cli

直接通过 npm install -g @vue/cli 来安装脚手架很慢, 因为要访问国外的资源.
我们可以使用淘宝镜像定制的cnpm来替代npm, 达到加速的效果!!

执行命令:
  sudo npm install -g cnpm --registry=https://registry.npm.taobao.org
  执行完后,在终端上就有两个命令可用于安装第三方模块啦! 1> npm 安装速度慢 2> cnpm 安装速度快,使用它!!
  
执行命令:
  sudo cnpm install -g @vue/cli
  执行完后,vue-cli脚手架就安装好啦! 安装完脚手架后,就会有个vue命令!!

  Ps:安装指定版本的脚手架 sudo npm install -g @vue/cli@5.0.8
     卸载 sudo npm uninstall -g @vue/cli
     查看全局安装哪些包 npm list -g

""" 该命令执行成功,则证明vue-cli脚手脚安装成功!
dengchuan@MacBook-Air ~ % vue -V
@vue/cli 5.0.8
"""
注: 若安装cnpm和vue脚手架出错,清除缓存后重新安装!清楚缓存的命令: npm cache clean --force
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 创建vue项目

后续我们开发项目用vue3!! 示例中是选择vue2作为示范的, 无伤大雅, vue2上所有的写法都能在vue3上完美运行成功.

# 方式一 cmd里

通过vue create命令创建vue项目. 示例中选择的是vue2,当然我们可以选vue3.

# ★ 注意,新建的项目会创建在当前路径下 ; 注意,加上sudo!!
dengchuan@MacBook-Air Desktop % sudo vue create myfirstvue
?  Your connection to the default npm registry seems to be slow.
   Use https://registry.npmmirror.com for faster installation? Yes

# 键盘上下键移动选第三个,自定义,安装什么自己决定!选中后敲回车.
Vue CLI v5.0.8
? Please pick a preset: 
  Default ([Vue 3] babel, eslint) 
  Default ([Vue 2] babel, eslint) 
❯ Manually select features 

# 上下键移动,按空格选中与取消选中. 这里,我们选Balel、Router、Vuex这三个第三方组件! 敲击回车到下一步.
# Balel  高版本es语法转化 - 在vue项目中可以写高版本的es语法,它会自动转化成es5的语法,来兼容一些不支持es高版本语法的浏览器!
# Router 路由
# Vuex   状态管理器,简单理解:就是一个存放变量的地方.但浏览器关闭的话,该变量就没啦!
# ★ Router和vuex是写vue项目必用的!!
Vue CLI v5.0.8
? Please pick a preset: Manually select features
? Check the features needed for your project: (Press <space> to select, <a> to toggle all, <i> to invert selection, and <enter> to proceed)
❯◉ Babel
 ◯ TypeScript
 ◯ Progressive Web App (PWA) Support
 ◉ Router
 ◉ Vuex
 ◯ CSS Pre-processors
 ◯ Linter / Formatter
 ◯ Unit Testing
 ◯ E2E Testing
 
 
# 选择vue的版本,学习为主,此处先选2.x的版本, 3.x与2.x其实差不了多少.
Vue CLI v5.0.8
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, Router, Vuex
? Choose a version of Vue.js that you want to start the project with (Use arrow keys)
  3.x 
❯ 2.x 

# 包管理文件选择package.json -- 它类比于 Django项目中的reqirement.txt
Vue CLI v5.0.8
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, Router, Vuex
? Choose a version of Vue.js that you want to start the project with 2.x
? Use history mode for router? (Requires proper server setup for index fallback in production) Yes
? Where do you prefer placing config for Babel, ESLint, etc.? 
  In dedicated config files 
❯ In package.json 

# 它在问你,这些配置要保存吗?保存后用于下一次创建新项目时使用. 选择No就行
Vue CLI v5.0.8
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, Router, Vuex
? Choose a version of Vue.js that you want to start the project with 2.x
? Use history mode for router? (Requires proper server setup for index fallback in production) Yes
? Where do you prefer placing config for Babel, ESLint, etc.? In package.json
? Save this as a preset for future projects? (y/N) N


# 展示下方的结果,表明vue项目创建成功!
Vue CLI v5.0.8
✨  Creating project in /Users/dengchuan/Desktop/myfirstvue.
🗃  Initializing git repository...
⚙️  Installing CLI plugins. This might take a while...

added 846 packages in 14s
🚀  Invoking generators...
📦  Installing additional dependencies...

added 7 packages in 2s
⚓  Running completion hooks...

📄  Generating README.md...

🎉  Successfully created project myfirstvue.
👉  Get started with the following commands:

 $ cd myfirstvue
 $ npm run serve
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# 方式二 浏览器里

还可以通过 vue ui 命令图形化界面里创建项目. 示例中选择的是vue2,当然我们可以选vue3.

vue ui # -- 图形化界面里创建
   - 选择创建项目的路径
   - 创建新项目
     - 包管理器选择npm (不选也行默认就是npm)
   - 选择手动, 手动配置项目
     - 选择功能/第三方模块
       Babel              它会将项目中ES6,ES7等新语法转成ES5的语法,实现对低版本浏览器语法的兼容
       Router             路由 
       VueX               状态管理器,简单理解:就是一个存放变量的地方.但浏览器关闭的话,该变量就没啦!
     - 版本选择2.x
   - 保存新预设,随便写个名字,下次创建vue项目时,选它,就有此次创建项目时的这些配置.
1
2
3
4
5
6
7
8
9
10
11

# 运行vue项目

项目创建好后, 用编译器打开项目!

# 终端运行命令

方式一: 在编译器终端里允许命令,记得加上sudo!!不然权限不够,编译会失败的.

dengchuan@MacBook-Air myfirstvue % sudo npm run serve

> myfirstvue@0.1.0 serve
> vue-cli-service serve

 INFO  Starting development server...

 DONE  Compiled successfully in 1936ms                                                                          

  App running at:
  - Local:   http://localhost:8080/ 
  - Network: http://192.168.31.208:8080/

  Note that the development build is not optimized.
  To create a production build, run npm run build.


● 方式二: pycharm里还可以配置此命令,点击个按钮,快速启动. 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 绿箭头

方式二: 进行如下配置. 在webstorm中点击绿箭头就能快速上运行项目!!

image-20231008164057663

注意, 图中有npm和node的路径, 应确保正确的.


# Vue项目目录

以后写代码,都在src文件夹下写,其它地方一般不动.

具体文件中每一行代码什么意思, 参考文档: https://www.jianshu.com/p/19a7774248c3

myfirstvue                         # -- 项目名
├── node_modules                   # -- 当前vue项目的所有的依赖,小文件很多,可以删掉! -- 类似于py的虚拟环境.
                                   #    它人拿到删除了该文件夹的项目,它人只需要执行 npm install 命令即可再次拥有该文件夹.
                                   #    会将 package.json 文件里的所有依赖都给安装上.
├── public                         # -- 共用资源
│   ├── favicon.ico                #    网址小图标
│   └── index.html                 #    项目入口页面/vue项目默认首页.
                                   #    单页面开发(整个网站就这一个index,页面的变化都是组件的替换 英文简称spa)
├── src                            # -- ★ 书写代码的地方
│   ├── assets                     # -- 网站的静态文件和资源
│       └── logo.png 
│   ├── components                 # -- 一堆小组件(给组件用的组件 非页面组件)
│       └── HelloWorld.vue         #    自定义的组件
│   ├── router                     # -- vue-router相关,安装了该功能自动生成此文件夹
│       └── index.js 
│   ├── store                      # -- vuex相关,安装了该功能自动生成此文件夹
│       └── index.js
│   ├── views                      # -- 一堆大组件(是页面组件)
│       └── AboutView.vue
│       └── HomeView.vue
│   ├── App.vue                    # -- !!! 根组件  
│   └── main.js                    # -- ★ 非常重要,是整个项目的入口. 等同于Django的manage.py
├── .gitignore                     # -- git忽略文件
├── babel.config.js                # -- 语法检查. 咋们不用管它.
├── jsconfig.json                  # -- 无需关注
├── package.json                   # -- ★ 超级重要,项目配置依赖.不能删!! 等同于Django项目中的reqirement.txt
                                   #    后期node_modules文件夹删除后,该json文件中的依赖可使用npm install重新安装
├── package-lock.json              # -- 锁定依赖包.不能删. 意味某个模块会依赖其他模块,它们的版本需要对应.
                                   #    若删了,重新安装该模块时,它依赖的模块会安装最新的.可能会出现问题.
├── README.md                      # -- 项目介绍
└── vue.config.js                  # -- vue项目的配置文件,等同于Django项目的settings.py
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
27
28
29
30
31

若打开的项目在编译器里只读, 为该vue项目添加权限即可!!

dengchuan@MacBook-Air Desktop % sudo chmod -R 777 myfirstvue 
1

一些补充

简单来说,vue项目创建好后,运行项目,根据vue-cli脚手架自动生成的代码,大抵可知:
App.vue根组件会关联到index.html ; 
App.vue根组件通过路由关联AboutView.vue和HomeView.vue这两个页面组件 ;
在HomeView.vue这个页面组件中导入了HelloWorld.vue这个小组件!!


在index.html中有这么两行代码,它的意思是,若浏览器禁用网站的js功能,那么就会显示这段文字.
意味着,vue项目的正常运行的前提是浏览器必须得允许js功能的执行!
<noscript>
  <strong>
    We're sorry but <%= htmlWebpackPlugin.options.title %> 
    doesn't work properly without JavaScript enabled. Please enable it to continue.
  </strong>
</noscript>
  
我们说index.html单页面开发,组件的替换其实替换的是这个位置
<div id="app"></div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 如何运作的?

项目是如何运行起来的 / 各个文件是如何协同工作的,逻辑是什么?

# main.js与index.html

尽管对里面的代码不清不楚, 但也无伤大雅.. main.js文件一般不会动它!! 我们也不用深究里面的代码!!

main.js是项目入口文件, 经实验,创建的vue实例挂载的是index.html里id为app的div. 是不是感觉很amazing?
当初我看到时也百思不得其解, 查阅资料, 发现跟webpack有关..
参考的文档: https://blog.csdn.net/qq_36145914/article/details/86497123 (了解即可)

另外, render: h => h(App) 又是什么? 箭头函数, 此处的h指代的是createElement函数, 跟啥虚拟dom有关..
另外, .$mount('#app') 相当于 el: '#app',

image-20231009160804522

// 分别导入: Vue库、App组件、路由配置、状态管理器
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

// 关闭生产模式下的错误提示信息
Vue.config.productionTip = false

/*
   new Vue({...})创建一个vue实例
   将路由配置、状态管理器以及App组件注入/渲染到vue实例中.
   .$mount('#app') 将Vue实例挂载到id为"app"的元素上.
*/
new Vue({
    router,
    store,
    render: h => h(App)
}).$mount('#app')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 组件的三部分

我们重新写App.vue和HelloWorld.vue文件,便于我们理解执行逻辑!!
(因为默认里面写了路由这些相关的代码.我们暂且不需要掌握)

1> <template> 标签里是以前我们在反引号里写的html代码,同样的,特别强调,组件必须在一个标签里.eg:div标签.
2> <script> 标签里写js、导入以及export default
      export default {} 该对象里写之前学的data、methods、watch、computed、生命周期函数等!
3> <style> 标签里写样式.

注意: <style scoped> 表明, 写的样式只在当前组件有效!!
也就是说, 这样写, 父组件里用了子组件, 子组件是不会应用父组件里写的样式的!!

另外,注意: 父组件中导入子组件export default的对象接着对子组件进行注册
只不过, 该对象里不用写template:反引号 ,会自动关联子组件<template> 标签里的东西.

image-20231009180148504

特别注意!! 示例代码截图中,helloWorld_obj是一个对象; export default导出的也是一个对象!!

image-20231009181321404

Ps: test.html单独运行,或者 运行 当前的vue项目!! 运行结果都如上图截图所示!!
why? 你可以这样对比理解..

main.js里有vue实例,main.js与index.html相关联.  --  相当于test.html里写了个vue实例 (test.html对标index.html)
main.js里的vue实例挂载id为app的div             --  相当于test.html中的vue实例挂载index.html中挂载id为app的div
main.js里的vue实例中加载了根组件App.vue         --  相当于test.html中的vue实例里面写了一个名为App的局部组件
项目运行后,根组件App.vue会自动渲染到挂载点        --  相当于test.html中在挂载点写子组件标签

根组件App.vue里导入子组件HelloWorld.vue        -- 相当于名为App的局部组件里编写了一个名为HelloWorld的子组件
1
2
3
4
5
6

# vue项目中组件通信

自定义属性实现父传子 ; 自定义事件实现子传父.

# 示例代码

APP.vue

<template>
  <div id="father">
    {{ fullname }}
    <button @click="handleClick">点我名字变化!</button>
    <br>
    子传父: x: {{ x }}
    <hr>
    <HelloWorld :fullname="fullname" @myevent="handleReceive"></HelloWorld>
  </div>
</template>

<style>
#father {
  width: 300px;
  margin: auto;
  padding: 10px;
  border: 1px solid bisque;
}
</style>

<script>
import HelloWorld from "@/components/HelloWorld"
  
export default {
  name: 'App',
  data() {
    return {
      isActive: true,
      fullname: "lqz",
      x: "",
    }
  },
  methods: {
    handleClick() {
      this.isActive = !this.isActive
      this.fullname = this.isActive ? 'lqz' : '彭于晏'
    },
    handleReceive(x) {
      this.x = x
    }
  },
  components: {  // 注册组件,即在父组件中使用子组件!
    // 'HelloWorld': HelloWorld  // ★ 简写-可以简单的只写import导入时给小组件起的名字 HelloWorld
    HelloWorld
  }
}
</script>
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

HelloWorld.vue

<template>
  <div>
    父传子: {{ fullname }} <br>
    <input type="text" v-model="x">
    x: {{ x }} ; y: {{ y }}
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: ["fullname"],  // 父传子的变量fullname无需在data里申明,写在props中后直接用就行
  data() {
    return {x: 10, y: 20,}
  },
  methods: {
    handleSend() {
      this.$emit('myevent', this.x)
    }
  },
  watch: {
    x(val) {
      this.handleSend()
    }
  },
  created() {
    this.handleSend()
  }
}
</script>
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
27
28
29
30

# 代码逻辑

image-20231009205056948

# 执行结果

组件

有两个组件,APP.Vue和HelloWorld.vue 并且根组件APP里注册了HelloWorld组件
1> 父传子, 点击按钮, 显示的名字同步改变!!
2> 子传父, 先是在生命周期的created函数中就传了一次;
          后因为双向绑定+监听,当数据改变时,会重新传递!!
1
2
3
4

有个小细节: 根组件的 <template> 里的代码覆盖了index.html中 <div id="app"></div> 这里的代码!!

image-20231010132340518

# props配置项

三种使用方式

特别注意!! 父传子,经过实验. (示例代码中只是props的基本使用!!) <helloWorld fullname="true"></helloWorld> 传过去的fullname的值是true, 该true是String类型的数据!! <helloWorld :fullname="true"></helloWorld> 传过去的fullname的值是true, 该true是Boolean类型的数据!!

★★★ props的三种使用方式,任选其一即可! 注意哈,String,S是大写的!!
1- 基本使用
  props: ["fullname"]
2- 进行属性认证
  props: {
    fullname: String, // 意味着接受父组件传过来的fullname,必须是string类型的数据!!
  }
3- 限定类型、限定必传、限定默认值
  props: {
    fullname: {
      type: String,
      // false表明没有限定必传(即子组件标签上没有绑定名为fullname的属性)
      required: false,
      // 若没有传的话,其默认值为‘啦啦啦’
      default: "啦啦啦",
    }
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# es6导入导出

注意: 在vue项目中, 导入时, @符号表示src的路径! 导入时,文件的.vue后缀、.js后缀都可以省略!

下方的示例中使用的是默认导出, 还有命名导出等方式.. 具体的参考文档: https://segmentfault.com/a/1190000039957496
暂且记住一点, 命名导出的话, 导入时 import {导出时的命名,导出时的命名,..} from 路径 需要加大括号!!

示例的目录结构如下:

my
├── other
│   └── index.js
├── one.js
├── two.js
└── test.html
1
2
3
4
5
6

代码逻辑
注意代码截图中用 ★ 标注的注释!!

image-20231009224132526

运行结果

image-20231009224655471


# mixin混入

需求: 父组件App.vue里使用子组件HelloWorld.vue, 这两个组件里都有同一个点击事件, 点击事件关联的函数体代码都是一样的!!
点击弹出一个框, 框中显示的内容是各自组件里的数据..

mixin混入: 可以把多个组件共用的配置提取成一个混入对象!!

minx

# 最初的代码

浅红色标柱的代码是公共的/一样的, 可以提取出来!!

image-20231010214121449

# 使用混入

第一步: 提取公共的代码, 定义混入.. 此处, 我们在src目录下新建mixin文件夹, 在mixin文件夹下创建index.js文件.
第二步: 注册混入, 有两种方式, 选择其中一种方式即可.
1> 全局注册 - 在main.js文件中注册, 注册后所有组件都可以使用混入的内容.
2> 局部注册 - 在组件中注册后,该组件才可以使用混入的内容.

# 全局注册

下方截图主要观察 index.js 以及 main.js中 框起来的代码.

image-20231010212852736

PS: 若混入的index.js中有多个命名导出.. 那么全局注册这样处理. 举个例子:

import {hunhe,hunhe2} from '@/mixin'

Vue.mixin(hunhe)
Vue.mixin(hunhe2)
1
2
3
4
# 局部注册

以子组件HelloWorld.vue为例

关键代码就两行: import {myMixin} from "@/mixin"; mixins: [myMixin]

<template>
  <div>
    <button @click="handleShowName">点击弹窗</button>
  </div>
</template>

<script>
import {myMixin} from "@/mixin";

export default {
  name: 'HelloWorld',

  data() {
    return {
      name: "child_路飞"
    }
  },
  methods: {},
  mixins: [myMixin]
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 插槽的使用

默认插槽、具名插槽 (其实在前面已经讲解过了)

<template v-slot:插槽名字> 还可以简写 <template #插槽名字>

image-20231011164056918

页面展示效果如下:

image-20231011164129321


# 存储数据

sessionStorage - 临时存储, 浏览器关闭或关闭标签页 就没啦!
localStorage - 永久存储, 除非手动清理/浏览器存储空间满了!
cookie - 有个过期时间, 过期时间一到就没啦! + 发送请求时会自动携带它.

前端存数据的三个地方 - cookie、sessionStorage、localStorage.
在cookie中存储需要借助第三方插件vue-cookies 暂且略过.
★ 借助这三个东西, 也可以实现组件间的通信!!

sessionStorage.setItem('name', 'lqz')  // 设置值
sessionStorage.getItem('name')         // 取值
sessionStorage.removeItem('name')      // 删除值
sessionStorage.clear()                 // 清空sessionStorage中所有数据

localStorage.setItem('name', 'lqz')
localStorage.getItem('name')
localStorage.removeItem('name')
localStorage.clear('name')             // 清空localStorage中所有数据    
1
2
3
4
5
6
7
8
9

应用场景:
无需登陆就可以将商品加入购物车,关闭浏览器后,重新打开浏览器,发现刚加入购物车里的商品还在!
实现原理 - 前端将商品信息加到了localStorage中!!

222

App.vue

<template>
  <div id="father">
    <p>
      用户名: {{ username ? username : "还未获取" }}
    </p>
    <button @click="handleSave">点击</button>
    <p style="color: rgb(128,128,128)">
      1> 起初 - 用户名处显示 "还未获取" <br>
      2> 点击按钮 向sessionStorage中放数据 - 用户名处显示存入的数据 "lqz" <br>
      3> 5s后 缓存的数据消失 - 用户名处显示 "缓存数据消失" <br>
    </p>
  </div>
</template>

<style scoped>
#father {
  width: 550px;
  margin: auto;
  padding: 10px;
  border: 1px solid bisque;
}

h3 {
  background-color: bisque;
}
</style>

<script>
export default {
  name: 'App',
  data() {
    return {
      username: ''
    }
  },
  methods: {
    handleSave() {
      sessionStorage.setItem('name', 'lqz')
      this.username = sessionStorage.getItem('name')
      /* 注意点:
         setTimeout是异步的,它不会阻塞在这,时间到了会执行里面的回调函数
         这里用了箭头函数,确保该处的this指向是vue实例,而不是window对象.
      */
      setTimeout(() => {
        sessionStorage.removeItem('name')
        this.username = "缓存数据丢失."
      }, 5000)
    }
  },
}
</script>
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

# vue3的变化

前面的讲解都是基于vue2实现的, 我们后续开发项目用vue3, vue3是兼容vue2的!!

vue3变化参考文档: https://www.cnblogs.com/liuqingzheng/articles/16840372.html
★ 学的vue2的所有东西都可以直接写在vue3上, 完全支持!!

# 创建vue3的项目

# webstorm里

它会自动选择vue3创建!! 创建时是默认的配置, 是没有 Router和 Vuex的.. 不碍事,后面可以手动加入.

另外, 通过这种方式创建的项目, 快速启动的绿色按钮也不需要自己配置啦!!
但在我的mac上实践了下,会报错, 在项目根目录下运行这两行命令完美解决 rm -rf node_modules ; npm install

image-20231013194534515

# 使用vite
创建vue3的项目:
  - 使用vue-cli创建,跟vue-cli创建vue2项目基本一致
  - 使用vite创建
    step1: 创建工程 “利用vite新创建的工程是没有node_modules文件夹的”
           npm init vite-app vue3_1
    step2: 进入项目工程 cd vue3_1
    step3: 安装依赖 npm install “项目根目录下就会多出node_modules文件夹”
    step4: 运行,注意命令 ★ npm run dev  “会发现,运行的特别快!!之前用vue-cli创建的运行起来还需编译,现在编译都不需要”
1
2
3
4
5
6
7
8

image-20231013211237820

可以浅看下代码, 利用vite创建好项目后, 最开始就默认有的代码是如何实现这个页面的..
可以发现里面使用的vue2的语法, 都是学过的, so easy. 有效的证明了“vue3兼容vue2嘛!!”

image-20231013212219257

细心点, 可以发现, <template> 标签里的html代码无需特地放在 一个div标签里啦!!

# 组合式API

vue2使用的是配置项API , vue3中推荐使用组合式API!!

以后vue3不建议组件中使用data、methods.. 这种配置项API; 建议使用setup这种组合式API!!

111

<template>
  {{ name }}:{{ age }}:{{ nums }} <br>
  <button @click="age++">点击年龄加一</button>
  <button @click="handlerNumAdd">点击数字加一</button>
  <br>
  身高:{{ person.height }} 体重:{{ person.weight }}
  <button @click="handlerHeightAdd">点击身高加1cm</button>
  <br>
  出生地:{{ BirthPlace }}
  <button @click="handlerChangeCity">点击修改城市</button>
  <br>
  监听它:{{ temp }}
  <button @click="temp++">点击监听的变量加一</button>
</template>

<script>
import {ref, reactive, computed, watch} from 'vue'

export default {
  name: 'App',
  setup() {
    /* 定义变量
     * 相当于在vue2的配置项API data(){return {name:'lqz',age:18}}
     * */
    // 若不加ref,那么点击按钮,age变量的值会加1,但是页面上{{age}}不会变/不会响应式的改变.
    // 若不加reactive,那么点击按钮,person对象的height的值是会改变的,会加1,但是页面上{{person.height}}不会响应式的改变.
    const name = ref('lqz')
    const age = ref(18)
    const nums = ref(0)
    const person = reactive({
      height: 172,
      weight: 110,
    })

    /* 定义函数方法
     * 相当于在vue2的配置项API  methods:{handlerNumAdd() {}},
     * */
    function handlerNumAdd() {
      // 因为使用了ref,所以nums变量变成了ref对象!
      // 注意,若未使用ref const name = 'lqz' , name变量是常量是不能改变的!
      //     (内存地址不能变,若是复杂数据类型,比如对象,对象内存地址不变,但里面的属性是可以变的)
      // ★★★《基本数据类型》用ref包裹一下,使之变成响应式. 在模版中直接使用;在setup(){}中需要nums.value获取真正的值.
      // ★★★《数组、对象类型》用reactive包裹一下,使之变成响应式. 在模版中和setup(){}中都直接使用;
      console.log(nums, typeof nums)
      nums.value += 1
    }

    function handlerHeightAdd() {
      person.height += 1
    }

    // ★★★ 可以写多个计算,也可以写多个监听
    
    /* 定义计算属性
     * 相当于在vue2的配置项API  computed: {}
     * */
    const student = reactive({
      nation: "中国",
      city: "成都"
    })
    let BirthPlace = computed(() => {
      return student.nation + student.city
    })
    // function handlerChangeCity(){}
    let handlerChangeCity = () => {
      student.city = "北京"
    }

    /* 定义监听属性
     * 相当于在vue2的配置项API  watch: {}
     * */
    const temp = ref(1)
    watch(temp, (newValue, oldValue) => {
      console.log(newValue, oldValue)
    })

    // ★★★ setup中可以写变量,写函数等, 但只有return了,在模版中才可以使用!
    //     这使得不会像vue2里面一样全部动态渲染,vue3需要啥渲染啥.
    return {
      name,
      age,
      nums,
      handlerNumAdd,
      person,
      handlerHeightAdd,
      BirthPlace,
      handlerChangeCity,
      temp,
    }
  }
}
</script>
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

# 生命周期

"[生命周期]"
- 在vue3里,若用vue2的配置项写法,生命周期的8个函数,有两个需要改一下名字
  beforeDestroy 改名为 beforeUnmount
  destroyed     改名为 unmounted
- 在vue3里,若使用vue3的组合式API写法 对应关系如下
  “但要注意,setup()一执行,就认为beforeCreate和created就执行完了.”
  “比如,在setup中写 import {onMounted} from 'vue';   onMounted(() => {})”
  beforeCreate  ===>     setup()
  created       ===>     setup()
  beforeMount   ===>     onBeforeMount
  mounted       ===>     onMounted
  beforeUpdate  ===>     onBeforeUpdate
  updated       ===>     onUpdated
  beforeUnmount ===>     onBeforeUnmount
  unmounted     ===>     onUnmounted 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# toRefs

对象解压, 就不必在模版中 对象.xx 取值啦!

image-20231013231513342

<template>
  身高:{{ person.height }} 体重:{{ person.weight }} <br>
  姓名:{{ name }} 年龄:{{ age }}
</template>

<script>
import {reactive, toRefs} from 'vue'

export default {
  name: 'App',
  setup() {
    const person = reactive({
      height: 172,
      weight: 110,
    })

    const fullName = reactive({
      name: "dc",
      age: 19,
    })


    // es6语法中的对象解压
    /* 下面的代码等同于
       return {
           person,
           name:fullName.name,
           age:fullName.age,
       }
    * */
    return {
      person,
      ...toRefs(fullName),
    }
  }
}
</script>
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
27
28
29
30
31
32
33
34
35
36
37

基础语法(3)
插件的使用(1)

← 基础语法(3) 插件的使用(1)→

最近更新
01
deepseek本地部署+知识库
02-17
02
实操-微信小程序
02-14
03
教学-cursor深度探讨
02-13
更多文章>
Theme by Vdoing | Copyright © 2023-2025 DC | One Piece
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式