Vue.js魔法书:前端开发者的终极指南----指令篇续篇

news2025/2/24 6:05:34

​个人名片:
😊作者简介:一个为了让更多人看见许舒雅的宝贝的小白先生
🤡个人主页:🔗 许舒雅的宝贝
🐼座右铭:深夜两点半的夜灯依旧闪烁,凌晨四点的闹钟不止你一个。
🎅学习目标: 坚持前端的学习进度,做一个全栈开发工程师

上篇文章没有写完的内容,在此进行补充。

目录

🌟 1.指令修饰符

👉 1.1按键修饰符

👉 1.2v-model修饰符

 👉 1.3补充

🌟 2.v-bind对样式控制的增强-操作class

👉 2.1数组语法

👉 2.2对象语法

 ✍🏻 小案例:京东秒杀-tab栏切换导航高亮

🌟 3.v-bind对样式控制的增强---操作style

👉 3.1语法

👉 3.2代码练习

✍🏻 小案例:进度条案例

🌟 4.v-model在其他表单元素的使用

🌟 5.computed计算属性

👉 5.1概念

👉 5.2语法

👉 5.3注意

👉 5.4案例

🌟 6.computed计算属性和methods方法的区别

👉 6.1computed计算属性

👉 6.2methods计算属性

👉 6.3计算属性的优势

👉 6.4总结

🌟 7.计算属性的完整写法

✍🏻 综合案例:成绩单

🌟 8.watch侦听器

👉 8.1作用

👉 8.2语法

🎉 8.2.1简单写法案例1

🎉 8.2.2简单写法案例2

🎉 8.2.3完整写法案例1(deep的使用)

 🎉 8.2.4完整写法案例2(immediate的使用)

👉 8.3总结

✍🏻 综合案例:购物车案例


🌟 1.指令修饰符

在Vue中,指令修饰符是用来改变指令行为的特殊后缀,通过在指令名称后添加一个点(.)来使用。用来帮助开发者简化判断代码。

👉 1.1按键修饰符

①@keyup.enter:键盘回车监听

②@keyup.tab:触发当用户按下tab键

③@keyup.delete或@keyup.esc:触发当用户按下Delete键(捕获“删除”键和Esc键)

等等,还有.space,up,down,left,right等等修饰符,最常用的已经给大家标注出来啦。


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="./css/style.css" />
    <title>记事本</title>
</head>
<body>

<!-- 主体区域 -->
<section id="app">
    <!-- 输入框 -->
    <header class="header">
        <h1>小黑记事本</h1>
        <input @keyup.enter="addTask()" v-model="message" placeholder="请输入任务" class="new-todo" />
        <button class="add" @click="addTask()">添加任务</button>
    </header>
    <!-- 列表区域 -->
    <section class="main">
        <ul class="todo-list">
            <li class="todo" v-for="(item,index) in taskList" :key="item.id">
                <div class="view">
                    <span class="index">{{ index + 1 }}.</span> <label>{{ item.msg }}</label>
                    <button class="destroy" @click="del(item.id)"></button>
                </div>
            </li>
        </ul>
    </section>
    <!-- 统计和清空   如果没有任务了,底部隐藏掉-->
    <footer class="footer" v-show="taskList.length > 0">
        <!-- 统计 -->
        <span class="todo-count">合 计:<strong> {{ taskList.length }} </strong></span>
        <!-- 清空 -->
        <button class="clear-completed" @click="reset()">
            清空任务
        </button>
    </footer>
</section>


<!-- 底部 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>

    const app = new Vue({
        el: '#app',
        data: {
            message: '',
            taskList: [
                {id: 1, msg: '吃饭'},
                {id: 2, msg: '跑步'},
                {id: 3, msg: '睡觉'},
            ]
        },
        methods: {
            del(id){
                this.taskList = this.taskList.filter(item => item.id !== id)
            },
            reset(){
                this.taskList = []
            },
            addTask() {
                // trim()函数去除字符串左右两边的空格,不去除字符串中的空格
                if(this.message.trim() === ''){
                    alert('请输入任务内容')
                    return
                }
                this.taskList.unshift({
                    id: +new Date(),
                    msg: this.message
                })
                this.message = ''
            }
        },
    })

</script>
</body>
</html>

用法就以keyup.enter作为案例来演示一下,这个很好理解,就是在某个地方我们使用了按键修饰符,那么当我们在这个地方使用键盘的按键之后,就会触发绑定的事件,就这么简单。

ok,我们现在思考一下怎么实现的?

当我们按下enter的时候,我们是不是可以拿到这个事件对象,事件对象中是不是有一个key,根据这个key来判断是否去触发事件不就行了。

我们可以在触发方法中加一行代码:console.log(e),方法参数传值e,上篇文章我们说了的,方法可以直接获取事件对象e。在页面F12查看控制台,触发事件观察事件对象的key。

👉 1.2v-model修饰符

①v-model.lazy:默认情况下,v-model在input事件中同步输入框的值与数据,使用.lazy修饰后,v-model则会变成在change事件中同步。

②v-model.number:当用户输入值时,.number修饰符确保输入值被转换为数值类型,如果输入值无法转换为数值,则为字符串。

③v-model.trim:使用.trim修饰符,会自动过滤用户输入的首尾空白字符。这里的.trim和和函数.trim()是不一样的,不要弄混了,虽然功能一样。

🚨 注意:这些修饰符都必须要和v-model结合使用,以满足不同的数据绑定需求。

 👉 1.3补充

①@事件名.stop:阻止冒泡,冒泡的意思就是说比如父div包裹了一个子div,父子都有自己的触发事件,当我们点击子div的事件的时候,会出现冒泡到了父div。

②事件名.prevent:阻止默认行为,比如我们有a标签,这个是跳转链接的标签,当我们在这个标签上使用,就无法跳转到该链接。
🚨 注意:@事件名.stop.prevent —>可以连用 即阻止事件冒泡也阻止默认行为

