Skip to content

概述

vue 是一套用于构建用户界面的前端框架。

特性

  • 数据驱动视图
  • image-20230421164324009
  • 双向数据绑定
  • image-20230421164410966
  • mvvm
  • image-20230421164542858
  • 工作原理
  • image-20230421164605877

使用步骤

  • 导入 vue.js 的 script 脚本文件
  • 在页面中声明一个将要被 vue 所控制的 DOM 区域
  • 创建 vm 实例对象(vue 实例对象)
  • image-20230421165811667
  • image-20230421170058229

指令

  • v-text="变量名称"替换元素标签之间的内容(会覆盖原有的元素)
  • 只能渲染纯文本内容
  • <p v-text="username">...</p>
  • {{}}解决覆盖的问题,插值表达式
    • <p>...{{name}}</p>
  • v-html

    • 可以渲染为页面的 HTML 元素
  • v-bind属性绑定,要为元素的属性动态绑定属性值

  • <... v-bind:属性名=“变量”>

  • 可以缩写为:
  • 除了支持绑定简单的数据值之外,还支持 Javascript 表达式的运算

  • v-on事件绑定指令

  • <button v-on:click="addCount[(传参)]"></button>

  • 简写@click
  • 通过 v-on 绑定的事件处理函数,需要在 methods 节点中进行声明:
    • image-20230421172028798
  • 原生 DOM 对象有 onclick、oninput、onkeyup 等原生事件,替换为 vue 的事件绑定形式后, 分别为:v-on:click、v-on:input、v-on:keyup
  • 事件对象 even:与dom类似,使用vue绑定时也可以收到事件对象event
    • image-20230421172419119
    • $event 是 vue 提供的特殊变量,用来表示原生的事件参数对象 event。$event 可以解决事件参数对象 event 被覆盖的问题。
    • image-20230421172936590
  • 事件修饰符
    • 方便的对事件的触发进行控制
    • image-20230421173117008
  • 按键修饰符

    • 在监听键盘事件时,我们经常需要判断详细的按键。此时,可以为键盘相关的事件添加按键修饰符
    • image-20230421173223726
  • v-model双向数据绑定

  • 者在不操作 DOM 的前提下,快速获取表单的数据。

    • 只能配合表单元素一起使用
  • image-20230421173401398
  • 的修饰符

    • image-20230421173446744
  • 条件渲染指令v-ifv-show

  • 按需控制 DOM 的显示与隐藏

  • image-20230421173721137

  • v-else v-else-if

    • image-20230421173814929
  • 更改变量后可能不会实时刷新,可以获取组件,并强制进行重新加载如formRef2.value.$forceUpdate();

  • 列表渲染指令

  • 基于一个数组来循环渲染相似的 UI 结构

  • 要使用 item in items 的特殊语法
    • items 是待循环的数组
    • item 是当前的循环
  • image-20230421174013215
  • v-for 指令还支持一个可选的第二个参数,即当前项的索引。

    • (item,index) in list
  • key:当列表的数据变化时,默认情况下,vue 会尽可能的复用已存在的 DOM 元素,从而提升渲染的性能。但这种 默认的性能优化策略,会导致有状态的列表无法被正确更新。

    • 需要为每项提供一个唯一的 key 属性
    • image-20230421174231511
    • image-20230421174300027

自定义组件

私有自定义指令
  • 声明
  • directives节点下声明私有自定义指令
  • image-20230422001318000
  • 使用时需要加上前缀v
  • v-focus
全局自定义指令
  • 声明
  • 全局共享的自定义指令需要通过“单页面应用程序的实例对象”进行声明
  • image-20230422001511381
  • mounted 函数只在元素第一次插入DOM 时被调用,当DOM 更新时mounted 函数不会被触发。updated 函数会在每次DOM 更新完成后被调用。
  • image-20230422001806347
  • 如果mounted 和updated 函数中的逻辑完全相同,则可以简写成如下格式:
  • image-20230422001823762
  • 指令的参数值
  • image-20230422001840122

过滤器

  • 过滤器(Filters)常用于文本的格式化。
  • 过滤器应该被添加在 JavaScript 表达式的尾部,由“管道符”进行调用
  • image-20230421174608756
  • 过滤器可以串联地进行调用...|...|...

