Bootstrap

前端框架Vue3——响应式数据,v-on,v-show和v-if,v-for,v-bind

        Vue的定义为渐进式的JavaScript框架。所谓渐进式,是指其被设计 为可以自底向上逐层应用。我们可以只使用Vue框架中提供的某层的功 能,也可以与其他第三方库整合使用。当然,Vue本身也提供了完整的 工具链,使用其全套功能进行项目的构建也非常简单。Vue的渐进式性质使其使用方式变得非常灵活,在使用时,我们可以使用其完整的框架,也可以只使用部分功能。

一、响应式数据

        响应式是Vue 框架重要的特点,在开发中,对 Vue 响应式特性的使 用非常频繁,常见的是通过数据绑定的方式将变量的值渲染到页面中,当变量发生变化时,页面对应的元素也会更新。
 1.ref方法

   ref是Vue3中用于创建响应式数据的方法之一。它主要用于创建基本数据类型(如NumberStringBoolean等)的响应式数据。ref接受一个内部值作为参数,并返回一个带有.value属性的响应式对象。

例如:

<!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">
        <p>{{ msg }}</p>
    </div>

    <script type="module">
        import {createApp, ref} from "./vue.esm-browser.js"  //模块化开发方式
        createApp({
            setup(){
                let msg = ref;
                
                // 返回一个对象类型的数据
                return { msg: "成功创建第一个Vue应用程序!" ,   
                         
                 }
            }
        }
        ).mount("#app");

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

效果如下(运行需安装live-server插件):

2.reactive方法

    reactive用于创建复杂的响应式数据对象,如对象或数组。它将一个普通的 JavaScript 对象转换为响应式对象。被reactive包裹的对象,其所有的属性都将变成响应式的。

例如:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>让数据变成响应式</title>
</head>

<body>
    <div id="app">
        <p>{{ web.url }}</p>
        <button @click="change">点击我更换网址</button>
    </div>

    <script type="module">
        import {createApp, reactive} from "./vue.esm-browser.js"  //模块化开发方式
        createApp({
            setup(){
 

                const web = reactive({
                    title: "百度一下,你就知道",
                    url: "www.baidu.com"
                });
                console.log(typeof web, web);

                const change = () => {
                    web.url += "-->数据被修改";
                }
                // 返回一个对象类型的数据
                return {  
                         web,
                         change
                 }
            }
        }
        ).mount("#app");

    </script>



</body>
</html>

效果如下(运行需安装live-server插件):

                  点击按钮前                                                             点击按钮后

二、事件绑定指令v-on

   v-on是 Vue.js 中用于绑定事件的指令。它可以将 DOM 事件(如clickkeydownsubmit等)绑定到组件实例的方法上。

enter space tab 按键修饰符

keyup是在用户松开按键时才触发

keydown是在用户按下按键时立即触发

这使得在用户与页面进行交互(如点击按钮、输入文字等)时,能够触发相应的 JavaScript 代码来处理业务逻辑。

<!-- v-on:click 表示在 button 元素上监听 click 事件 -->
<button v-on:click="edit">修改</button> <br>
    
<!-- @click 简写形式 -->
<button @click="add(20, 30)">加法</button> <br>

可以通过@keyup.+键盘内的某个键设置点击该按键或者组合键触发函数,代码如下:

回车 <input type="text" @keyup.enter="add(40, 60)"> <br>
空格 <input type="text" @keyup.space="add(20, 30)"> <br>
Tab <input type="text" @keydown.tab="add(10, 20)"> <br>
w <input type="text" @keyup.w="add(5, 10)"> <br>

<!-- 组合快捷键 -->
Ctrl + Enter <input type="text" @keyup.ctrl.enter="add(40, 60)"> <br>
Ctrl + A <input type="text" @keyup.ctrl.a="add(20, 30)">

效果如下:

                 未按键版                                              按键版

以下是一个v-on指令事件绑定的例子:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>绑定事件</title>
</head>

<body>
    <div id="app">
        <h3>{{ msg }}</h3>
        <h3>{{ web.url }}</h3>
        <h3>{{ web.user }}</h3>
        <h3>{{ sub(100, 20) }}</h3>
    
        <!-- v-on:click 表示在 button 元素上监听 click 事件 -->
        <button v-on:click="edit">修改</button> <br>
    
        <!-- @click 简写形式 -->
        <button @click="add(20, 30)">加法</button> <br>

    
    </div>

    <script type="module">
        import { createApp, reactive, ref } from './vue.esm-browser.js'
        
        createApp({
            setup() {

                let msg = "成功启动!!!";

                const web = reactive({
                    title: "百度",
                    url: "baidu.com",
                    user: 0
                });
    
                const edit = () => {
                    web.url = "www.baidu.com"
                    msg = "云中医" //错误示例 不能直接改变msg的值,因为msg是一个普通变量, 不是响应式数据
                    console.log(`msg修改为: ${msg}`); //从控制台打印信息可以知道确实改变了,但是模板没有响应更新(非响应式数据)    
                }
    
                const add = (a, b) => {
                    web.user += a + b
                }
    
                const sub = (a, b) => {
                    return a - b
                }
    
                return {
                    msg, //普通变量, 非响应式数据, 在模板中普通变量不会自动更新
                    web, //响应式数据
                    edit, //方法
                    add,
                    sub,
                }
            }
        }).mount("#app")
    
    </script>