<style>
    .father {
      width: 200px;
      height: 200px;
      background-color: pink;
      margin-top: 20px;
    }
    .son {
      width: 100px;
      height: 100px;
      background-color: skyblue;
    }
  </style>

 <div id="app">
    <h3>v-model修饰符 .trim .number</h3>
    姓名:<input v-model="username" type="text"><br>
    年纪:<input v-model="age" type="text"><br>

    
    <h3>@事件名.stop     →  阻止冒泡</h3>
    <div @click="fatherFn" class="father">
      <div @click="sonFn" class="son">儿子</div>
    </div>

    <h3>@事件名.prevent  →  阻止默认行为</h3>
    <a @click href="http://www.baidu.com">阻止默认行为</a>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        username: '',
        age: '',
      },
      methods: {
        fatherFn () {
          alert('老父亲被点击了')
        },
        sonFn (e) {
          // e.stopPropagation()
          alert('儿子被点击了')
        }
      }
    })
  </script>

🌟 2.v-bind对样式控制的增强-操作class

为了方便开发者进行样式控制, Vue 扩展了 v-bind 的语法,可以针对 class 类名 和 style 行内样式进行控制 。

👉 2.1数组语法

<div> :class = "对象/数组">这是一个div</div>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="./css/style.css" />
    <title>demo</title>
</head>
<style>
    .box {
        width: 200px;
        height: 200px;
        background-color: #fff;
        border: 1px solid #000;
    }
    .pink {
        background-color: pink;
    }
    .big {
        width: 500px;
        height: 500px;
    }
</style>
<body>
    <div id="app">
<!--        <div class="box" :class="{pink: true}">小白先生</div>-->
        <div class="box" :class="['pink']">小白先生</div>
    </div>
<!-- 底部 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>

    const app = new Vue({
        el: '#app',
        data: {
        }
    })

</script>
</body>
</html>

 测试结果

适用场景:批量添加或删除类

👉 2.2对象语法

当class动态绑定的是对象时,就是类名,值就是布尔值,如果值是true,就有这个类,否则没有这个类

<div class="box" :class="{ 类名1: 布尔值, 类名2: 布尔值 }"></div>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="./css/style.css" />
    <title>demo</title>
</head>
<style>
    .box {
        width: 200px;
        height: 200px;
        background-color: #fff;
        border: 1px solid #000;
    }
    .pink {
        background-color: pink;
    }
    .big {
        width: 500px;
        height: 500px;
    }
</style>
<body>
    <div id="app">
<!--        <div class="box" :class="{pink: true}">小白先生</div>-->
        <div class="box" :class="{pink: true,big: true}">小白先生</div>
    </div>
<!-- 底部 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>

    const app = new Vue({
        el: '#app',
        data: {
        }
    })

</script>
</body>
</html>

测试结果

 适用场景:一个类名,来回切换

 ✍🏻 小案例:京东秒杀-tab栏切换导航高亮

需求:当我们点击哪个导航栏时,哪个导航栏高亮。


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="./css/style.css" />
    <title>demo</title>
</head>
<style>
    * {
        margin: 0;
        padding: 0;
    }
    ul {
        display: flex;
        border-bottom: 2px solid #e01222;
        padding: 0 10px;
    }
    li {
        width: 100px;
        height: 50px;
        line-height: 50px;
        list-style: none;
        text-align: center;
    }
    li a {
        display: block;
        text-decoration: none;
        font-weight: bold;
        color: #333333;
    }
    li a.active {
        background-color: #e01222;
        color: #fff;
    }

</style>
<body>
<div id="app">
    <ul>
        <li v-for="(item,index) in list" :key="item.id">
            <a :class="{active:index===activeIndex}" @click="activeIndex = index " href="#">{{item.name}}</a>
        </li>
    </ul>
</div>
<!-- 底部 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>

    const app = new Vue({
        el: '#app',
        data: {
            activeIndex: 0,
            list: [
                { id: 1, name: '京东秒杀' },
                { id: 2, name: '每日特价' },
                { id: 3, name: '品类秒杀' }
            ]
        }
    })

</script>
</body>
</html>

测试结果: 

思路很简单:

①根据数据适用v-for动态渲染数据

②准备一个下标,记录高亮的是哪一个

③基于下标动态切换class的类名 

🌟 3.v-bind对样式控制的增强---操作style

👉 3.1语法

<div class="box" :style="{ CSS属性名1: CSS属性值, CSS属性名2: CSS属性值 }"></div>

👉 3.2代码练习


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="./css/style.css" />
    <title>demo2</title>
</head>
<style>

    .box {
        width: 200px;
        height: 200px;
        background-color: rgb(187, 150, 156);
    }
</style>
<body>
<div id="app">
    <div class="box" :style="{width: '400px'}"></div>
</div>
<!-- 底部 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {

        }
    })

</script>
</body>
</html>

测试结果: 

✍🏻 小案例:进度条案例

点击下面的百分比的按钮,即可生成相应的进度条。


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="./css/style.css" />
    <title>demo2</title>
</head>
<style>
    .progress {
        height: 25px;
        width: 400px;
        border-radius: 15px;
        background-color: #272425;
        border: 3px solid #272425;
        box-sizing: border-box;
        margin-bottom: 30px;
    }
    .inner {
        width: 50%;
        height: 20px;
        border-radius: 10px;
        text-align: right;
        position: relative;
        background-color: #409eff;
        background-size: 20px 20px;
        box-sizing: border-box;
        transition: all 1s;
    }
    .inner span {
        position: absolute;
        right: -20px;
        bottom: -25px;
    }
