JavaWeb——第七章 前端工程化_2

第七章 前端工程化_2

    • 六、Vue3视图渲染技术
      • 6.1 模版语法
        • 6.1.1 插值表达式和文本渲染
        • 6.1.2 Attribute属性渲染
        • 6.1.3 事件的绑定
      • 6.2 响应式基础
        • 6.2.1 响应式需求案例
        • 6.2.2 响应式实现关键字ref
        • 6.2.3 响应式实现关键字reactive
        • 6.2.4 扩展响应式关键字toRefs 和 toRef
      • 6.3 条件和列表渲染
        • 6.3.1 条件渲染
        • 6.3.2 列表渲染
      • 6.4 双向绑定
      • 6.5 属性计算
      • 6.6 数据监听器
      • 6.7. Vue生命周期
        • 6.7.1 生命周期简介
        • 6.7.2 生命周期案例
      • 6.8 Vue组件
        • 6.8.1 组件基础
        • 6.8.2 组件化入门案例
        • 6.8.3 组件之间传递数据
          • 6.8.3.1 父传子
          • 6.8.3.2 子传父
          • 6.8.3.3 兄弟传参
    • 七、Vue3路由机制router
      • 7.1 路由简介
      • 7.2 路由入门案例
      • 7.3 路由重定向
      • 7.4 编程式路由(useRouter)
      • 7.5 路由传参(useRoute)
      • 7.6 路由守卫
    • 八、 案例开发-日程管理-第五期
      • 8.1 重构前端工程
    • 九、Vue3数据交互axios
      • 9.0 预讲知识-promise
        • 9.0.1 普通函数和回调函数
        • 9.0.2 Promise 简介
        • 9.0.3 Promise 基本用法
        • 9.0.4 Promise catch()
        • 9.0.5 async和await的使用
      • 9.1 Axios介绍
      • 9.2 Axios 入门案例
      • 9.3 Axios get和post方法
      • 9.4 Axios 拦截器
    • 十、案例开发-日程管理-第六期
      • 10.1 前端代码处理
        • 10.1.1 创建src/utils/request.js文件
        • 10.1.2 注册页面完成注册
        • 10.1.3 登录页面完成登录
      • 10.2 后端代码处理
        • 10.2.1 添加跨域处理器
          • 10.2.1.1 什么是跨域
          • 10.2.1.2为什么会产生跨域
          • 10.2.1.3 如何解决跨域
        • 10.2.2 重构UserController
        • 10.2.3 删除登录校验过滤器
    • 十一、Vue3状态管理Pinia
      • 11.1 Pinia介绍
      • 11.2 Pinia基本用法
      • 11.3 Pinia其他细节
    • 十二、案例开发-日程管理-第七期
      • 12.1 前端使用pinia存储数据
      • 12.2 显示所有日程数据
      • 12.3 增加和保存日程数据
      • 12.5 删除日程数据
    • 十三、Element-plus组件库
      • 13.1 Element-plus介绍
      • 13.2 Element-plus入门案例
      • 13.3 Element-plus常用组件

六、Vue3视图渲染技术

6.1 模版语法

Vue 使用一种基于 HTML 的模板语法,使我们能够声明式地将其组件实例的数据绑定到呈现的 DOM 上。所有的 Vue 模板都是语法层面合法的 HTML,可以被符合规范的浏览器和 HTML 解析器解析。在底层机制中,Vue 会将模板编译成高度优化的 JavaScript 代码。结合响应式系统,当应用状态变更时,Vue 能够智能地推导出需要重新渲染的组件的最少数量,并应用最少的 DOM 操作。

6.1.1 插值表达式和文本渲染

插值表达式:最基本的数据绑定形式是文本插值,它使用的是“Mustache”语法 ,即双大括号{{}}

  • 插值表达式是将数据渲染到元素的指定位置的手段之一
  • 插值表达式不绝对依赖标签,其位置相对自由
  • 插值表达式中支持javascript的运算表达式
  • 插值表达式中也支持函数的调用
<script setup type="module">
  let msg ="hello vue3"
  let getMsg= ()=>{
    return 'hello vue3 message'
  }
  let age = 19
  let bee = '蜜 蜂'
  // 购物车
  const 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>
    getMsg返回的值为:{{ getMsg() }}  <br>
    是否成年: {{ age>=18?'true':'false' }} <br>
    反转: {{ bee.split(' ').reverse().join('-') }} <br>
    购物车总金额: {{ compute() }} <br/>
    购物车总金额: {{carts[0].price*carts[0].number + carts[1].price*carts[1].number}} <br>
  div>
template>

<style scoped>

style>

为了渲染双标中的文本,我们也可以选择使用v-textv-html命令

  • v-*** 这种写法的方式使用的是vue的命令
  • v-***的命令必须依赖元素,并且要写在元素的开始标签中
  • v-***指令支持ES6中的字符串模板
  • 插值表达式中支持javascript的运算表达式
  • 插值表达式中也支持函数的调用
  • v-text可以将数据渲染成双标签中间的文本,但是不识别html元素结构的文本
  • v-html可以将数据渲染成双标签中间的文本,识别html元素结构的文本
