一、环境:
1、安装vscode
2、需要安装一个叫node的东西,如果安装了下图就可以执行。
(Node.js 提供了一个 ++可以在非浏览器环境下 执行 JavaScript 代码的++ 环境)
(还包含,npm工具,就可以装东西了,所以需要装好node.js)
可以用来验证有没有node.js
配置npm
# 查看
npm config get prefix # 查看 全局安装目录 npm install xxx -g 时,会吧东西装进去
npm config get cache # 查看 全局缓存目录
# 设置重新修改(C盘不好)---先新建文件(就建在安装的nodejs里面吧一般)
npm config set prefix "D:\soft\nodejs\node_global"
npm config set cache "D:\soft\nodejs\node_cache"
配置环境变量
在安装目录中,cmd 里, 可以 npm config list ,
其他地方如果不行,要配置环境变量, 安装时好像自动配上了,就是在系统变量path中加一个 安装目录路径就行、和上面安装指导有出入。
设置镜像源为淘宝源
npm config set registry https://registry.npm.taobao.org # 过期
npm config set registry https://registry.npmmirror.com # 最新
npm config list # 查看验证
npm --version
npm安装
全局安装
尝试安装nprogress
其他局部不用安装直接使用?(gpt说不能用)
局部安装
直接如:npm install screenfull@5.2.0, 安装后有package.json文件,里面记录有哪些包, node_modules文件夹里放实际的包
生产依赖和开发依赖关系分享
局部安装分装到生产依赖,还是开发依赖
默认为生产依赖
加 参数 --save-dev 或 -d 就保存为开发依赖:
本地运行时,其实不管是哪种,但是上线后,通常选择 生产依赖,在开发过程中,就把一些辅助工具的依赖,装到开发依赖
总结: 初学时安装,就都不加 -d , 当你知道它是打包工具,测试工具,等辅助工具时,就最好加上-d。
二、快速使用vue包学习
本来需要使用npm xxx 创建的vue项目+ 初始化调试,我们先不管了,直接解压里面的压缩包来用
解压后,目录中package.json 中,name 就是项目名,可以改成自己喜欢的,然后把外层的文件名换一样的, 这样 就和 npm安装 是一样的效果了。
然后终端执行:npm install (要把packagejson中需要的插件,源码给下载好,生成node_modules文件)
仍然需要做一些准备工作:
1. 装插件 vetur (.vue文件高亮, 以及保存时代码风格化代码)
右键插件的【扩展配置】, 点stting.json。进行配置
javascript
{
"vetur.completion.scaffoldSnippetSources": {
"workspace": "💼",
"user": "🗒️",
"vetur": "✌"
},
"[vue]":{
"editor.defaultFormatter": "octref.vetur",
"editor.detectIndentation": false,//缩进
"editor.tabSize": 4,//缩进大小
"editor.formatOnSave": true //保存自动格式化
},
"[python]": {
"editor.formatOnType": true
},
"python.autoComplete.extraPaths": [],
"python.analysis.extraPaths": []
}
2. 其他插件-下面有代码补全的功效
vue 3 snippets
vue vscode snippets
其他(如果不懂的话可以装一下这些,具体啥用我也不知道):
eslint先别装,它好像是限制代码格式的,不装为好
(ESLint 插件 的主要功能是帮助你实时检查代码中的错误和规范问题,它会根据配置的规则自动检测并标记出代码中的潜在问题。)
如果已经装了 eslint , 那么项目下的.eslintrc.js, 可以下面这样设置
javascript
module.exports = {
root: true,
env: {
node: true
},
extends: [
'plugin:vue/vue3-essential',
'@vue/standard'
],
parserOptions: {
parser: '@babel/eslint-parser',
requireConfigFile: false
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'space-before-function-paren': 0, // 关闭在函数定义的左括号前强制使用一致的间距
'eol-last': 0, // 关闭在文件末尾至少强制执行一个换行符
'prefer-const': 0, // 关闭对声明后从未重新赋值的变量,要常量声明
'spaced-comment': 0, // 关闭在注释中的//或/*后面强制使用一致的间距
'no-multi-spaces': 0, // 关闭不允许多个空格的检查
'import/no-duplicates': 0, // 解决vue组件重复导入问题
indent: 0, // 解决js缩进问题
'vue/multi-word-component-names': 0, // 解决组件名称单单词的问题
'vue/no-unused-components': 0 //组件导入未使用问题
}
}
运行启动
终端执行: npm run dev (其实就是使用vite 来启动,再package.json中还可以把dev 改成其他值,比如改成serve) ,那就还是npm run serve
然后就能浏览器访问页面了、
看src中的main.js文件, 引入的主文件, http://localhost:5173/ 访问的就是主文件。
接下来就是修改红框里的代码。来进行巩固学习。
1、入门知识
1. 这个看js的一些用法
http://localhost:5173/ 访问后,打开F12观察控制台
知识点都写在了 Study1.vue里面,就不介绍了
javascript
// import App from './App.vue'
import App from './components/study/Study1.vue'
2. 这个是vue中的插值表达式{{}}
因为已经装了一些插件,如果是重新开始写代码,直接vbase, 选中其中一个模板,就可以快速生成代码,笔记已经写好了,直接用,知道就行。
不同变量的一些取值简单使用
javascript
// import App from './App.vue'
import App from './components/study/Study2.vue'
3. v-text 和 v-html
效果和插值表达式差不多, v-text="" 中间可以放一些js语句,如 num +100
javascript
import App from './components/study/Study3.vue'
4.v-bind, 简写 :
javascript
import App from './components/study/Study4.vue'
属性前写了 v-bind: 或 : 后面就接变量
:class属性,后面的变量可以是字符串,可以是数组(推荐),也可以是对象
:style属性,后面可以字符串,数组, 字典对象(推荐)
a标签的,href属性能用, button标签的 disabled属性都可以使用
除此之外,引号中,是可以写js语句的,比如
javascript
<div :style="{ color: 颜色变量名, 'font-size': 数值变量 + 'px' }">
5.v-if 和 v-show
注:v-if 和 v-else-if 和 v-else 是一组
javascript
import App from './components/study/Study5.vue'
6.v-for 可以变出多个标签
javascript
import App from './components/study/Study6a.vue'
v-for = "" 引号中的写法 是 (item, index) in list, 当前标签就可以变成多个
- 可以遍历数组(item,index) in list
- 可以变量对象 (value, key, index) in person , 代码没举例
注:对于li标签,需要 :key="index" (是为了帮助 Vue 识别每个循环的元素,以便在数据更新时进行高效的重新渲染)
Study6a 和 Study6b的区别:
6a是 :key="index" , 6b是:key="item.id", 62更优秀,因为加值后,id 也不会变来变去
7. 操作动作属性 v-on 简写 @
javascript
import App from './components/study/Study7.vue'
v-on 写在有动作的标签里面,如<button></button>中
- 可以放js代码,比如点了按钮就会执行
- 可以触发函数,<button @click="addnum()">按钮</button>
- 动作属性后面加.once, 如 <button v-on:click.once="count += 1">按钮</button> ,表示只会生效一次
接受参数 (能接受 事件对象)
1.定义事件与函数<input type="text" @input="input($event)" /> 也可以不打括号,函数就能默认接收到 事件对象
2.定义函数 const input = (e) => {console.log(e.target.value)} # e.target.value 表示该事件的对象的值 a.如是点击一个按钮, e.target 表示 该按钮标签 。
8. v-on 补充
- @动作.once 一次
- @动作.prevent
- @click.prevent -----比如a标签的点击,会调整,可以prevent然后就不跳转,(也可以不加.prevent , 后面自定义函数,函数中要有,event.preventDefault()------Study8.vue
- @submit.prevent 表单标签中加了这个,就不会刷新了
- 我们使用 @submit.prevent 来监听表单的提交事件,并且使用 prevent 修饰符来阻止表单的默认提交行为。这样,当用户点击提交按钮时,不会触发表单的默认提交行为(即刷新),而是会执行我们自定义的 submitForm 方法。
- 其实是 事件 event调用了e.preventDefault()
- @动作.stop ,应该可以连起来用,没试过 .once.stop.prevent
- 补充:input的键盘事件 - @keyup.enter=showMessge (键盘的回车事件)
9. v-on补充2.stop用在动作传递中起阻止传作用
- @click.stop 停止(传递) (默认情况:如有多层,我点击内圈,相当于大的外圈也被点击了)
- 其实是 事件 event调用了e.stopPropagation() 例子--Study9.vue----,如果在方法里使用了stopPropagation(),那么每层都会阻止了,可以注释,打开查
10. v-model双向绑定
---Study10.vue-
方式1:
假如不知道这个知识,可以用 @ v-on 和 : v-bind 结合,有双向绑定的效果,如下
: value,表示value取下面, @input 后面的js 意思又是把下面 改成 标签的value
<input type="text" :value="address" @input="address = $event.target.value" />
{{ address }}
方式2
使用 v-model="xxxx" ,便可以直接双向绑定, 直接绑定就是input输入框的value值
v-model:value="name" 可以省略简写 v-model="name"
11. v-model 的修饰符
---Study11vue---
- v-model.lazy 标移才把输入值,传到变量
- v-model.number 只会把数字传到变量
- v-model.trim 去两侧的空格
12. v-model用在单选框、各input项的value值要先定义
---Study12.vue---
单选type="radio" 和普通 input文本框不同的是, input的值是输入的,而单选框:
- 每个value值,要先自己定义好(就像下来选项先有值)。 (再用 v-model = "变量")
- 一组内每个input要同样的 v-model="变量"
13. v-model用在多选框、各input项的value值要先定义
---Study13.vue---
与单选框不同的是, v-model="xxx" , xxx需要是一个数组
14.v-model用在select下拉选框
---Study14.vue---
对于select标签。
- 1.先定义,select中的option的 value的 值, (如果不定义,绑的就是文本值)
-
- select 标签中 写 v-model="xxx"
选中一项后, 绑定的值就是所选option的value
对于单选下拉框, xxx定义成 字符串
对于复选下拉框,xxx定义成 列表(数组)
2、 入门知识2
1. 计算属性变量
vue3中完整写法 :---Study15vue---
computed中间时一个对象
去获取customValue 值时, 就是调用的 get,获取到了xxxx
当某个函数中给 customValue 设置值时, 会调用其中的set方法
javascript
const customValue = computed({
get() { return xxxx},
set:()=> {}, //可以这么写 set(){}
})
computed中间是一个函数时,那就默认为只读,及这个函数就是get的函数。---Study16.vue---
vue2中的写法,稍显复杂,但是也是要定义get 和set的方法。
vue2_计算属性.html , 直接右键open with live server 打开
如下的例子, 如果 全名:<input type="text" v-model="fullName">, 绑定fullName,
就可以实现写姓名和改全名, 写全名可以改姓名,
如果是绑定fullName2 , 那么只能实现get, 及只能写姓名和改全名
2. watch 侦听属性
---Study17.vue---
侦听对象,和处罚函数的位置。
最后一个对象,可以不写
- immediate: true,表示初始化会调用watch中的 那个函数
- deep: true, 暂未知效果
侦听对象可以是reactive对象,或者ref对象。 reactive里面的具体对象也可以侦听,但写发不同
---Study18.vue---
按钮都是改变值,然后他们会按箭头所示,来触发函数
其中: 侦听函数中的方法中,可以支持异步的东西。 如代码中,侦听到num变化,过了5秒后,又变成了900
对于侦听函数,可以有多个侦听对象。---Study19vue---
- 侦听一个变量写法(深度) : watch(num, (newValue, oldValue) => {},{immediate:true, deep:true})
- 侦听一组变量写法 : watch( [num1, num2] , (newValue, oldValue) => {}) 此时newValue 表示两个值
注:
-
对于监听对象是ref时,watch的第一个参数,监听对象写, 不要写num.value ,如笔记中,直接写 num就行
-
如果是监听reactive对象,监听对象不能写成 state.num , 可以试试写成 () => state.num (如代码中的监听state.hellonum时)
vue2的侦听属性写法 src\components\study\vue2_侦听属性.html
- 复杂写法 wath:{ 监控对象名 :{handler(){xxx}, immediate:ture, deep:true}}
- 简单写法 watch:{ 监控对象名(){ xxx } }
3. vue3新增的watchEffect函数
---Study20vue--- 由于写法简单,用法就简单了,大概不能获取到变化后的值和老值
4. 侦听和计算的区别:
见
计算: src\components\study\vue2_计算属性.html
侦听: src\components\study\vue_侦听与计算对比.html
侦听的对象,改变之后, 触发的函数里面可以加异步的东西。
如代码中: 修改了firstName, 2秒后才异步的设置了 全名
案例1:实现搜索框
- 通过watch来实现---Study21.vue--- 逻辑:输入文本框,一变化,就侦听到, 把新填的值,进行判断,去过滤,赋值到定义好的 临时空数组 页面展示(新的临时数组)
- 通过computed来实现---Study22.vue--- - 逻辑:输入文本框,一变化,就计算, 得到计算属性临时列表, 页面也展示这个临时列表。
案例2:实现搜索+升序降序
设置一个变量,不同的按钮,点击后来重设变量为不同的值,根据值来if判断, 实现升序,还是降序
- 需要使用到 数组.sort() ,--原理看代码 src\components\study\Study23.vue
- ------src\components\study\Study24.vue------- 代码里面用到了三目运算, 来实现是升序,还是降序
5. 生命周期函数
vue3的生命周期函数写法: src\components\study\Study25.vue
onUnmounted 的例子在后面看 ,搜索 路由导航 router-link 和 router.push()方式
注:代码里面的生命周期函数是 vue3里面的,写在setup里面的,如果要用vue2的写法,写在和setup同级。
补充:
onMounted 执行完,刷新一下,才会渲染出页面 , 看 src\components\study\Study26.vue
补充案例,它里面一直在执行 onMounted的回调函数, 看src\components\study\Study27.vue
3.入门知识3:父子组件
假如xxx2.vue里有xxx1.vue, 我们就说xxx2.vue为父组件。
1. 数据---父给子
-----src\components\study2\Father.vue----------注意main.js中注意路径对不对--------
效果如下:
父vue中
- 需要指定components, 表示可以用哪些 子vue, (即能用到哪些子vue标签)
- 子组件标签中,可自定义属性,把变量 传给子组件
- 如果不用 v-bind , 如下图 taoke="111" 就是传的字符串, 下图用了v-bind , :taoke="111" , 传过去的是number
- 、
子组件中:
用props来接收
方法1:
javascript
props: ['abc', 'age', 'hij'],
方式2-定义了数据格式:
javascript
props: { abc: String, age: Number, hij: Array },
方式3:放松2的基础上还可以这样写,就还能定义默认值
javascript
props: {
abc: String,
age: Number,
hij: Array,
taoke: {
type: String,
// required: true,
default: '如果父没有传,就用我'
}
}
注: 子组件中,父给子的 props的值,不能直接更改,,可以的做法就是, 先把 props的值,取到放到data中
2. 数据- 子给父
方式1 子组件中emit的方式
src\components\study2\Father2.vue 效果如下
父vue中
- 用 components ,包含哪些组件。
- 在子组件标签中,用v-on绑定一个自定义属性 = 函数 (可以接受子组件 emit传过来的参数)。
子vue中(Child2.vue)
- 使用emit('自定义属性', state) ,这样就能把state传给父中的函数,并能接收一个参数
方式2: 子组件中,定义props.onMounted中给props给值
子:
要定义props, onMounted中给props给值 (setup要写成 setup(props){} )
父中:
子组件标签中使用abc属性, 后面接函数 () (函数可以接受一个参数,该参数就是abc传来的值)
方式3(和1 差不多。还要多经过一层)
子中: 是一样的, 用emit 来发射
父中:子组件标签中, 写一个 ref= "child" , 然后用如图的写法
3. 父组件中,使用component标签来放子组件
src\components\study2\Father4.vue
4 . 插槽
插槽允许父组件在使用子组件时向子组件传递额外的内容,以便在子组件的特定位置插入这些内容。
根据现象可以观察,无名插槽会挤在一起, 展示顺序要看 子组件中 各个 slot的位置
无名插槽
src\components\study3\Father.vue
- 子组件中,使用 <slot> 标签来标记一个插槽位置:
- 父组件中,在子组件标签内插入内容来填充插槽。这些内容将会被传递到子组件中对应的 <slot>标签位置
有名插槽
src\components\study3\Father2.vue
使用具名插槽(有名插槽)来更灵活地在父组件中向子组件传递内容。
具名插槽允许你在子组件中定义多个插槽位置,并在父组件中选择要填充的插槽。这对于需要在不同位置插入不同内容的情况非常有用。
- 子中,slot 标签要指定一个 name
- 父中,使用template标签,并用v-slot指定 插槽名字, 或者用简写 #插槽名字
子组件里可以用在插槽位置 slot标签 把子组件的数据传给 父组件 。
src\components\study3\Father3.vue
那个tmplist命名是自己随便命的
4. 入门4、跨组件通信
实际业务情况常常为,一个公共组件,比 列表组件,它们里面多为inject, 当具体的一个业务列表时, 就会provide对应业务的数据
如下图分别是
src\components\study3\One1.vue 使用了公共组件作为子组件
src\components\study3\One.vue 使用了公共组件作为子组件
补充:
可以provide reactive的一项(上面的例子)
可以provide 整个reactive对象
也可以provide 一个 ref 对象
三、vue框架
1. 路由配置基础
原本:一个路由关联一个vue组件, 当访问的路由时,组件内容会去替换<router-view> 或者另写法 <RouterView />
以上知识点:
路由模式 即history属性有两种
- createWebHashHistory, 项目路径要加 路由前面要加 /#
- createWebHistory
两种方式:
// which is lazy-loaded when the route is visited.(访问路由,才加载这个组件 ,懒加载)
特点: 项目打包时,一个组件打包成一个js文件
component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
npm i vue-router, 可以看下packagege.json中有没有安装 npm i vue-router@next --save
- 总组件中(要改main.js中的那个组件) 改成 import App from './App2.vue', 简介一点
- 配置新的url, 路由---组件 (router文件 中 index.js), /test路由中选一个 vue文件
路由配置是如何生效的, 是由于有main.js文件,里面使用到了配置。
总组件中(路由为/ 的),可以写访问 子路由的东西, 访问子路由后,对应的组件展示在位置。
2.路由重定向配置
3. 路由导航 router-link 和 router.push()方式
准备工作:
main.js中,import App from './components/luyou/test1.vue'
然后点击他们都可以实现路由的跳转
方式1:使用 router-link ,跳转 (申明式) 方式2:是方法中使用router.push('/about1')
- to表示路由, to后面的值 和 router index.js中的 path 一样, 如下有两种方式
javascript
// 写法1
<router-link to="/about1" active-class="active">about</router-link>
// 写法2 (这样写,就可以用path 或者用name了)
<router-link :to="{ path: '/home1' }" active-class="active">首页ya</router-link>
- active-class 表示 选中后的样式,如下active,就写到style里面, 比如代码里是写的红色
补充:不展示的路由的组件,它就失效了
时效了,就会触发生命周期函数的
setup中的onBeforeUnmount 和onUnmounted 方法 (vue3)
或者和setup同级的 unmounted 方法 (vue2)
让不展示的路由组件保持挂载在页面,不被摧毁 (拥有缓存)
作用:防止重复渲染DOM,减少加载时间及性能消耗,提高用户体验性。
做法:在饮用子组件的的外层添加了 标签
src\components\luyou\test1.vue 中 没有生效,不知道为什么,如果成功,
参数:
- include ="子组件的名称" 子组件的名称定义写在,和setup同级,写name="xxx",如下图,就可以针对性,对某个组件进行缓存
- 如果需要限制缓存的组件数量,你可以使用 max 属性进行设置,如 <keep-alive max="3">
4. 路由的前进后退
vue3
javascript
script中
import { useRouter } from 'vue-router'
或者 import router from '@/router' // 项目文件中自己定义的(不要中括号) ,下面就不用const router了
---------------setup中
const router = useRouter()
router.forward() # 前进
router.back() # 后退
router.go() # 传-1,就是后退一下,-2是两下, 1是前进, 不传没效果
vue2
javascript
不是setup的
this.$router.forward()
this.$router.back()
this.$router.go(1)
5.嵌套路由(二级路由)
访问/kengcheng路由时, 访问kecheng.vue时,的css样式,需要装一个插件 npm install -D less
这里我们看出,那个Back.vue的内容,后端内容列表就放出来。过程是下图这个样子
6. router-link 标签的传参 (3的补充)
main.js中,还是用import App from './components/luyou/test1.vue' 作为主组件,
点击传参到kekeng1,路由,对应组件是 src\components\luyou\Kecheng2.vue
使用this.$route.query 获取时,及格式为 路由?name=xxx&age=yyy的格式
传参方式1:
点击前端,进行查看
/about1/front?text2=小滴课堂yaya
多参数/about1/front?text2=小滴课堂yaya & address=xxxx
传参方式2-实现效果和上面一样也是url传参:
点击后端,进行查看
router-link 里面的to参数 里面放一个字典, 里面有个query, 再放参数对象
使用this.$route.params获取时,效果是把参数直接拼到路由
方式1: 点击params传参, 进行查看
三个地方:
- 路由配置,把参数配置成路由中。
2 router-link处
- 获取要这样写
方式2,
和方式1,不同的是 to后面接对象,且带一个params对象
router-link的replace的意思
- 看 这, 有了他效果就是,点击其他也没,再到这里, 后退就后退不过去了, 点击后退,或者点击浏览的返回都退不去了
7.编程式导航
看src\components\luyou\test1.vue
this.$router.push('/home1')
javascript
//vue3
import { useRouter } from 'vue-router'
const router = useRouter() // 这个也写在setup里面
或者 import router from '@/router' // 项目文件中自己定义的(不要中括号)
方法中写这个:router.push('/about1')
//vue2的写法
this.$router.push('/home1')
传参:
路由配置一下, 也可以像6中 的prarams传参一样
javascript
//多参数的传递
this.$router.push('/home1/taoke/18') // 需要配置好路由为 path:/home1/:name/:age
// 也可以用对象的形式 (和下方的 params传参的对象,一样的传递方式)
this.$router.push( { name: 'ceshi', params: { text: name } })
// 待跳转的组件获取值,也和下面的 parms传参一样
mounted() {
console.log(this.$route.params) // {myName: "直接拼在后面"}
}
this.$router.replace('/home1')
如果是这种,相比方式2, 它会跳转,并且会替换上一个路由记录,返回就不会一层一层返回
8.路由守卫
- 组件的路由进行配置
- 看下面这部分代码,是要放到路由的index.js中的,
如果加上这部分代码后, 每个页面都不能访问,要自己回到 / login
javascript
router.beforeEach((to, from, next) => {
const userId = localStorage.getItem('userId')
// eslint-disable-next-line no-cond-assign
if (to.path === '/login') {
next()
} else if (userId) {
next()
} else {
next('/login')
}
}
)
- 换个判断逻辑,路由配置里的额外信息判断,某些也没再校验是否登录
javascript
router.beforeEach((to, from, next) => {
const userId = localStorage.getItem('userId')
// eslint-disable-next-line no-cond-assign
if (to.meta.needAuth ) {
if (userId) {
next()
} else {
next('/login')
alert('请登录')
}
}
else {
next()
}
}
)
模拟登录