</style>
<body>
<div id="app">
    <div class="progress">
        <div class="inner" :style="{width:progress+'%'}">
            <span>{{progress}}%</span>
        </div>
    </div>
    <button @click="changeProgress(25)">设置25%</button>
    <button @click="changeProgress(50)">设置50%</button>
    <button @click="changeProgress(75)">设置75%</button>
    <button @click="changeProgress(100)">设置100%</button>
</div>
<!-- 底部 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            progress:25
        },
        methods: {
            changeProgress(num){
                this.progress = num
            }
        }
    })

</script>
</body>
</html>

测试结果:

🌟 4.v-model在其他表单元素的使用

常见的表单元素都可以用v-model绑定关联-->快速获取或设置表单元素的值,它会根据控件类型自动选取正确的方法来更新元素。

输入框  input:text   ——> value
文本域  textarea	 ——> value
复选框  input:checkbox  ——> checked
单选框  input:radio   ——> checked
下拉菜单 select    ——> value
...
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="./css/style.css" />
    <title>demo</title>
</head>
<body>
<div id="app">
    <h3>个人信息主页</h3>

    姓名:
    <input type="text" v-model="username">
    <br><br>

    是否单身:
    <input type="checkbox" v-model="isSingle">
    <br><br>

    <!--
      前置理解:
        1. name:  给单选框加上 name 属性 可以分组 → 同一组互相会互斥
        2. value: 给单选框加上 value 属性,用于提交给后台的数据
           并且通常value用具体的标识,一般不会传字符串文本的,一般是男是1,女是2      结合 Vue 使用 → v-model
    -->
    性别:
    <input v-model="gender" type="radio" name="gender" value="1">男
    <input v-model="gender" type="radio" name="gender" value="2">女
    <br><br>

    <!--
      前置理解:
        1. option 需要设置 value 值,提交给后台
           option的value里面城市的编码一般是从后台获取的
        2. select 的 value 值,关联了选中的 option 的 value 值
      结合 Vue 使用 → v-model
    -->
    所在城市:
    <select v-model="cityId">
        <option value="101">北京</option>
        <option value="102">上海</option>
        <option value="103">成都</option>
        <option value="104">南京</option>
    </select>
    <br><br>

    <!-- 文本域和输入框是类似的 -->
    自我描述:
    <textarea v-model="desc"></textarea>

    <button>立即注册</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            username: '',
            isSingle: false,
            // 标识女选中
            gender: "2",
            cityId: '102',
            desc: ""
        }
    })
</script>
</body>

</html>

测试结果:

🌟 5.computed计算属性

👉 5.1概念

基于现有的数据,计算出新属性依赖的数据变化,自动重新计算。

👉 5.2语法

①声明在computed配置项中,一个计算属性对应一个函数

②使用起来和普通属性一样使用{{计算属性名}}

👉 5.3注意

①computed配置项和data配置项是同级

②computed中的计算属性虽然是函数的写法,但他依然是个属性

③computed中的计算属性不能和data中的属性同名

④使用computed中的计算属性和使用data中的属性是一样的用法

⑤computed中计算属性内部的this依然指向的是Vue实例

👉 5.4案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="./css/style.css" />
    <title>demo</title>
</head>

<style>
    table {
        border: 1px solid #000;
        text-align: center;
        width: 240px;
    }
    th,td {
        border: 1px solid #000;
    }
    h3 {
        position: relative;
    }
</style>
<body>
<div id="app">
    <h3>小黑的礼物清单</h3>
    <table>
        <tr>
            <th>名字</th>
            <th>数量</th>
        </tr>
        <tr v-for="(item, index) in list" :key="item.id">
            <td>{{ item.name }}</td>
            <td>{{ item.num }}个</td>
        </tr>
    </table>

    <!-- 目标:统计求和,求得礼物总数 -->
    <p>礼物总数:{{total}} 个</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            // 现有的数据
            list: [
                { id: 1, name: '篮球', num: 1 },
                { id: 2, name: '玩具', num: 2 },
                { id: 3, name: '铅笔', num: 5 },
            ]
        },
        computed: {
            total(){
                let sum = 0;
                this.list.forEach(item => {
                    sum += item.num;
                });
                return sum;
            }
        }
    })
</script>
</body>

</html>

 测试结果:

🌟 6.computed计算属性和methods方法的区别

👉 6.1computed计算属性

作用:封装了一段对于数据的处理,求得一个结果

语法:

①写在computed配置项中

②作为属性,直接使用

        Ⅰjs中使用计算属性:this.计算属性

        Ⅱ模板中使用计算属性:{{计算属性}}

👉 6.2methods计算属性

作用:给Vue实例提供一个方法,调用以处理业务逻辑

语法:

①写在methods配置项中

②作为方法调用

        Ⅰjs中调用:this.方法名()

        Ⅱ模板中调用{{方法名()}}或者@事件名="方法名"

👉 6.3计算属性的优势

①缓存特性(提升性能):计算属性会对计算出来的结果缓存,在此使用时直接读取缓存,依赖项变化了,会自动重新计算,并再次缓存。

②methods没有缓存特性

👉 6.4总结

①computed有缓存特性,methods没有缓存   ②当一个结果依赖其他多个值时,推荐使用计算属性

③当处理业务逻辑时,推荐使用methods方法,比如事件的处理函数

🌟 7.计算属性的完整写法

计算属性也是属性,能访问,应该也是可以修改的

计算属性默认的简写,只能读取访问,不能“修改”,如果需要修改,需要写计算属性的完整写法。


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="./css/style.css" />
    <title>demo</title>
</head>

<body>
<div id="app">
    姓:<input type="text" v-model="firstName"> +
    名:<input type="text" v-model="lastName"> =
    <span>{{totalName}}</span><br><br>
    <button @click="changeName">改名卡</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            firstName: '刘',
            lastName: '备'
        },
        computed: {
            totalName:{
                // (1) 当fullName计算属性,被获取求值时,执行get(有缓存,优先读缓存)
                //     会将返回值作为,求值的结果
                get(){
                    return this.firstName + this.lastName
                },
                // (2) 当fullName计算属性,被修改赋值时,执行set
                //     修改的值,传递给set方法的形参
                set(value){
                    this.firstName = value.slice(0,1)
                    this.lastName = value.slice(1)
                },

            }
        },
        methods: {
            changeName(){
                this.totalName = '吕小布'
            }
        }
    })