<script setup type="module">
  let msg ='hello vue3'
  let getMsg= ()=>{
    return msg
  }
  let age = 19
  let bee = '蜜 蜂'
  let redMsg ='msg'
  let greenMsg =`${msg}`
script>

<template>
  <div>
    <span v-text='msg'>span> <br>
    <span v-text='redMsg'>span> <br>
    <span v-text='getMsg()'>span> <br>
    <span v-text='age>18?"成年":"未成年"'>span> <br>
    <span v-text='bee.split(" ").reverse().join("-")'>span> <br>
    <span v-html='msg'>span> <br>
    <span v-html='redMsg'>span> <br>
    <span v-html='greenMsg'>span> <br>
    <span v-html="`${msg}`">span> <br>
  div>
template>

<style scoped>

style>
6.1.2 Attribute属性渲染

想要渲染一个元素的 attribute,应该使用 v-bind指令

  • 由于插值表达式不能直接放在标签的属性中,所有要渲染元素的属性就应该使用v-bind
  • v-bind可以用于渲染任何元素的属性,语法为 v-bind:属性名='数据名', 可以简写为 :属性名='数据名'
<script setup type="module">
  const data = {
    name:'尚硅谷',
    url:"http://www.atguigu.com",
    logo:"http://www.atguigu.com/images/index_new/logo.png"
  }
script>

<template>
  <div>
    <a 
      v-bind:href='data.url' 
      target="_self">
      <img 
        :src="data.logo" 
        :title="data.name">
      <br>
      <input type="button" 
             :value="`点击访问${data.name}`">
    a>
  div>
template>

<style scoped>
style>
6.1.3 事件的绑定

我们可以使用 v-on 来监听 DOM 事件,并在事件触发时执行对应的 Vue的JavaScript代码。

  • 用法:v-on:click="handler" 或简写为 @click="handler"
  • vue中的事件名=原生事件名去掉on 前缀 如:onClick --> click
  • handler的值可以是方法事件处理器,也可以是内联事件处理器
  • 绑定事件时,可以通过一些绑定的修饰符,常见的事件修饰符如下
    • .once:只触发一次事件。[重点]
    • .prevent:阻止默认事件。[重点]
    • .stop:阻止事件冒泡。
    • .capture:使用事件捕获模式而不是冒泡模式。
    • .self:只在事件发送者自身触发时才触发事件。
<script setup type="module">
  import {ref} from 'vue'
  // 响应式数据 当发生变化时,会自动更新 dom树
  let count=ref(0)
  let addCount= ()=>{
    count.value++
  }
  let incrCount= (event)=>{
    count.value++
    // 通过事件对象阻止组件的默认行为
    event.preventDefault();
    
  }
script>

<template>
  <div>
    <h1>count的值是:{{ count }}h1>
    
    <button v-on:click="addCount()">addCountbutton> <br>
    
    <button @click="count++">incrCountbutton> <br>
    
    <button @click.once="count++">addOncebutton> <br>
    
    <a href="http://www.atguigu.com" target="_blank" @click.prevent="count++">preventa> <br>
    
    <a href="http://www.atguigu.com" target="_blank" @click="incrCount($event)">preventa> <br>
  div>
template>

<style scoped>

style>

6.2 响应式基础

此处的响应式是指 : 数据模型发生变化时,自动更新DOM树内容,页面上显示的内容会进行同步变化,vue3的数据模型不是自动响应式的,需要我们做一些特殊的处理

6.2.1 响应式需求案例

需求:实现 + - 按钮,实现数字加一减一

<script type="module" setup>
    let counter = 0;
    function show(){
        alert(counter);
    }
script>

<template>
  <div>
    <button @click="counter--">-button> 
    {{ counter }} 
    <button @click="counter++">+button>
    <hr>
    
    <button @click="show()">显示counter值button>
   div>
template> 

<style scoped>

style>

6.2.2 响应式实现关键字ref

ref 可以将一个基本类型的数据(如字符串,数字等)转换为一个响应式对象。 ref 只能包裹单一元素

<script type="module" setup>
    /* 从vue中引入ref方法 */
    import {ref} from 'vue'
    let counter = ref(0);
    function show(){
        alert(counter.value);
    }
    /* 函数中要操作ref处理过的数据,需要通过.value形式 */
    let decr = () =>{
      counter.value--;
    }
    let incr = () =>{
      counter.value++;
    }
script>

<template>
  <div>
    <button @click="counter--">-button> 
    <button @click="decr()">-button> 
    {{ counter }} 
    <button @click="counter++">+button>
    <button @click="incr()">+button> 
    <hr>
    <button @click="show()">显示counter值button>
   div>