定义

  • 以在 filters 节点中定义过滤器
  • image-20230421174642356
  • 在 filters 节点下定义的过滤器,称为“私有过滤器”,因为它只能在当前 vm 实例所控制的 el 区域内使用。
  • 全局过滤器:望在多个 vue 实例之间共享过滤器
  • Vue.filter('全局过滤器的名字',(str)=>{处理函数})
  • 传参
  • image-20230421175001590
    • 第一个参数保留为管道符前面传入的

组件

vite

  • 用于创建vue的SPA( 单页面应用程序)项目
  • 创建:
  • npm init vite-app 项目名称
  • cd 项目名称
  • npm inastall
  • npm run dev
    • 令会启动一个开发服务器,该服务器会监听您的源代码更改并自动重新编译和刷新您的应用程序,以便在开发过程中实时查看更改的效果。
  • 文件目录
  • image-20230421201411455

    • vue 要做的事情很单纯:通过main.js 把App.vue 渲染到index.html 的指定区域中。
    • App.vue 用来编写待渲染的模板结构
    • index.html 中需要预留一个el 区域
    • main.js 把App.vue 渲染到了index.html 所预留的区域中
  • 过程:

  • App.vue 中编写模板结构
    • image-20230421201750908
  • index.html 中预留el 区域
    • image-20230421201816981
  • main.js中进行渲染
    • 把App.vue 中的模板内容渲染到index.html 页面的el 区域中
    • image-20230421201954492

组件化开发

  • 根据封装的思想,把页面上可重用的部分封装为组件,从而方便项目的开发和维护。
  • vue 中规定组件的后缀名是.vue。之前接触到的App.vue 文件本质 上就是一个vue 的组件。
  • vue 中组件的引用原则:先注册后使用