</script>
</body>

</html>

computed的完整写法一般不常用,一般只作为计算,最终展示在页面上,不做修改操作,因为可以看出来,修改的操作还挺麻烦的。

✍🏻 综合案例:成绩单

功能描述:

1.渲染功能  2.删除功能  3.添加功能  4.统计总分,求平均分

思路分析:

1.渲染功能 v-for :key v-bind:动态绑定class的样式

2.删除功能 v-on绑定事件, 阻止a标签的默认行为

3.v-model的修饰符 .trim、 .number、 判断数据是否为空后 再添加、添加后清空文本框的数据

4.使用计算属性computed 计算总分和平均分的值

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="./css/index.css" />
    <title>Document</title>
</head>
<body>
<div id="app" class="score-case">
    <div class="table">
        <table>
            <thead>
            <tr>
                <th>编号</th>
                <th>科目</th>
                <th>成绩</th>
                <th>操作</th>
            </tr>
            </thead>
            <tbody>
            <tr v-for="(item,index) in list" :key="item.id">
                <td>{{index+1}}</td>
                <td>{{ item.subject }}</td>
                <td :class="{red:item.score<60}">{{ item.score }}</td>
                <td><a @click.prevent="deleteData(item.id)" href="#">删除</a></td>
            </tr>
            </tbody>
            <tbody v-if="list.length<=0">
            <tr>
                <td colspan="5">
                    <span class="none">暂无数据</span>
                </td>
            </tr>
            </tbody>

            <tfoot>
            <tr>
                <td colspan="5">
                    <span>总分:{{ totalScope }}</span>
                    <span style="margin-left: 50px">平均分:{{ average }}</span>
                </td>
            </tr>
            </tfoot>
        </table>
    </div>
    <div class="form">
        <div class="form-item">
            <div class="label">科目:</div>
            <div class="input">
                <input
                        type="text"
                        placeholder="请输入科目"
                        v-model.trim="subject"
                />
            </div>
        </div>
        <div class="form-item">
            <div class="label">分数:</div>
            <div class="input">
                <input
                        type="text"
                        placeholder="请输入分数"
                        v-model.trim.number="score"
                />
            </div>
        </div>
        <div class="form-item">
            <div class="label"></div>
            <div class="input">
                <button class="submit" @click="addData()">添加</button>
            </div>
        </div>
    </div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            list: [
                { id: 1, subject: '语文', score: 20 },
                { id: 7, subject: '数学', score: 99 },
                { id: 12, subject: '英语', score: 70 },
            ],
            subject: '',
            score: ''
        },
        methods: {
            deleteData(id){
                this.list = this.list.filter(item => item.id !== id)
            },
            addData(){
                if(!this.subject || !this.score){
                    alert('请输入数据!输入框不可为空!')
                    return
                }
                //unshift将元素把到数组的最前面,后面的元素一次往后移一位
                this.list.unshift(
                    {
                        id: +new Date(),
                        subject: this.subject,
                        score: this.score
                    }
                )
                this.subject = ''
                this.score = ''
            }
        },
        computed: {
            totalScope(){
                return this.list.reduce((prev,item) => prev + Number(item.score),0)
            },
            average(){
                return this.list.reduce((prev,item) => prev + Number(item.score),0) / this.list.length
            }
        }
    })
</script>
</body>
</html>

样式文件css:

.score-case {
    width: 1000px;
    margin: 50px auto;
    display: flex;
}
.score-case .table {
    flex: 4;
}
.score-case .table table {
    width: 100%;
    border-spacing: 0;
    border-top: 1px solid #ccc;
    border-left: 1px solid #ccc;
}
.score-case .table table th {
    background: #f5f5f5;
}
.score-case .table table tr:hover td {
    background: #f5f5f5;
}
.score-case .table table td,
.score-case .table table th {
    border-bottom: 1px solid #ccc;
    border-right: 1px solid #ccc;
    text-align: center;
    padding: 10px;
}
.score-case .table table td.red,
.score-case .table table th.red {
    color: red;
}
.score-case .table .none {
    height: 100px;
    line-height: 100px;
    color: #999;
}
.score-case .form {
    flex: 1;
    padding: 20px;
}
.score-case .form .form-item {
    display: flex;
    margin-bottom: 20px;
    align-items: center;
}
.score-case .form .form-item .label {
    width: 60px;
    text-align: right;
    font-size: 14px;
}
.score-case .form .form-item .input {
    flex: 1;
}
.score-case .form .form-item input,
.score-case .form .form-item select {
    appearance: none;
    outline: none;
    border: 1px solid #ccc;
    width: 200px;
    height: 40px;
    box-sizing: border-box;
    padding: 10px;
    color: #666;
}
.score-case .form .form-item input::placeholder {
    color: #666;
}
.score-case .form .form-item .cancel,
.score-case .form .form-item .submit {
    appearance: none;
    outline: none;
    border: 1px solid #ccc;
    border-radius: 4px;
    padding: 4px 10px;
    margin-right: 10px;
    font-size: 12px;
    background: #ccc;
}
.score-case .form .form-item .submit {
    border-color: #069;
    background: #069;
    color: #fff;
}

测试结果:

 这个代码可能不是最简单的和简短的,我只是为了练习之前学的一些内容,所以我是按照我的学习进度写的代码,大家可能有更好的解决方案的。

🌟 8.watch侦听器

👉 8.1作用

监视数据变化,执行一些业务逻辑或异步操作。

👉 8.2语法

①watch声明在data同级的配置项中