</body>
</html>

效果如下:

             未点击版                                                         点击版

三、条件渲染指令v-show和v-if

   v-show是 Vue.js 中的一个指令,用于根据表达式的值来控制元素的显示和隐藏。当表达式的值为true时,元素会显示;当表达式的值为false时,元素会隐藏。它通过修改元素display CSS 属性来实现显示和隐藏的效果。

例如:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>节点的条件渲染</title>
</head>

<body>
    <div id="app">
        <h3>显示状态: {{ web.show }}</h3>
        <!-- Vue处理v-show变化时,是用display:none实现隐藏的(可以通过F12检查源代码,当点击时,源码会加入display:none) -->
        <p v-show="web.show">广东云浮中医药职业学院计算机学院v-show</p>   
    </div>

    <script type="module">
        import { createApp, reactive, ref } from './vue.esm-browser.js'
        
        createApp({
        setup() {
                const web = reactive({   // 响应式数据
                    show: true,
                    user: 500
                });


                return {
                    web,
                }
            }
        }).mount("#app");
    
    </script>



</body>
</html>

效果如下:

①当表达式的值为true时,元素正常显示:

②当表达式的值为false时,元素被隐藏:

   v-if也是用于条件渲染的指令。它根据表达式的值来决定是否渲染元素。如果表达式的值为true,元素会被渲染到 DOM 中;如果表达式的值为false,元素不会被渲染。

同样是上面的例子,以v-if来实现:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>节点的条件渲染</title>
</head>

<body>
    <div id="app">
        <h3>显示状态: {{ web.show }}</h3>
        <!-- Vue处理v-if变化时,是通过删除节点实现隐藏的(可以通过F12检查源代码,当点击时,源码会删除节点) 。
         当遇到需要频繁显示和隐藏的场景时,不是合使用v-if, 因为频繁增删节点,会导致渲染效率下降 -->
        <p v-if="web.show">广东云浮中医药职业学院基础学院v-if</p>
        <button @click="toggle">切换显示状态</button>
    </div>

    <script type="module">
        import { createApp, reactive, ref } from './vue.esm-browser.js'
        
        createApp({
        setup() {
                const web = reactive({   // 响应式数据
                    show: true,
                    user: 500
                });

                const toggle = () => {
                    web.show = !web.show;   // 这个布尔变量被切换后,模板中用到的地方会自动更新,进而被v-show捕获
                }

                return {
                    web,
                    toggle,
                }
            }
        }).mount("#app");
    
    </script>


</body>
</html>

效果如下:

四、遍历指令v-for

   v-for是 Vue.js 中用于遍历数组或对象并渲染列表的指令。它可以根据数据源(如数组、对象、数字范围等)的内容来动态地生成多个相同结构的 DOM 元素。

1.遍历一个对象的数值:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>遍历指令</title>

    <style>
        .textColor{
            color: red;
        }
    </style>
</head>

<body>

    <div id="app">
        <!-- 遍历对象的值 -->
        <h4>遍历对象的值。</h4>
        <ul>
            <li v-for="value in data.user">
                {{ value }}
            </li>
        </ul>
    </div>

    <script type="module">
        import { createApp, reactive } from './vue.esm-browser.js'
        createApp({
        setup() {
                const data = reactive({                    
                    //对象
                    user: { name: "李雷",   gender: "女" }
                });

                return {
                    data
                }
            }
        }).mount("#app")
    </script>



</body>
</html>

效果如下:

2.遍历对象的值和索引 (注意:写指令时,先值后索引)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>遍历指令</title>

    <style>
        .textColor{
            color: red;
        }
    </style>
</head>

<body>

    <div id="app">
        <!-- 遍历对象的值和索引。 注意:写指令时,先值后索引 -->
        <h4>遍历对象的值和索引。 注意:写指令时,先值后索引</h4>
        <ul>
            <li v-for="(value, index) in data.number">
                {{ index }} : {{ value }}
            </li>
        </ul>    
    </div>

    <script type="module">
        import { createApp, reactive } from './vue.esm-browser.js'
        createApp({
        setup() {
                const data = reactive({
                    //数组
                    number: ["十",  "十一",  "十二"],                     
                });

                return {
                    data
                }
            }
        }).mount("#app")
    </script>

</body>
</html>

效果如下:

3.遍历对象的值和键( 注意:写指令时,先值后键):
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>遍历指令</title>

    <style>
        .textColor{
            color: red;
        }
    </style>
</head>

<body>

    <div id="app">
        <!-- 遍历对象的值和键。 注意:写指令时,先值后键 -->
        <h4>遍历对象的值和键。 注意:写指令时,先值后键</h4>
        <ul>
            <li v-for="(value, key) in data.user">
                {{ key }} : {{ value }}
            </li>
        </ul>    
    </div>

    <script type="module">
        import { createApp, reactive } from './vue.esm-browser.js'
        createApp({
        setup() {
                const data = reactive({
                    //对象
                    user: { name: "李雷",   gender: "女" }                     
                });

                return {
                    data
                }
            }
        }).mount("#app")
    </script>