template> 

<style scoped>

style>
  • 在上面的例子中,我们使用 ref 包裹了一个数字,在代码中给这个数字加 1 后,视图也会跟着动态更新。需要注意的是,由于使用了 ref,因此需要在访问该对象时使用 .value 来获取其实际值。
6.2.3 响应式实现关键字reactive

我们可以使用 reactive() 函数创建一个响应式对象或数组:

<script type="module" setup>
    /* 从vue中引入reactive方法 */
    import {ref,reactive} from 'vue'
    let data = reactive({
      counter:0
    })
    function show(){
        alert(data.counter);
    }
    /* 函数中要操作reactive处理过的数据,需要通过 对象名.属性名的方式 */
    let decr = () =>{
      data.counter--;
    }
    let incr = () =>{
      data.counter++;
    }
script>

<template>
  <div>
    <button @click="data.counter--">-button> 
    <button @click="decr()">-button> 
    {{ data.counter }} 
    <button @click="data.counter++">+button>
    <button @click="incr()">+button> 
    <hr>
    <button @click="show()">显示counter值button>
   div>
template> 

<style scoped>

style>

对比ref和reactive:

  • 使用 ref 适用于以下开发场景:

    • 包装基本类型数据:ref 主要用于包装基本类型数据(如字符串、数字等),即只有一个值的数据,如果你想监听这个值的变化,用 ref 最为方便。在组件中使用时也很常见。
    • 访问方式简单:ref 对象在访问时与普通的基本类型值没有太大区别,只需要通过 .value 访问其实际值即可。
  • 使用 reactive 适用于以下开发场景:

    • 包装复杂对象:reactive 可以将一个普通对象转化为响应式对象,这样在数据变化时会自动更新界面,特别适用于处理复杂对象或者数据结构。
    • 需要递归监听的属性:使用 reactive 可以递归追踪所有响应式对象内部的变化,从而保证界面的自动更新。
  • 综上所述,ref 适用与简单情形下的数据双向绑定,对于只有一个字符等基本类型数据或自定义组件等情况,建议可以使用 ref;而对于对象、函数等较为复杂的数据结构,以及需要递归监听的属性变化,建议使用 reactive。当然,在实际项目中根据需求灵活选择也是十分必要的。

6.2.4 扩展响应式关键字toRefs 和 toRef

toRef基于reactive响应式对象上的一个属性,创建一个对应的 ref响应式数据。这样创建的 ref 与其源属性保持同步:改变源属性的值将更新 ref 的值,反之亦然。toRefs将一个响应式对象多个属性转换为一个多个ref数据,这个普通对象的每个属性都是指向源对象相应属性的 ref。每个单独的 ref 都是使用 toRef() 创建的。

案例:响应显示reactive对象属性

<script type="module" setup>
    /* 从vue中引入reactive方法 */
    import {ref,reactive,toRef,toRefs} from 'vue'
    let data = reactive({
      counter:0,
      name:"test"
    })

    // 将一个reactive响应式对象中的某个属性转换成一个ref响应式对象
    let ct =toRef(data,'counter');
    // 将一个reactive响应式对象中的多个属性转换成多个ref响应式对象
    let {counter,name} = toRefs(data)

    function show(){
        alert(data.counter);
        // 获取ref的响应对象,需要通过.value属性
        alert(counter.value);
        alert(name.value)
    }
    /* 函数中要操作ref处理过的数据,需要通过.value形式 */
    let decr = () =>{
      data.counter--;
    }
    let incr = () =>{
      /* ref响应式数据,要通过.value属性访问 */
      counter.value++;
    }
script>

<template>
  <div>
    <button @click="data.counter--">-button> 
    <button @click="decr()">-button> 
    {{ data.counter }} 
    &
    {{ ct }} 
    <button @click="data.counter++">+button>
    <button @click="incr()">+button> 
    <hr>
    <button @click="show()">显示counter值button>
   div>
template> 

<style scoped>

style>


6.3 条件和列表渲染

6.3.1 条件渲染

v-if 条件渲染

  • v-if='表达式' 只会在指令的表达式返回真值时才被渲染

  • 也可以使用 v-elsev-if 添加一个“else 区块”。

  • 一个 v-else 元素必须跟在一个 v-if 元素后面,否则它将不会被识别。

<script type="module" setup>
    import {ref} from 'vue'
    let awesome = ref(true)
script>

<template>
  <div>
    <h1 v-if="awesome">Vue is awesome!h1>
    <h1 v-else>Oh no h1>
    <button @click="awesome = !awesome">Togglebutton>
  div>
template> 

<style scoped>
style>

v-show条件渲染扩展:

  • 另一个可以用来按条件显示一个元素的指令是 v-show。其用法基本一样:

  • 不同之处在于 v-show 会在 DOM 渲染中保留该元素;v-show 仅切换了该元素上名为 display 的 CSS 属性。

  • v-show 不支持在