②简单写法:简单类型数据直接监视

③完整写法:添加额外的配置项

<script>
    const app = new Vue({
      el: "#app",
      data: {
        project: "语文",
        obj: {
          name: "张三",
        },
      },
      watch: {
        //该方法会在数据变化,触发执行
        数据属性名(newValue, oldValue) {
          一些业务逻辑或异步操作;
        },
        "对象.属性名"(newValue, oldValue) {
          一些业务逻辑或异步操作;
        },
      },
    });
  </script>

🎉 8.2.1简单写法案例1

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
</head>
<body>
<div id="app">
    <textarea name="" v-model="project"></textarea>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
    new Vue({
        el: "#app",
        data: {
            project: "语文",
        },
        watch: {
            //该方法会在数据变化,触发执行
            //newValue新值,oldValue老值(一般不用)
            project(newValue, oldValue) {
                console.log("变化前的值:", newValue, "变化后的值:", oldValue);
            },
        },
    });
</script>
</html>

测试结果:

🎉 8.2.2简单写法案例2

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
</head>
<body>
<div id="app">
    <textarea name="" v-model="obj.project"></textarea>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
    new Vue({
        el: "#app",
        data: {
            obj: {
                project: "语文"
            }
        },
        watch: {
            //该方法会在数据变化,触发执行
            //newValue新值,oldValue老值(一般不用)
            "obj.project"(newValue, oldValue) {
                console.log("变化前的值:", newValue, "变化后的值:", oldValue);
            },
        },
    });
</script>
</html>

测试结果:

🎉 8.2.3完整写法案例1(deep的使用)

1.deep:true对复杂类型深度监视(监视对象中的所有属性)

2.immediate:true 初始化立刻执行一次handler方法

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
</head>
<body>
<div id="app">
    <select v-model="obj.country">
        <option value="italy">意大利</option>
        <option value="english">英语</option>
        <option value="german">德语</option>
    </select>
    <textarea name="" v-model="obj.project"></textarea>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
    const app = new Vue({
        el: "#app",
        data: {
            obj: {
                project: "语文",
                country: "english",
            },
        },
        watch: {
            //完整写法不是一个方法,是一个对象
            obj: {
                deep: true,
                handler(newValue) {
                    console.log("对象被改变了", newValue);
                },
            },
        },
    });
</script>
</html>

测试结果:

 🎉 8.2.4完整写法案例2(immediate的使用)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
</head>
<body>
<div id="app">
    <select v-model="obj.country">
        <option value="italy">意大利</option>
        <option value="english">英语</option>
        <option value="german">德语</option>
    </select>
    <textarea name="" v-model="obj.project"></textarea>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
    const app = new Vue({
        el: "#app",
        data: {
            obj: {
                project: "语文",
                country: "english",
            },
        },
        watch: {
            //完整写法不是一个方法,是一个对象
            obj: {
                deep: true,
                immediate: true,
                handler(newValue) {
                    console.log("对象被改变了", newValue);
                },
            },
        },
    });
</script>
</html>

测试结果: 

👉 8.3总结

watch侦听器的写法有几种?

简单写法

watch: {
  数据属性名 (newValue, oldValue) {
    一些业务逻辑 或 异步操作。 
  },
  '对象.属性名' (newValue, oldValue) {
    一些业务逻辑 或 异步操作。 
  }
}

完整写法

watch: {// watch 完整写法
  数据属性名: {
    deep: true, // 深度监视(针对复杂类型)
    immediate: true, // 是否立刻执行一次handler
    handler (newValue) {
      console.log(newValue)
    }
  }
}

✍🏻 综合案例:购物车案例

需求说明:

  1. 渲染功能

  2. 删除功能

  3. 修改个数

  4. 全选反选

  5. 统计 选中的 总价 和 总数量

  6. 持久化到本地

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="./css/inputnumber.css" />
    <link rel="stylesheet" href="./css/index.css" />
    <title>购物车</title>
</head>