组件的构成

  • 每个.vue 组件都由3 部分构成
  • template-> 组件的模板结构
  • script-> 组件的JavaScript 行为
  • style-> 组件的样式
  • 每个组件中必须包含template 模板结构,而script 行为和style 样式是可选的组成部分。

  • template

  • 在template节点中,支持使用指令语法来辅助渲染dom结构
  • image-20230421202644564

  • script

  • 组件内的\

    ```

    • 默认情况下,切换动态组件时无法保持组件的状态。此时可以使用vue 内置的\组件保持动态组件的状态。

    • 会缓存动态组件的实例,避免每次切换组件都要重新创建实例。

    • 具体来说,<keep-alive>会将其包裹的组件缓存到内存中,如果组件再次被使用,则可以直接从缓存中取出,而不需要重新创建实例和重新渲染组件。这样可以大大提高组件的性能。

    插槽

    • 插槽(Slot)是vue 为组件的封装者提供的能力。允许开发者在封装组件时,把不确定的、希望由用户指定的 部分定义为插槽
    • image-20230421235058332
    • image-20230421235131722
    • 如果在封装组件时没有预留任何插槽,则用户提供的任何自定义内容(\元素中的内容)都会被丢弃。
    • 封装组件时,可以为预留的插槽提供后备内容(默认内容)。如果组件的使用者没有为插槽提供任何 内容,则后备内容会生效。
    • <slot>后备内容<\slot>
    • 具名插槽
    • 如果在封装组件时需要预留多个插槽节点,则需要为每个插槽指定具体的name名称
    • 组件中直接给slot组件添加name属性
    • 使用组件时用<template v-slot:插槽名称></template>
      • v-slot可以简写为#
    • image-20230421235536709

    作用域插槽

    • 声明作用域插槽
    • v-slot:default=""表示作用域插槽
    • 可以通过作用域插槽把表格每一行的数据传递给组件的使用者。
    • image-20230422001103672
    • 使用作用域插槽
    • 声明和使用时的名称不需要相同
    • image-20230422001130705

    • 作用域插槽

    • 为预留的插槽绑定props 数据

    • 作用域插槽允许子组件向父组件暴露具有可复用性的插槽内容,这样父组件就可以使用子组件提供的插槽内容来自定义渲染子组件的部分内容。(数据从子组件传输到父组件)
    • image-20230422000119155
    • html <el-table-column prop="rate" label="涨跌幅"> <template #default="{ row }"> <span :style="{ color: row.rate > 0 ? 'red' : 'green' }">{{ row.rate }}%</span> </template> </el-table-column>
    • 解构作用域插槽的Prop

    • 简化数据的接收过程

    • 解构作用域插槽的 Prop 不仅可以用来获取单个属性值,还可以用来获取多个属性值

      • vue <child-component> <template v-slot:default="{ propA, propB }"> <p>{{ propA }}</p> <p>{{ propB }}</p> </template> </child-component>

    axios前后端交互(http)

    • 安装:npm install axios

    • 引入import axios from 'axios'

    • 全局使用

    • image-20230421232437986

    • 之后每个组件中都可以使用this.$http来访问axios对象

    • 在使用Axios发送HTTP请求时,响应会被封装成一个response对象

    • 含以下属性:

      • data: 服务器返回的响应数据。
      • status: HTTP状态码。
      • statusText: HTTP状态消息。
      • headers: 响应头。
      • config: 请求的配置信息。
      • request: 发送请求的XMLHttpRequest对象。
    • get:获取数据,请求指定的信息,返回实体对象

    • js axios.get('/api/users').then((response) => { console.log(response.data); });

    • post:向指定资源提交数据(例如表单提交或文件上传)

    • js axios.post('/api/users', { name: 'Alice', age: 20, }).then((response) => { console.log(response.data); });

    • put:更新数据,从客户端向服务器传送的数据取代指定的文档的内

    • 与post的区别:

      • image-20230421233359578
    • js axios.put('/api/users/1', { name: 'Alice', age: 25, }).then((response) => { console.log(response.data); });

    • delete:请求服务器删除指定的数据

    • js axios.delete('/api/users/1').then((response) => { console.log(response.data); });

    • server.proxy代理解决网络阻止问题

    • 在开发环境中,如果我们的应用程序需要调用远程API,通常需要通过HTTP请求来访问它们。但是,由于CORS(跨源资源共享)策略的限制,浏览器默认情况下禁止跨域请求。这时候我们可以使用 server.proxy 选项来解决跨域请求问题

    • 拦截器:对请求以及响应添加通用的预处理

    • ```js // 添加请求拦截器 axios.interceptors.request.use(function (config) { // 在发送请求之前做些什么 return config; }, function (error) { // 对请求错误做些什么 return Promise.reject(error); });

      // 添加响应拦截器 axios.interceptors.response.use(function (response) { // 2xx 范围内的状态码都会触发该函数。 // 对响应数据做点什么 return response; }, function (error) { // 超出 2xx 范围的状态码都会触发该函数。 // 对响应错误做点什么 return Promise.reject(error); }); ```

    • 如对错误进同一处理,在请求前面添加token头

    • 带头参数

    • js return axios.get("/news/index",{ headers:{ 'Content-Type':'application/x-www-form-urlencoded' }, params: { key: "022856a900e4d201e1d865f0866863", page: page, page_size: 10, type: "caijing", is_filter: 1 }, })

    路由

    • SPA 指的是一个web 网站只有唯一的一个HTML 页面,所有组件的展示与切换都在这唯一的一个页面内完成。 此时,不同组件之间的切换需要通过前端路由来实现。
    • 是Hash 地址与组件之间的对应关系。
    • 工作方式
    • image-20230422002044407

    vue-router

    基本用法

    • 安装npm i vue-router
    • 定义路由组件
    • 假设项目中有三个vue组件,现在要通过路由来控制他们的展示与切换
    • 使用\声明路由链接,\声明路由占位符
      • 路由链接:
      • 它提供了一个 HTML 标签来创建链接,使用户可以点击链接跳转到不同的路由页面。
      • <router-link to="/about">About</router-link>
      • 路由占位符:
      • 当用户访问某个路由时,Vue Router 会根据当前路由匹配到的组件渲染到 <router-view></router-view>
    • image-20230422002814595

    • 创建路由模块

    • 在项目中创建router.js 路由模块
    • 从vue-router 中按需导入两个方法
      • image-20230422002930316
    • 导入需要使用路由控制的组件
      • image-20230422002949692
    • 创建路由实例对象
      • image-20230422003003099
    • 向外共享路由实例对象
      • image-20230422003041024
    • 在main.js 中导入并挂载路由模块

      • image-20230422003102304
    • 404匹配

    • { path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound },

    路由重定

    • 路由重定向指的是:用户在访问地址A 的时候,强制用户跳转到地址C
    • 通过路由规则的redirect属性,指定一个新的路由地址
    • image-20230422003234311

    路由高亮

    • 将激活的路由链接进行高亮显示
    • 被激活的路由链接,默认会应用一个叫做router-link-active的类名。开发者可以使用此类名选择器,为激活 的路由链接设置高亮的样式
    • image-20230422003350822

    嵌套路由

    • 通过路由实现组件的嵌套展示,叫做嵌套路由。
    • 声明子路由链接和子路由占位符
    • 在About.vue 组件中,声明tab1 和tab2 的子路由链接以及子路由占位符。
    • image-20230422003510627
    • 在父路由规则中,通过children属性嵌套声明子路由规则
    • 在router.js 路由模块中,导入需要的组件,并使用children 属性声明子路由规则。
    • image-20230422003649634

    动态路由匹配

    • 把Hash 地址中可变的部分定义为参数项,从而提高路由规则的复用性

    • image-20230422003825853

    • 通过动态路由匹配的方式渲染出来的组件中,可以使用$route.params 对象访问到动态匹配的参数值。

      • image-20230422003908374

      • 为了简化,可以使用pros传参,即去掉$route.params,直接使用{{id}}

    编程式导航

    • 通过调用API 实现导航的方式,叫做编程式导航。与之对应的,通过点击链接实现导航的方式,叫做声明式导航。
    • 普通网页中点击 链接、vue 项目中点击 都属于声明式导航
    • 普通网页中调用location.href 跳转到新页面的方式,属于编程式导航
    • this.$router.push('hash 地址')跳转到指定Hash 地址,从而展示对应的组件
    • this.$router.go(数值n) 实现导航历史的前进、后退

    命名路由

    • 通过name 属性(不可以重复)为路由规则定义名称的方式,叫做命名路由。
    • image-20230422004201920
    • 为 标签动态绑定to 属性的值,并通过name 属性指定要跳转到的路由规则。期间还可以用 params 属性指定跳转期间要携带的路由参数。
    • image-20230422004240829
    • 调用push 函数期间指定一个配置对象,name是要跳转到的路由规则、params是携带的路由参数(同理)

    导航守卫

    • 导航守卫可以控制路由的访问权限。示意图如下

    • image-20230422004316407

    • 声明全局导航守卫

    • image-20230422004344599

    ##### 守卫方法

    • 全局导航守卫的守卫方法中接收3 个形参
      • image-20230422004439864
    • 在守卫方法中如果不声明next 形参,则默认允许用户访问每一个路由!;在守卫方法中如果声明了next 形参,则必须调用next() 函数,否则不允许用户访问任何一个路由!
      • 直接放行:next()
      • 强制其停留在当前页面:next(false)
      • 强制其跳转到登录页面:next('/login')
    • image-20230422004612105

    补充

    • 点击按钮跳转
    • 在template中使用el-button type="primary" @click="$router.push('/')">回到首页 </el-button>

    transition

    • 过渡动画

    • 如可以用于包住一组v-if v-else

    • html <transition name="fade"> ... </transition>

    • 使用vueuse库

    • 安装@vueuse/integrations universal-cookie

    • 引入

    • js import { useCookies } from '@vueuse/integrations/useCookies'; const cookie = useCookies();

    • 设置

    • cookie.set("名称","值")

    • 获取

    • cookie.get("名称")

    • 删除

    • cookie.remove("名称 ")

    script setup

    • <script setup></script>
    • setup 函数中,所有 ES 模块导出都被认为是暴露给上下文的值,并包含在 setup() 返回对象中。
    • 不需要export default

    功能

    • 自动注册子组件
    • 不需要components
    • 可以直接在模板中使用 props 和响应式变量
    • 自动处理了响应式变量和 props 的声明和引用,不需要手动导入和使用 refreactivetoRefs 等 API。

    几种暴露方式

    • defineExpose暴露实例,例如提供函数(成员方法)

    • defineProps提供接口,允许外界输入值(修改)

    • js const props = defineProps({ title:String, size:{ type:String, default:"45%" }, destroyOnClose:{ type:Boolean, default:false }, confirmText:{ type:String, default:"确定" }, })

    • defineEmits定义对外信号事件

    • const emit = defineEmits(["submit"])

    keep-alive

    • 减少页面重复加载,提高响应速度

    • js <router-view v-slot="{ Component }"> <keep-alive :max="10"> <component :is="Component"></component> </keep-alive> </router-view>

    • max表示缓存数目的上限

    transition全局过渡动画

    • html <transition name="fade"></transition>

    • ```css

    ```

    • 要求页面只能有一个div根节点

    响应式与非响应式

    • 以下是响应式对象的特点:
    • Vue.js 可以追踪它们的变化。
    • 当响应式对象发生变化时,Vue.js 会自动更新相关 DOM。
    • 响应式对象应该使用 Vue.js 提供的特定方式创建或初始化。
    • Vue.js 只会追踪对象的属性,而不是对象本身。
    • 响应式对象应该是顶层对象,而不是嵌套在其他非响应式对象中。
    • 以下是一些不是响应式对象的示例:
    • 原始类型的值(例如数字、字符串、布尔值等)。
    • 非顶层对象(例如一个嵌套在其他对象中的对象)。
    • 通过 Object.freeze() 函数冻结的对象。
    • 在创建对象后添加的属性。Vue.js 只会追踪已经存在的属性,而不会追踪新添加的属性。如果需要追踪新添加的属性,可以使用 Vue.set() 方法或者修改对象的属性值,触发 Vue.js 监测变化。
    • 实现
    • script中使用data
    • script setup中使用ref对象实现
    • 或者强制刷新组件,实现伪响应式

    compositon-api

    setup

    • 与传统的将 props、data、computed、methods 分类放在export default中相比,新的模式是创建一个setup函数(或直接script setup)包含多个功能的不同组成

    • setup函数会在 beforeCreate 之前被调用(早于dom完成渲染),因此获取dom元素要放在onmonuted中

    • ```vue

    ```

    • 如果使用<script setup>则想到与default export中的内容,整个部分都会暴露

    • 参数

    • 第一个参数位props,第二个参数为context(上下文对象)

    • vue export default { props: { name: String, }, setup(props) { console.log(props.name) }, }

    • defineProps

      • 用与声明变量类型以及赋初值

      • js const props=defineProps({ num: { type: Number, default: 0 } })

      • 访问时也要通过props

      • 数组、对象必须有默认值,可以初始化为空

      • js const props = defineProps({ value: { type: Array, default: function(v) { return } } })

    响应式系统

    • ref

    • 生成const count = ref(0)

    • 在脚本中访问使用.value
    • 在模板中使用会自动解套不需要.value

    • computed

    • 以函数的形式定义,返回一个value不可修改的ref对象

      • ```js const count = ref(1) const plusOne = computed(() => count.value + 1)

      console.log(plusOne.value) // 2

      plusOne.value++ // 错误! ```

    • 传入get、set函数创建可以读写的

      • ```js const count = ref(1) const plusOne = computed({ get: () => count.value + 1, set: (val) => { count.value = val - 1 }, })

      plusOne.value = 1 console.log(count.value) // 0 ```

    • watcheffect

    • 立即执行传入的一个函数,并响应式追踪其依赖,并在其依赖变更时重新运行该函数(当函数的依赖项发生改变时再次执行函数)

      • ```js const count = ref(0)

      watchEffect(() => console.log(count.value)) // -> 打印出 0

      setTimeout(() => { count.value++ // -> 打印出 1 }, 100) ```

    • 停止侦听,定义停止函数,用于调用

      • ```js const stop = watchEffect(() => { / ... / })

      // 之后 stop() ```

    • watch

    • 侦听单个数据源

    • js watch(count, (count, prevCount) => { /* ... */ })

    • 侦听多个数据源

    • js watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => { /* ... */ })

    • emit

    • js const emit = defineEmits(["alertSome"]) function clickButton(){ //todo emit("alertSome",6666) }

    生命周期

    - image-20230509215859488

    vite

    配置

    • 设置路径别名:

    • ```js import path from 'path' export default defineConfig({

      //设置别名 resolve: { alias: { '~':path.resolve(__dirname, "src"), }, } }) ```