Vue3笔记

发布于:2025-02-28 ⋅ 阅读:(40) ⋅ 点赞:(0)

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 启动项目

此时运行项目不再使用vscodego 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 事件,并在事件触发时执行对应的 VueJavaScript代码。

+ 用法:`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-modelvalue 一般都省略 :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>

效果