<body>
<div class="app-container" id="app">
    <!-- 顶部banner -->
    <div class="banner-box"><img src="./img/fruit.jpg" alt="" /></div>
    <!-- 面包屑 -->
    <div class="breadcrumb">
        <span>🏠</span>
        /
        <span>购物车</span>
    </div>
    <!-- 购物车主体 -->
    <div v-if="fruitList.length > 0" class="main">
        <div class="table">
            <!-- 头部 -->
            <div class="thead">
                <div class="tr">
                    <div class="th">选中</div>
                    <div class="th th-pic">图片</div>
                    <div class="th">单价</div>
                    <div class="th num-th">个数</div>
                    <div class="th">小计</div>
                    <div class="th">操作</div>
                </div>
            </div>
            <!-- 身体 -->
            <div class="tbody">
                <div v-for="(item,index) in fruitList" :key="item.id" class="tr" :class="{active: item.isChecked}">
                    <div class="td"><input type="checkbox" v-model="item.isChecked" /></div>
                    <div class="td"><img :src="item.icon" alt="" /></div>
                    <div class="td">{{ item.price }}</div>
                    <div class="td">
                        <div class="my-input-number">
                            <button :disabled="item.num < 1 " @click="sub(item.id)" class="decrease"> - </button>
                            <span class="my-input__inner">{{ item.num }}</span>
                            <button @click="add(item.id)" class="increase"> + </button>
                        </div>
                    </div>
                    <div class="td">{{ item.num*item.price}}</div>
                    <div class="td"><button @click="del(item.id)">删除</button></div>
                </div>
            </div>
        </div>
        <!-- 底部 -->
        <div class="bottom">
            <!-- 全选 -->
            <label class="check-all">
                <input v-model="isAll" type="checkbox" />
                全选
            </label>
            <div class="right-box">
                <!-- 所有商品总价 -->
                <span class="price-box">总价&nbsp;&nbsp;:&nbsp;&nbsp;¥&nbsp;<span class="price">{{totalPrice}}</span></span>
                <!-- 结算按钮 -->
                <button class="pay">结算( {{ totalCount }} )</button>
            </div>
        </div>
    </div>
    <!-- 空车 -->
    <div v-else class="empty">🛒空空如也</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
    const defaultArr = [{
        id: 1,
        icon: './img/火龙果.png',
        isChecked: true,
        num: 2,
        price: 6,
    },
        {
            id: 2,
            icon: './img/荔枝.png',
            isChecked: false,
            num: 7,
            price: 20,
        },
        {
            id: 3,
            icon: './img/榴莲.png',
            isChecked: false,
            num: 3,
            price: 40,
        },
        {
            id: 4,
            icon: './img/鸭梨.png',
            isChecked: true,
            num: 10,
            price: 3,
        },
        {
            id: 5,
            icon: './img/樱桃.png',
            isChecked: false,
            num: 20,
            price: 34,
        },
    ]
    const app = new Vue({
        el: '#app',
        data: {
            // 水果列表
            fruitList: JSON.parse(localStorage.getItem('list')) || defaultArr,
        },
        computed: {
            isAll: {
                //获取计算属性
                get() {
                    return this.fruitList.every(item => item.isChecked === true);
                },
                //设置计算属性并下发给小选项
                //当你直接对复选框进行修改时,即修改计算属性,那么修改的值会传入到set的形参当中
                set(value) {
                    this.fruitList.forEach(item => item.isChecked = value);
                }
            },
            //统计水果总价
            totalPrice() {
                return this.fruitList.reduce((sum, item) => {
                    if (item.isChecked) {
                        sum = sum + item.num*item.price;
                        return sum;
                    } else {
                        return sum;
                    }
                }, 0)
            },
            //统计水果总数量
            totalCount() {
                return this.fruitList.reduce((sum, item) => {
                    if (item.isChecked) {
                        sum = sum + item.num;
                        return sum;
                    } else {
                        return sum;
                    }
                }, 0)
            }
        },
        methods: {
            //删除某一行水果
            del: function (id) {
                this.fruitList = this.fruitList.filter(item => item.id != id)
            },
            //将某一行的水果的数量增加
            add: function (id) {
                //1.找到对应id的水果
                const fruit = this.fruitList.find(item => item.id === id);
                //2.添加水果个数
                fruit.num++
            },
            //减少水果数量
            sub: function (id) {
                //1.找到对应id的水果
                const fruit = this.fruitList.find(item => item.id === id);
                //2.减少水果个数
                fruit.num--
            }
        },
        watch:{
            fruitList:{
                deep:true,
                handler(newValue){
                    //将变化后的newValue存入本地
                    localStorage.setItem('list',JSON.stringify(newValue))
                }
            }
        }
    })
</script>
</body>

</html>

css文件:

.app-container {
  padding-bottom: 300px;
  width: 800px;
  margin: 0 auto;
}
@media screen and (max-width: 800px) {
  .app-container {
    width: 600px;
  }
}
.app-container .banner-box {
  border-radius: 20px;
  overflow: hidden;
  margin-bottom: 10px;
}
.app-container .banner-box img {
  width: 100%;
}
.app-container .nav-box {
  background: #ddedec;
  height: 60px;
  border-radius: 10px;
  padding-left: 20px;
  display: flex;
  align-items: center;
}
.app-container .nav-box .my-nav {
  display: inline-block;
  background: #5fca71;
  border-radius: 5px;
  width: 90px;
  height: 35px;
  color: white;
  text-align: center;
  line-height: 35px;
  margin-right: 10px;
}

.breadcrumb {
  font-size: 16px;
  color: gray;
}
.table {
  width: 100%;
  text-align: left;
  border-radius: 2px 2px 0 0;
  border-collapse: separate;
  border-spacing: 0;
}
.th {
  color: rgba(0, 0, 0, 0.85);
  font-weight: 500;
  text-align: left;
  background: #fafafa;
  border-bottom: 1px solid #f0f0f0;
  transition: background 0.3s ease;
}
.th.num-th {
  flex: 1.5;
}
.th {
  text-align: center;
}
.th:nth-child(4),
.th:nth-child(5),
.th:nth-child(6),
.th:nth-child(7) {
  text-align: center;
}
.th.th-pic {
  flex: 1.3;
}
.th:nth-child(6) {
  flex: 1.3;
}

.th,
.td {
  position: relative;
  padding: 16px 16px;
  overflow-wrap: break-word;
  flex: 1;
}
.pick-td {
  font-size: 14px;
}
.main,
.empty {
  border: 1px solid #f0f0f0;
  margin-top: 10px;
}
.tr {
  display: flex;
  cursor: pointer;
  border-bottom: 1px solid #ebeef5;
}
.tr.active {
  background-color: #f5f7fa;
}
.td {
  display: flex;
  justify-content: center;
  align-items: center;
}

.table img {
  width: 100px;
  height: 100px;
}

button {
  outline: 0;
  box-shadow: none;
  color: #fff;
  background: #d9363e;
  border-color: #d9363e;
  color: #fff;
  background: #d9363e;
  border-color: #d9363e;
  line-height: 1.5715;
  position: relative;
  display: inline-block;
  font-weight: 400;
  white-space: nowrap;
  text-align: center;
  background-image: none;
  border: 1px solid transparent;
  box-shadow: 0 2px 0 rgb(0 0 0 / 2%);
  cursor: pointer;
  transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  touch-action: manipulation;
  height: 32px;
  padding: 4px 15px;
  font-size: 14px;
  border-radius: 2px;
}
button.pay {
  background-color: #3f85ed;
  margin-left: 20px;
}

