npm
npm软件
①前端框架的下载工具
②前端框架的管理工具
补充:
框架:针对特定的问题的一套固定的解决方案 软件的半成品 在此之上极大提高开发效率
后端框架:表现形式 一大堆jar 例如:Jackson针对JSON格式转换的一套固定解决方案
前端框架:表现形式 一大堆 css js … …文件
Node.js
什么是Nodejs
> Node.js可以使 JavaScript 运行在服务器端。Node.js 具有以下特点:
- 单线程,但是采用了事件驱动、异步 I/O 模型,可以处理高并发请求。
- 轻量级,使用 C++ 编写的 V8 引擎让 Node.js 的运行速度很快。
- 模块化,Node.js 内置了大量模块,同时也可以通过第三方模块扩展功能。
- 跨平台,可以在 Windows、Linux、Mac 等多种平台下运行。
npm常见命令
1.项目初始化
+ npm init
+ npm init -y
+ 执行,-y yes的意思,所有信息使用当前文件夹的默认值!不用挨个填写!
2.安装依赖
仅供当前项目使用
+ npm install 包名 或者 npm install 包名@版本号
+ 安装包或者指定版本的依赖包(安装到当前项目中)---------------一定要在当前项目下执行该命令
供所有npm管理的项目使用
+ npm install -g 包名
+ 安装全局依赖包(安装到d:/Glo balNodeModules)则可以在任何项目中使用它,而无需在每个项目中独立安装该包。
+ npm install
+ 安装package.json中的所有记录的依赖
3.升级依赖
+ npm update 包名
+ 将依赖升级到最新版本
4.卸载依赖
+ npm uninstall 包名
5.查看依赖
+ npm ls
+ 查看项目依赖
+ npm list -g
+ 查看全局依赖
> 6.运行命令
+ npm run 命令是在执行 npm 脚本时使用的命令。npm 脚本是一组在 package.json 文件中定义的可执行命令。npm 脚本可用于启动应用程序,运行测试,生成文档等,还可以自定义命令以及配置需要运行的脚本。
vue简介
Vue的两个核心功能:
- 声明式渲染:Vue 基于标准 HTML 拓展了一套模板语法,使得我们可以声明式地描述最终输出的 HTML 和 JavaScript 状态之间的关系。
- 响应性:Vue 会自动跟踪 JavaScript 状态并在其发生变化时响应式地更新 DOM
使用vue思路:数据发生改变时,数据所绑定的位置的dom树会自动跟着变化
VUE_Vite构建工程化前端项目
操作步骤:
1 使用命令行创建工程
①在vscode的控制台里输入:npm create vite
②然后输入项目名
③选择框架
2 安装项目所需依赖
⑤最后要下载依赖:首先要进入到当前项目,然后输入 npm install----------下载项目依赖
注意:
3 启动项目
此时运行项目不再使用vscode的go line;而是再控制台输入 npm run dev-----------------运行项目(前提是要进入到该项目)
退出项目:ctrl+c操作
单文件组件概念
----------------------------------一个文件就可以构成一个组件
> 什么是VUE的组件
+ 一个页面作为整体,是由多个部分组成的,每个部分在这里就可以理解为一个组件
+ 每个.vue文件就可以理解为一个组件,多个.vue文件可以构成一个整体页面
+ 组件化给我们带来的另一个好处就是组件的复用和维护非常的方便
> 什么是.vue文件
+ 传统的页面有.html文件.css文件和.js文件三个文件组成(多文件组件)
+ vue将这文件合并成一个.vue文件(Single-File Component,简称 SFC,单文件组件)
+ .vue文件对js/css/html统一封装,这是VUE中的概念 该文件由三个部分组成 `<script> <template> <style>`
+ template标签 代表组件的html部分代码 代替传统的.html文件
+ script标签 代表组件的js代码 代替传统的.js文件
+ style标签 代表组件的css样式代码 代替传统的.css文件
>Vue3_工程文件之间的关系
+ index.html是项目的入口,其中 `<div id ='app'></div>`是用于挂载所有组建的元素
+ index.html中的script标签引入了一个main.js文件,具体的挂载过程在main.js中执行
+ main.js是vue工程中非常重要的文件,他决定这项目使用哪些依赖,导入的第一个组件
+ App.vue是vue中的核心组件,所有的其他组件都要通过该组件进行导入,该组件通过路由可以控制页面的切换
响应式数据和setup语法糖
响应式数据:在数据变化时,vue框架会将变量最新得值更新到dom树中,页面数据就是实时最新的
非响应式数据:在数据变化时,vue框架不会将变量的值更新到dom树中,页面数据就不是实时最新的
vue2中,数据不做特殊处理,默认就是响应式的
vue3中,数据要经过ref/reactive函数的处理才是响应的
ref/reactive函数是vue框架中给我们提供的方法,导入进来即可使用
ref处理响应式数据,在操作时需要注意
在script标签中,操作ref的响应数据需要通过.value的形式操作
在template标签中,操作ref的响应式数据,无需通过.value
让一个普通数据转换为响应式数据 两种方式
1 ref函数 更适合单个变量
在script标签中操作ref响应式数据要通过.value
在template中操作ref响应式数据则无需.value
2 reactive函数 更适合对象
在script template 操作reactive响应式数据都直接使用 对象名.属性名
3 toRef函数 将reactive响应式数据中的某个属性转换为ref响应式数据
4 toRefs函数 同时将reactive响应式数据中的多个属性转化为ref响应式数据
<script>
import {ref} from 'vue'
export default{//export default是默认导出的意思
setup(){
//定义一些要展示到html上的一些数据 变量/对象
let counter=ref(1)//ref相当于将counter转成一个对象,其值代表此对象value属性的值{value:1}
//让counter自增的方法
function counterIncr(){
counter.value++
}
//让counter自减的方法
function counterDecr(){
counter.value--
}
//显示counter值得方法
function showCounter(){
alert(counter.value)
}
return{
counter,
counterIncr,
counterDecr,
showCounter
}
}
}
</script>
<template>
<div>
<button @click="counterIncr">+</button>
<span v-text="counter"></span>
<button @click="counterDecr">-</button>
<button @click="showCounter">showCounter</button>
</div>
</template>
<style scoped>
</style>
setup语法糖:
export default{
setup(){
}
}------------可以简化为在script标签后添加一个setup
渲染
插值表达式和文本渲染
> 插值表达式:最基本的数据绑定形式是文本插值,它使用的是“Mustache”语法 ,即双大括号`{{}}`
+ 插值表达式是将数据渲染到元素的指定位置的手段之一
+ 插值表达式不绝对依赖标签,其位置相对自由
+ 插值表达式中支持javascript的运算表达式
+ 插值表达式中也支持函数的调用
插值表达式
插值表达式:将变量/响应式数据关联到页面元素上
语法:{{数据名字/函数/对象调用API}}
注意:
插值表达式不依赖标签,没有标签可以单独使用
插值表达式中可以调用函数,将函数的返回值渲染到指定位置
插值表达式支持一些常见的运算符
插值表达式中支持对象调用一些API
代码举例:
<script setup>
//定义一些常见数据
let msg="hello vue3"
let getMsg=()=>{
return "hello vue3 message"
}
let age=19
let bee="蜜 蜂"
//Json串
let carts=[{name:"可乐",price:3,number:10},{name:"薯片",price:6,number:8}]
//定义一个获得商品总金额的方法
function compute(){
let count=0
for(let index in carts){
count+=carts[index].price*carts[index].number
}
return count
}
</script>
<template>
<div>
<!--将数据绑定到下面的元素上-->
<h1>{{msg}}</h1>
<!--插值表达式不依赖标签,没有标签可以单独使用-->
msg的值为{{msg}}<br/>
<!--插值表达式中可以调用函数,将函数的返回值渲染到指定位置-->
msg的值为{{getMsg()}}<br/>
<!--插值表达式支持一些常见的运算符-->
年龄:{{ age }},是否成年{{ age>18? '是':'否' }}<br/>
<!--插值表达式中支持对象调用一些API-->
{{ bee.split(' ').reverse().join('') }}<br/>
总金额:{{ compute() }}
</div>
</template>
<style scoped>
</style>
文本渲染
> 为了渲染双标中的文本,我们也可以选择使用`v-text`和`v-html`命令
+ v-*** 这种写法的方式使用的是vue的命令
+ v-***的命令必须依赖元素,并且要写在元素的开始标签中
+ v-***指令支持ES6中的字符串模板
+ 插值表达式中支持javascript的运算表达式
+ 插值表达式中也支持函数的调用
+ v-text可以将数据渲染成双标签中间的文本,但是不识别html元素结构的文本
+ v-html可以将数据渲染成双标签中间的文本,识别html元素结构的文本
Attribute属性渲染
> 想要渲染一个元素的 attribute,应该使用 `v-bind`指令
+ 由于插值表达式不能直接放在标签的属性中,所有要渲染元素的属性就应该使用v-bind
+ v-bind可以用于渲染任何元素的属性,语法为 `v-bind:属性名='数据名'`, 可以简写为 `:属性名='数据名'`
事件的绑定
> 我们可以使用 `v-on` 来监听 DOM 事件,并在事件触发时执行对应的 Vue的JavaScript代码。
+ 用法:`v-on:click="handler"` 或简写为 `@click="handler"`
+ vue中的事件名=原生事件名去掉`on` 前缀 如:`onClick --> click`
+ handler的值可以是方法事件处理器,也可以是内联事件处理器
+ 绑定事件时,可以通过一些绑定的修饰符,常见的事件修饰符如下
+ `.once:只触发一次事件。[重点]`
+ `.prevent:阻止默认事件。[重点]`
+ .stop:阻止事件冒泡。
+ .capture:使用事件捕获模式而不是冒泡模式。
+ .self:只在事件发送者自身触发时才触发事件。
代码举例:
<script setup>
import {ref} from 'vue'
/*
事件渲染命令:
格式:
v-on:事件名称="函数名()"
简写:@事件名="函数名()"
注意:
原生js的事件名是on*** onclick onblur onfocuse
vue中的事件名去掉on click blur focuse
内联事件处理器:事件名后面直接等于原本要写在函数中的代码
*/
function fun1(){
alert("hi")
}
let count=ref(1)
function fun2(){
count.value++
}
function fun3(){
let flag= confirm("确定要访问目标链接吗")
if(!flag){
//原生js编码方式阻止组件的默认行为
event.preventDefault()
}
}
function fun4(){
alert("超链接被点击了")
}
</script>
<template>
<div>
<!--事件的绑定函数-->
<button v-on:click="fun1()">hello</button>
<!--内联事件处理器:事件名后面直接等于原本要写在函数中的代码-->
<button v-on:click="fun2()">+</button>
{{ count }}
<!--内联-->
<button v-on:click="count--">-</button>
<!--事件的修饰符(写在事件名后面).once事件只绑定一次;.prevent修饰符阻止组件的默认行为-->
<button v-on:click.once="count--">-</button>
<br>
<!--阻止方式一-->
<a href="http://www.atguigu.com" v-on:click="fun3()">尚硅谷</a>
<!--阻止方式二-->
<a href="http://www.atguigu.com" v-on:click.prevent="fun4()">尚硅谷</a>
</div>
</template>
<style scoped>
</style>
条件渲染
> `v-if` 条件渲染
+ `v-if='表达式' `只会在指令的表达式返回真值时才被渲染
+ 也可以使用 `v-else` 为 `v-if` 添加一个“else 区块”。
+ 一个 `v-else` 元素必须跟在一个 `v-if` 元素后面,否则它将不会被识别。
> `v-show`条件渲染扩展:
+ 另一个可以用来按条件显示一个元素的指令是 `v-show`。其用法基本一样:
+ 不同之处在于 `v-show` 会在 DOM 渲染中保留该元素;`v-show` 仅切换了该元素上名为 `display` 的 CSS 属性。
+ `v-show` 不支持在 `<template>` 元素上使用,也不能和 `v-else` 搭配使用.
`v-if` `v-show`区别
+ `v-if` 是“真实的”按条件渲染,因为它确保了在切换时,条件区块内的事件监听器和子组件都会被销毁与重建。
+ `v-if` 也是**惰性**的:如果在初次渲染时条件值为 false,则不会做任何事。条件区块只有当条件首次变为 true 时才被渲染。
+ 相比之下,`v-show` 简单许多,元素无论初始条件如何,始终会被渲染,只有 CSS `display` 属性会被切换。
+ 总的来说,`v-if` 有更高的切换开销,而 `v-show` 有更高的初始渲染开销。因此,如果需要频繁切换,则使用 `v-show` 较好;如果在运行时绑定条件很少改变,则 `v-if` 会更合适。
列表渲染
> 我们可以使用 `v-for` 指令基于一个数组来渲染一个列表。
+ `v-for` 指令的值需要使用 `item in items` 形式的特殊语法,其中 `items` 是源数据的数组,而 `item` 是迭代项的**别名**:
+ 在 `v-for` 块中可以完整地访问父作用域内的属性和变量。`v-for` 也支持使用可选的第二个参数表示当前项的位置索引。
双向绑定
> 单项绑定和双向绑定
+ 单向绑定: 响应式数据的变化会更新dom树,但是dom树上用户的操作造成的数据改变不会同步更新到响应式数据
+ 双向绑定: 响应式数据的变化会更新dom树,但是dom树上用户的操作造成的数据改变会同步更新到响应式数据
+ 用户通过表单标签才能够输入数据,所以双向绑定都是应用到表单标签上的,其他标签不行
+ v-model专门用于双向绑定表单标签的value属性,语法为 `v-model:value=''`,可以简写为 `v-model=''`
+ v-model还可以用于各种不同类型的输入,`<textarea>`、`<select>` 元素。
代码举例:
代码:
<script setup>
import {ref,reactive} from 'vue'
/**
* 单项绑定 v-bind 响应式数据发生变化时,更新dom树 用户操作造成页面的内容改变不会影响响应式数据
* 双向绑定 v-model 页面上的数据由于用户的操作造成了改变,也会同步修改对应的响应式数据
* 双向绑定一般都用于表单标签
* 双向绑定也有人称呼为收集表单信息的命令
* v-model:value="数据" 双向 绑定
* v-model:value 一般都省略 :value
*/
let message=ref("zhangsan")
let person=reactive(
{
username:"",
userPwd:"",
intro:"",
pro:""
}
)
let has=ref([])
function cearlForm(){
person.intro="",
person.pro="",
person.userPwd="",
person.username="",
has.value.splice(0,has.value.length)
}
</script>
<template>
<div>
<input type="text" v-model="person.username"><br>
<input type="password" v-model="person.userPwd"><br>
爱好:
<input type="checkbox" v-model="has" value="sing">唱
<input type="checkbox" v-model="has" value="dance">跳
<input type="checkbox" v-model="has" value="rap">rap
<!--复选框/单选框:
v-model:指明关联的数组是什么
勾选时往数组中放的元素还需要设置属性value的值
-->
<br>
简介:
<textarea v-model="person.intro" cols="30" rows="10"></textarea><br>
籍贯:
<select v-model="person.pro">
<option value="京">京</option>
<option value="津">津</option>
<option value="冀">冀</option>
</select>
<br>
<button @click="cearlForm()">清空</button>
<br>
{{ person }}
<br>
{{ has }}
<hr>
<input type="text" v-bind:value="message"><br>
<!--单项绑定:用户在页面操作修改数据不会改变对应的响应式数据-->
<input type="text" v-model="message"><br>
<!--双向绑定:用户在页面操作修改数据会改变对应的响应式数据-->
{{ message }}
</div>
</template>
<style scoped>
</style>
效果
计算属性
* 函数:每使用一次就执行一次
* 计算属性(一个属性的值要通过函数计算才能获得,且其值要用computed包裹):
* 通过计算属性获得数据:每次使用时,如果和上一次使用时,数据没有变化,则直接使用上一次得结果
* 只要但其引用的响应式数据发生了变化,其中的computed才会执行这个函数
Vue3_数据监听器
> 计算属性允许我们声明性地计算衍生值。然而在有些情况下,我们需要在状态变化时执行一些“副作用”:例如更改 DOM,或是根据异步操作的结果去修改另一处的状态。我们可以使用 [watch]在每次响应式状态发生变化时触发回调函数:
+ watch主要用于以下场景:
+ 当数据发生变化时需要执行相应的操作
+ 监听数据变化,当满足一定条件时触发相应操作
+ 在异步操作前或操作后需要执行相应的操作
> 监控响应式数据(watch):
//watch函数监听一个ref的响应式数据
//传入监听的响应时数据,再传入处理函数(函数的两个参数为newValue,oldValue)
watch(firstname,(newValue,oldValue)=>{
console.log(`${oldValue}变为${newValue}`)
fullname.value=newValue+lastname.name
})
//watch函数监听一个reative响应式数据watch(函数返回要监听的响应式数据,处理函数)
// ---->专门监听reactive响应式数据中的一个属性
watch(()=>{return lastname.name},(newValue,oldValue)=>{
console.log(`${oldValue}变为${newValue}`)
fullname.value=firstname.value+newValue
})
//watch函数监听一个reative响应式数据watch(函数返回要监听的响应式数据,处理函数)
// ---->专门监听reactive响应式数据中的多个属性
watch(()=>{return lastname.name},(newValue,oldValue)=>{
//监听多个属性时(newValue与oldValue都表示lastname这个对象
//注意监听多个属性时要加上一个函数{deep:true,immediate:true}
//其中immediate:true的意思是立即执行;watch默认是单监听的响应式数据发生改变时才执行的
fullname.value=firstname.value+newValue
},{deep:true,immediate:true})
> 监控响应式数据(watchEffect):
+ watchEffect默认监听所有的响应式数据
//watchEffect:可以同时监听不同的(ref/reactive)响应式数据
//任何的响应式数据,如果想监听,直接监听即可,无需将要将监听的响应式数据作为参数
//函数体中出现了那些响应式数据,当这些再函数体中出现的响应式数据发生变化时,就会触发函数的执行
watchEffect(()=>{
fullname=firstname.value+lastname.name
})
> `watch` 与 `watchEffect`
+ `watch` 和 `watchEffect` 都能响应式地执行有副作用的回调。它们之间的主要区别是追踪响应式依赖的方式:
+ `watch` 只追踪明确侦听的数据源。它不会追踪任何在回调中访问到的东西。另外,仅在数据源确实改变时才会触发回调。`watch` 会避免在发生副作用时追踪依赖,因此,我们能更加精确地控制回调函数的触发时机。
+ `watchEffect`,则会在副作用发生期间追踪依赖。它会在同步执行过程中,自动追踪所有能访问到的响应式属性。这更方便,而且代码往往更简洁,但有时其响应性依赖关系会不那么明确。
Vue3_生命周期
+ 常见钩子函数
+ onMounted() 注册一个回调函数,在组件挂载完成后执行。
+ onUpdated() 注册一个回调函数,在组件因为响应式状态变更而更新其 DOM 树之后调用。
+ onUnmounted() 注册一个回调函数,在组件实例被卸载之后调用。
+ onBeforeMount() 注册一个钩子,在组件被挂载之前被调用。
+ onBeforeUpdate() 注册一个钩子,在组件即将因为响应式状态变更而更新其 DOM 树之前调用。
+ onBeforeUnmount() 注册一个钩子,在组件实例被卸载之前调用。
Vue组件
组件基础
> 组件允许我们将 UI 划分为独立的、可重用的部分,并且可以对每个部分进行单独的思考。组件就是实现应用中局部功能代码和资源的集合!在实际应用中,组件常常被组织成层层嵌套的树状结构:
+ 这和我们嵌套 HTML 元素的方式类似,Vue 实现了自己的组件模型,使我们可以在每个组件内封装自定义内容与逻辑。
+ 组件化:对js/css/html统一封装,这是VUE中的概念
+ 模块化:对js的统一封装,这是ES6中的概念
+ 组件化中,对js部分代码的处理使用ES6中的模块化
组件传参问题
父组件
<script setup>
/**
* 父组件接收数据
* 让在子组件中定义的传数据的事件绑定一个接收函数receiver( @sendMenu="receiver"该函数不用带())
* 传入接收函数receiver的实参就是要接收的数据
*
* 父组件向子组件传递数据
* 在子组件中自定义一个属性(v-bind:message="menu")并且要渲染
* 让其属性值为要传递的数据
*/
import {ref} from 'vue'
/**引入多个组件 */
import Hearder from './components/Hearder.vue';
import Navigator from './components/Navigator.vue';
import Content from './components/Content.vue';
let menu=ref("")
//定义接收传递数据的函数
function receiver(data){
menu.value=data
}//data就是传递过来的数据
</script>
<template>
<div>
<Hearder class="header"></Hearder>
<Navigator class="navigator" @sendMenu="receiver"></Navigator>
<!--
为sendMenu事件准备一个函数接收传递过来的数据
这里的函数不写()代表默认传入事件对象,也就是子组件sendMenu事件携带的data
-->
<Content class="content" v-bind:message="menu"></Content>
<!--
父传子:给子组件Content定义一个属性(属性名自定义,但在子组件接收数据时就要用该名),
让其属性值等于要传递的数据值;且该属性是需要在子组件Content中被渲染(展示到页面)的所以要用v-bind
-->
</div>
</template>
<style scoped>
.header{
height: 80px;
border: 1px solid red;
}
.navigator{
width: 15%;
height: 600px;
border: 1px,solid green;
float: left;
}
.content{
width: 83%;
height: 600px;
border: 1px solid blue ;
float: right;
}
</style>
子组件
<script setup>
</script>
<template>
<div>
欢迎:XXX <a href="#">退出登录</a>
</div>
</template>
<style scoped>
</style>
子组件
<script setup>
/**向父组件发送参数
* 导入defineEmits函数,通过defineEmits定义一个提交是数据的事件sendMenu,
* 并得到一个emits变量(实际上它是一个方法)
* 定义一个传递数据的函数send,上元素绑定该函数
* 在传递函数send中调用上面得到的方法emits("事件名",要传递的数据)
*/
//defineEmits用于定义向父组件提交数据的事件以及正式提交的数据
import {defineEmits} from 'vue'
//定义一个向父组件提交数据的事件,事件名称自定义(在父组件中要通过该事件名称接收数据)
let emits=defineEmits(["sendMenu"])
//定义一个提交数据的方法
function send(data){
emits("sendMenu",data)//用emits向父组件提交了一个事件(前面定义的),该事件携带了data
}
</script>
<template>
<div>
<ul>
<li @click="send('学员管理')">学员管理</li>
<!--注意send函数中传递的数据要用 ''引起来,不然会将器当作变量提交-->
<li @click="send('图书管理')">图书管理</li>
<li @click="send('请假管理')">请假管理</li>
<li @click="send('考试管理')">考试管理</li>
<li @click="send('讲师管理')">讲师管理</li>
</ul>
</div>
</template>
<style scoped>
</style>
子组件
<script setup>
/**
* 接收父组件的参数
* 导入defineProps函数
* 通过defineProps函数定义一个响应式数据,名称就为父组件中为子组件定义的接收数据的属性名,
* message:String
* String是要接收的数据的类型
*/
import {defineProps} from 'vue'
//通过defineProps函数定义一个响应式数据,名称就为父组件中为子组件定义的接收数据的属性名
defineProps({
message:String
//String是要接收的数据的类型
})
</script>
<template>
<div>
这里是内容展示页面
<br>
{{ message }}
</div>
</template>
<style scoped>
</style>
效果