</body>
</html>

效果如下:

4.遍历对象的值,键和索引。 注意:写指令时,先值再键后索引:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>遍历指令</title>

    <style>
        .textColor{
            color: red;
        }
    </style>
</head>

<body>

    <div id="app">
        <!-- 遍历对象的值,键和索引。 注意:写指令时,先值再键后索引 -->
        <h4>遍历对象的值,键和索引。 注意:写指令时,先值再键后索引</h4>
        <ul>
            <li v-for="(value, key, index) in data.user">
                {{ index }} : {{ key }} : {{ value }}
            </li>
        </ul>    
    </div>

    <script type="module">
        import { createApp, reactive } from './vue.esm-browser.js'
        createApp({
        setup() {
                const data = reactive({
                    //对象
                    user: { name: "李雷",   gender: "女" }                     
                });

                return {
                    data
                }
            }
        }).mount("#app")
    </script>

</body>
</html>

效果如下:

5.指令嵌套: 先用v-for指令遍历对象,然后展示符合v-if条件的节点:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>遍历指令</title>

    <style>
        .textColor{
            color: red;
        }
    </style>
</head>

<body>

    <div id="app">
        <h4>指令嵌套: 先用v-for指令遍历对象,然后展示符合v-if条件的节点</h4>
        <ul>
            <!--注: <template> 标签可以用来包装多个元素或者多行代码, 不会在页面中渲染  -->
            
            <template v-for="(value, key, index) in data.user">
                <li v-if="index == 1">  
                    {{ index }} : {{ key }} : {{ value }}
                </li>           
            </template>
        </ul>    
    </div>

    <script type="module">
        import { createApp, reactive } from './vue.esm-browser.js'
        createApp({
        setup() {
                const data = reactive({
                    //对象
                    user: { name: "李雷",   gender: "女" }                     
                });

                return {
                    data
                }
            }
        }).mount("#app")
    </script>

</body>
</html>

效果如下:

五、属性动态化指令v-bind

  v-bind是 Vue.js 中的一个指令,用于动态地绑定一个或多个属性到元素上。它允许你根据组件的数据来改变元素的属性值,比如srchrefclassstyle等属性。通过v-bind,可以实现数据驱动的属性变化,使得视图能够随着数据的改变而自动更新相关属性。

语法为v-bind:属性名="表达式",不过在实际开发中,更常用的是缩写形式:属性名="表达式"

1.iuput标签动态属性绑定
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>节点的动态属性(单向绑定)</title>

    <style>
        .textColor{
            color: red;
        }
    </style>
</head>

<body>
    <div id="app">

        <h3>  iuput标签动态属性绑定    v-bind:value </h3>
        <input type="text" v-bind:value="web.str">
    
        <h3>  iuput标签动态属性绑定(简写形式)   :str </h3>
        <input type="text" :value="web.str">

        <br>
        <button @click="change">修改</button>
    </div>

    <script type="module">
        import { createApp, reactive } from './vue.esm-browser.js'
    
        createApp({
            setup() {
                const web = reactive({
                    str: "w",
                })

                const change = () => {
                    web.str += "w";
                }
    
                return {
                    web,
                    change
                }
            }
        }).mount("#app")
    </script>

</body>
</html>

效果如下:

               未点击修改键                                                点击修改键(根据点击次数叠加)

2.img标签动态属性绑定
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>节点的动态属性(单向绑定)</title>

    <style>
        .textColor{
            color: red;
        }
    </style>
</head>

<body>
    <div id="app">    
        <h3>  img标签动态属性绑定(简写形式)    :src </h3>
        <img :src="web.img">

        <br>
        <button @click="change">修改</button>
    </div>

    <script type="module">
        import { createApp, reactive } from './vue.esm-browser.js'
    
        createApp({
            setup() {
                const web = reactive({
                    img: "./img_src/logo0.png",
                })

                const change = () => {
                    web.img=`./img_src/logo1.png`;
                }
    
                return {
                    web,
                    change
                }
            }
        }).mount("#app")
    </script>



</body>
</html>

效果如下:

3.b标签动态属性绑定
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>节点的动态属性(单向绑定)</title>

    <style>
        .textColor{
            color: red;
        }
    </style>
</head>

<body>
    <div id="app">
        <h3>  b标签动态属性绑定(简写形式)   :class</h3>
        <h4>  注:通过布尔值控制某个类名是否存在,进而控制对应的CSS样式是否被选中生效</h4>
        <b :class="{textColor:web.fontStatus}">广东云浮中医药职业学院</b>

        <br>
        <button @click="change">修改</button>
    </div>




    <script type="module">
        import { createApp, reactive } from './vue.esm-browser.js'
    
        createApp({
            setup() {
                const web = reactive({
                    fontStatus: false
                })

                const change = () => {
                    web.fontStatus = !web.fontStatus;
                }
    
                return {
                    web,
                    change
                }
            }
        }).mount("#app")
    </script>



</body>
</html>

效果如下:

;