.bottom {
  height: 60px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-right: 20px;
  border: 1px solid #f0f0f0;
  border-top: none;
  padding-left: 20px;
}
.right-box {
  display: flex;
  align-items: center;
}
.check-all {
  cursor: pointer;
}
.price {
  color: hotpink;
  font-size: 30px;
  font-weight: 700;
}
.price-box {
  display: flex;
  align-items: center;
}
.empty {
  padding: 20px;
  text-align: center;
  font-size: 30px;
  color: #909399;
}
.my-input-number {
  display: flex;
}
.my-input-number button {
  height: 40px;
  color: #333;
  border: 1px solid #dcdfe6;
  background-color: #f5f7fa;
}
.my-input-number button:disabled {
  cursor: not-allowed!important;
}
.my-input-number .my-input__inner {
  height: 40px;
  width: 50px;
  padding: 0;
  border: none;
  border-top: 1px solid #dcdfe6;
  border-bottom: 1px solid #dcdfe6;
}
.my-input-number {
  position: relative;
  display: inline-block;
  width: 140px;
  line-height: 38px;
}
.my-input-number span {
  -moz-user-select: none;
  -webkit-user-select: none;
  -ms-user-select: none;
}
.my-input-number .my-input {
  display: block;
  position: relative;
  font-size: 14px;
  width: 100%;
}
.my-input-number .my-input__inner {
  -webkit-appearance: none;
  background-color: #fff;
  background-image: none;
  border-radius: 4px;
  border: 1px solid #dcdfe6;
  box-sizing: border-box;
  color: #606266;
  display: inline-block;
  font-size: inherit;
  height: 40px;
  line-height: 40px;
  outline: none;
  padding: 0 15px;
  transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
  width: 100%;
  padding-left: 50px;
  padding-right: 50px;
  text-align: center;
}
.my-input-number .my-input-number__decrease,
.my-input-number .my-input-number__increase {
  position: absolute;
  z-index: 1;
  top: 1px;
  width: 40px;
  height: auto;
  text-align: center;
  background: #f5f7fa;
  color: #606266;
  cursor: pointer;
  font-size: 13px;
}
.my-input-number .my-input-number__decrease {
  left: 1px;
  border-radius: 4px 0 0 4px;
  border-right: 1px solid #dcdfe6;
}
.my-input-number .my-input-number__increase {
  right: 1px;
  border-radius: 0 4px 4px 0;
  border-left: 1px solid #dcdfe6;
}
.my-input-number .my-input-number__decrease.is-disabled,
.my-input-number .my-input-number__increase.is-disabled {
  color: #c0c4cc;
  cursor: not-allowed;
}

实现思路:

1.基本渲染: v-for遍历、:class动态绑定样式

2.删除功能 : v-on 绑定事件,获取当前行的id

3.修改个数 : v-on绑定事件,获取当前行的id,进行筛选出对应的项然后增加或减少

4.全选反选

  1. 必须所有的小选框都选中,全选按钮才选中 → every

  2. 如果全选按钮选中,则所有小选框都选中

  3. 如果全选取消,则所有小选框都取消选中

声明计算属性,判断数组中的每一个checked属性的值,看是否需要全部选

5.统计 选中的 总价 和 总数量 :通过计算属性来计算选中的总价和总数量

6.持久化到本地: 在数据变化时都要更新下本地存储 watch。

测试结果:

这篇文章就到这里了,下次见!

🥇原创不易,还希望各位大佬支持一下!

👍点赞,你的认可是我创作的动力 !

🌟收藏,你的青睐是我努力的方向!

✏️评论,你的意见是我进步的财富!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2146947.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

linux 操作系统下的dhclient命令介绍和案例使用

linux 操作系统下的dhclient命令介绍和案例使用 dhclient 是 Linux 系统中用于动态主机配置协议&#xff08;DHCP&#xff09;客户端的命令。它的主要功能是从 DHCP 服务器获取网络配置&#xff0c;包括 IP 地址、子网掩码、默认网关和 DNS 服务器等信息 dhclient 命令概述 …

如何使用ssm实现校园二手交易平台的设计与开发+vue

TOC ssm641校园二手交易平台的设计与开发vue 研究背景与现状 时代的进步使人们的生活实现了部分自动化&#xff0c;由最初的全手动办公已转向手动自动相结合的方式。比如各种办公系统、智能电子电器的出现&#xff0c;都为人们生活的享受提供帮助。采用新型的自动化方式可以…

速通汇编(六)认识栈,SS、SP寄存器,push和pop指令的作用

一&#xff0c;栈 &#xff08;一&#xff09;栈的特点 栈是一种具有特殊访问方式的存储空间&#xff0c;特殊在于&#xff0c;进出这块存储空间的数据&#xff0c;“先进后出&#xff0c;后进先出” 由于栈的这个“先进后出”的特点&#xff0c;我们可以利用其来很好的操作内…

传输层协议 —— TCP协议(上篇)

目录 1.认识TCP 2.TCP协议段格式 3.可靠性保证的机制 确认应答机制 超时重传机制 连接管理机制 三次握手 四次挥手 1.认识TCP 在网络通信模型中&#xff0c;传输层有两个经典的协议&#xff0c;分别是UDP协议和TCP协议。其中TCP协议全称为传输控制协议&#xff08;Tra…

Java毕业设计 基于SpringBoot和Vue自习室管理系统

Java毕业设计 基于SpringBoot和Vue自习室管理系统 这篇博文将介绍一个基于SpringBoot框架和Vue开发的自习室管理系统&#xff0c;适合用于Java毕业设计。 功能介绍 学生 登录 个人中心 修改密码 系统首页 自习室浏览 学生预约记录 管理员  登录 个人中心 修改密码 系统…

零信任安全架构--持续验证

随着网络安全威胁的不断演变&#xff0c;传统的“信任但验证”安全模式已无法应对现代复杂的攻击。零信任安全架构&#xff08;Zero Trust Architecture, ZTA&#xff09;应运而生&#xff0c;作为一种全新的安全理念&#xff0c;它彻底改变了企业的网络安全防护方式。核心思想…

file的判断和获取,创建和删除

常见成员方法 1.length 返回文件的大小(字节数量) 细节1:这个方法只能获取文件的大小&#xff0c;单位是字节如果单位我们要是M&#xff0c;G&#xff0c;可以不断的除以1024 细节2:这个方法无法获取文件夹的大小如果我们要获取一个文件夹的大小&#xff0c;需要把这个文件夹…

项目管理系统的期限提醒功能如何确保项目按时推进?

在竞争激烈的项目申报垂直领域&#xff0c;时间就是效率&#xff0c;效率关乎成败。每一个申报项目的截止日期都是一道不容错过的关卡&#xff0c;错过即意味着失去了宝贵的机会。为了确保项目能够按时推进&#xff0c;避免因时间管理不当而导致的延误&#xff0c;项目管理系统…

SpringCloud系列之一---搭建高可用的Eureka注册中心

前言 本篇文章主要介绍的是SpringCloud相关知识、微服务架构以及搭建服务注册与发现的服务模块(Eureka)以及Eureka集群。 GitHub源码链接位于文章底部。 什么是SpringCloud Spring Cloud 是一系列框架的有序集合。 它利用 Spring Boot 的开发便利性巧妙地简化了分布式系统基础设…

如何使用ssm实现基于web的物流配送管理系统的设计与实现+vue

TOC ssm646基于web的物流配送管理系统的设计与实现vue 第一章 绪论 1.1研究背景与意义 在科学技术水平还比较低下的时期&#xff0c;企业通常采用人工登记的方式对相关的物流配送信息进行记录&#xff0c;而后对这些信息记录进行管理和控制。这种采用纸质存储信息的管理模式…

平安养老险广东分公司:防范非法集资,守护消费者“钱袋子”

随着经济的不断发展&#xff0c;非法集资犯罪案件频频发生。非法集资案件受害人多&#xff0c;涉及资金广&#xff0c;犯罪手段多元化&#xff0c;涉案财物追缴困难等等。为提升金融消费者风险防范意识&#xff0c;保障其合法经济利益&#xff0c;今天我们一起来学习防范非法集…

利用条件编译解决vivado下verilog代码中ila与仿真的共存问题

vivado自带的仿真工具已经接近Modelsim的功能&#xff0c;且与原生开发环境的紧密结合&#xff0c;对仿真非常方便。 我的习惯是在实现工程中另外建一个仿真工程&#xff0c;保存仿真的testbench文件等&#xff0c;而实现工程中保存实际功能的源码文件。 这样仿真时会存在一个问…

PyQGIS开发 1 环境配置

PyQGIS 开发环境配置 1 安装QGIS QGIS官方下载地址 Windows环境下载对应版本的msi文件双击进行安装。 2 安装 PyCharm PyCharm官方下载地址 PyCharm官方提供专业版&#xff08;收费&#xff09;和社区版&#xff08;免费&#xff09;两个版本&#xff0c;自行选择下载、安…

Oracle EBS form个性化中调用带参数的存储过程或者函数

方式1 通过活动-消息 调用 这个方式的特点是会有一个消息弹框&#xff0c;不需要弹框时可以用方式2 方式2 通过 内置-执行过程 这个地方【变元】中的引用有点复杂&#xff0c;其中参数要用如下格式进行 #三个单引号||项目的表达式 ||${item.BLOCKNAME.FIELDNAME.value}|| #如…

从入门到精通,玩转Python的print函数(探索Python print函数的隐藏功能)

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 文章内容 📒📝 基础用法参数详解示例📝 高级用法自定义分隔符和结束符输出到文件追加模式📝 覆盖打印与进度条简单覆盖打印动态进度条示例代码⚓️ 相关链接 ⚓️📖 介绍 📖 刚开始学习编程时,我们接触到的第一个方…

运行npm install 时,卡在sill idealTree buildDeps没有反应

一直停留在sill idealTree buildDeps 解决方法 npm config set registry https://registry.npm.taobao.org 配置后用下面命令看是否配置成功 npm config get registry 如果配置还不好使 就执行下行的ssl npm set strict-ssl false 然后执行 npm install 成功执行

线程池的类型和状态

一、线程池的类型 1.通过Executors工具类创建的线程池对象 Executors.newFixedThreadPool(nThreads)&#xff1a;固定线程数目的线程池&#xff1b; 核心线程数和最大线程数一致&#xff1b;只要非核心线程空闲&#xff0c;则立刻被回收&#xff1b;工作队列为无界队列。 Exe…

基于yolov8的DMS驾驶员抽烟打电话喝水吃东西检测系统python源码+onnx模型+评估指标曲线+精美GUI界面

【算法介绍】 基于YOLOv8的DMS&#xff08;驾驶员监控系统&#xff09;驾驶员抽烟、打电话、喝水、吃东西检测系统是一种利用先进计算机视觉技术的实时监测系统。该系统通过YOLOv8算法&#xff0c;一种在速度和准确性上均表现优异的实时目标检测算法&#xff0c;实现对驾驶员行…

Spring Controller

服务器控制 响应架构 Spring Boot 内集成了 Tomcat 服务器&#xff0c;也可以外接 Tomcat 服务器。通过控制层接收浏览器的 URL 请求进行操作并返回数据。 底层和浏览器的信息交互仍旧由 servlet 完成&#xff0c;服务器整体架构如下&#xff1a; Server&#xff1a; Tomcat…

达梦数据库配置SSL通信加密

相关概念&#xff1a; SSL通过在发送方和接收方之间建立加密通道&#xff0c;确保数据在传输过程中的安全性和完整性。 SSL的关键特点 加密通信&#xff1a;SSL使用对称和非对称加密技术来加密数据&#xff0c;确保数据在传输过程中不被窃听或篡改。 身份验证&#xff1a;通…