Vue2基础语法

Vue2基础语法

【一】插值语法

  • 语法:{{ 变量、js语法、三目表达式 }}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>插值语法</title>
<!--    此处我下在了本地-->
    <script src="./js/vue/vue.js"></script>
<!--    也可以使用cdn链接-->
<!--    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.7.14/vue.min.js"></script>-->

</head>
<body>
<div id="app">
    <ul>
        <li>字符串:{{name}}</li>
        <li>数值:{{age}}</li>
        <li>数组:{{list1}}</li>
        <li>对象:{{obj1}}</li>
        <li>html标签字符串:{{link1}} <small>依旧以字符串形式显示</small></li>
        <li>运算:{{10 + 20 + 30 + 40}}</li>
        <li>三目运算符:{{10 > 20 ? '是' : '否'}}</li>
    </ul>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            name: 'User', // 字符串
            age: 18, // 数值
            list1: [1,2,3,4],   // 数组
            obj1: {name: 'User', age: 18}, // 对象
            link1: '<a href="https://www.baidu.com">百度一下 你就知道</a>'
        },
        methods: {},
        computed: {}
    })
</script>
</html>

image-20240427203129973

【补】响应式

  • 深入响应式原理 — Vue.js (vuejs.org)

  • 在 Vue 中,当你把一个普通的 JavaScript 对象传递给 Vue 实例作为数据对象时,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter,这样 Vue 就能追踪数据的变化。

  • 当数据发生变化时,所有依赖于该数据的地方都会自动更新,这包括 DOM 中绑定了该数据的元素。这种自动的响应式更新使得开发者无需手动操作 DOM,只需关注数据的变化即可。

  • 值得注意的是,Vue 在初始化实例时会递归地将所有的属性转为 getter/setter,这使得 Vue 能够在数据被访问时添加依赖,从而在数据变化时通知更新。这也意味着,当你添加新属性时,它不会触发视图更新,因此需要提前声明所有的根级响应式属性。

简单来讲,当你修改Vue中的数据时,Dom上对应的元素将会改变

Vue响应式

【二】指令

【1】 文本指令

指令 释义
v-html 让HTML渲染成页面
v-text 标签内容显示js变量对应的值
v-show 放1个布尔值:为真 标签就显示;为假 标签就不显示
v-if 放1个布尔值:为真 标签就显示;为假 标签就不显示

v-showv-if区别

  • v-show:标签还在,只是不显示了(display: none
  • v-if:直接操作DOM,删除/插入 标签
<body>
<div id="app">
    <h2>文本指令</h2>
    <ul>
        <li v-text="name"></li>
        <li v-text="age"></li>
        <li v-text="list1"></li>
        <li v-text="obj1"></li>
        <li v-html="link1"></li>
        <li v-show="1">show显示标签</li>
        <li v-show="0">show隐藏标签</li>
        <li v-if="1">if显示标签</li>
        <li v-if="0">show删除标签</li>
    </ul>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            name: 'User', // 字符串
            age: 18, // 数值
            list1: [1,2,3,4],   // 数组
            obj1: {name: 'User', age: 18}, // 对象
            link1: '<a href="https://www.baidu.com">百度一下 你就知道</a>'
        },
        methods: {},
        computed: {}
    })
</script>
</html>

image-20240427205922608

通过修改li标签属性展示v-show=false的标签

Vue-v-show与v-if

【2】事件指令

指令 释义
v-on 触发事件
@ 触发事件
@[event] 触发event事件(可以是其他任意事件

例如:v-on:click可以缩写成@click

【2.1】常见的事件指令

  • 常见的事件类型有 clickinputchangemouseoverkeydown
<body>
<div id="app">
    <h2>事件指令</h2>
    <p>{{eventS}}</p>
    <ul>
        <li>
            <button v-on:click="handleClick">点击事件</button>
        </li>
        <li><input type="text" @input="handleInput">input事件:输入的内容【{{stringI}}】</li>
        <li><input type="text" @change="handleChange">change事件:修改的内容【{{stringC}}】</li>
        <li><span @mouseover="handleOver" @mouseout="handleOut">悬浮事件</span></li>
        <li>
            <button @keydown="handleKD" @keyup="handleKO">键盘事件</button>
            按下的键【{{keycode}}】
        </li>
    </ul>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            eventS: '事件名称',
            stringI: '',
            stringC: '',
            keycode:''
        },
        methods: {
            handleClick(event) {
                this.eventS = '点击事件';
            },
            handleInput(event) {
                this.eventS = 'input事件';
                this.stringI = event.data;
                console.log(event)
            },
            handleChange(event) {
                this.eventS = 'change事件'
                this.stringC = event.target.value
                console.log(event)
            },
            handleOver(event) {
                this.eventS = 'mouseover事件'
                console.log(event)
            },
            handleOut(event) {
                this.eventS = 'mouseout事件'
                console.log(event)
            },
            handleKD(event) {
                this.eventS = 'mousekeydown事件'
                this.keycode=event.key
                console.log(event)
            },
            handleKO(event) {
                this.eventS = 'mousekeyon事件'
                console.log(event)
            }
        },
        computed: {}
    })
</script>

Vue-事件指令

【2.2】input标签的事件处理

# input	当输入框进行输入的时候 触发的事件
# change	当元素的值发生改变时 触发的事件
# blur	当输入框失去焦点的时候 触发的事件
# focus   当获得焦点的时候 触发的事件
<body>
<div id="app">
    <h1>input事件</h1>
    <input type="text" v-model="name1" @input="handleInput">-->{{name1}}
    <h1>change事件</h1>
    <input type="text" v-model="name2" @change="handleChange">-->{{name2}}
    <h1>blur事件</h1>
    <input type="text" v-model="name3" @blur="handleBlur">-->{{name3}}
    <h1>focus事件</h1>
    <input type="text" v-model="name4" @focus="handleFocus">-->{{name4}}
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            name1: '',
            name2: '',
            name3: '',
            name4: '提示信息',
        },
        methods: {
            handleInput(event) {
                console.log('输入的值:',event.data)
            },
            handleChange() {
                console.log('handleChange:只有离开输入框,且内容发生变化才会触发,如果内容不变也不触发')
            },
            handleBlur() {
                console.log('handleBlur:失去焦点触发')
            },
            handleFocus() {
                console.log('Focus:获得焦点触发,可以执行清空输入框')
                this.name4 = ''
            }
        },
        computed: {}
    })
</script>

Vue-input事件

【补】数据双向绑定v-model

# 1 针对 input 标签--》页面中输入值--》js中有对应变量
# 2 数据单向绑定:变量变,页面变 --》页面变,变量不会变
# 3 数据双向绑定:相互影响
<body>
<div id="app">
    <h1>数据单向绑定</h1>
    <input type="text" :value="name1">-----------> 通过插值语法查看值{{name1}}
    <h1>数据双向绑定</h1>
    <input type="text" v-model="name2">----------->{{name2}}
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            name1: '',
            name2: ''
        },
        methods: {},
        computed: {}
    })
</script>

Vue-数据双向绑定

【2.3】事件修饰符

  • 在事件处理程序中调用 event.preventDefault()event.stopPropagation() 是非常常见的需求。尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。
  • 为了解决这个问题,Vue.js 为 v-on 提供了事件修饰符。之前提过,修饰符是由点开头的指令后缀来表示的。
    • .stop:阻止事件冒泡,即不再向上层元素派发事件。
    • .prevent:阻止事件的默认行为,例如阻止表单提交或者超链接跳转。
    • .capture:事件捕获模式,即事件将在捕获阶段触发,而不是在冒泡阶段触发。
    • .self:只有当事件是由元素自身触发时才触发事件处理函数,而不是子元素触发的。
    • .once:事件只会触发一次,即事件处理函数只会执行一次,之后便移除监听。
    • .passive:告诉浏览器不要阻止事件的默认行为,可以用来提升移动端的滚动性能。

使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent 只会阻止对元素自身的点击。

Vue-事件冒泡

事件冒泡:当一个事件发生在DOM元素上时,它会从最具体的元素(文档中嵌套层次最深的那个节点)开始向上逐级触发,直到触发到最顶层的文档对象(document对象)为止

【2.3.1】self和stop
<style>
    .div1 {
        width: 300px;
        height: 300px;
    }

    .father {
        background-color: #0d6efd;
    }

    .son {
        background-color: #20c997;
    }
</style>
<body>
<div id="app">
    <div @click.self="handleFunc" class="div1 father">
        <h2>@click.self 阻止父标签的冒泡事件</h2>
        <p>当为事件指定self修饰符时,该事件只有当前标签触发</p>
        <div @click.stop="handleFunc2" class="div1 son">
            <h3>@click.stop 阻止子标签的冒泡事件</h3>
            <p>当为事件指定stop修饰符时,该事件不会向上层元素派发事件,也就是不会触发click</p>
        </div>
    </div>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {},
        methods: {
            handleFunc() {
                alert('父标签的点击事件')
            },
            handleFunc2() {
                alert('子标签的点击事件')
            }
        },
        computed: {}
    })
</script>

Vue-事件修饰器self和stop

【2.3.2】once
<body>
<div id="app">
    <div>
        <p>{{count}}</p>
        <p><button @click="handleCount">点击数字加1</button></p>
        <p><button @click.once="handleCount">点击数字加1【仅触发一次】</button></p>
    </div>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            count: 0
        },
        methods: {
            handleCount() {
                this.count += 1
            }
        },
        computed: {}
    })
</script>

Vue-事件修饰器once

【2.4】键盘事件的按键修饰符

<body>
<div id="app">
    <h1>按键事件</h1>
    <input type="text" v-model="keyname" @keyup="handleKeyUp">-->{{keyname}}
    <hr>
    <h2>按键修饰符</h2>
    <input type="text" v-model="keyname2" @keyup.ctrl="handleKeyCtrl">-->{{keyname2}}
    <br>
    <h3>使用keycode对应码表</h3>
    <input type="text" @keyup.65="handleKey13">
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            keyname: '',
            keyname2: '',
        },
        methods: {
            handleKeyUp(event) {
                console.log(event)
                console.log('按下', event.key)
                this.keyname = event.key
            },
            handleKeyCtrl() {
                alert('按下了【ctrl】')
            },
            handleKey13() {
                alert('按下了【A】')
            }
        },
        computed: {}
    })
</script>

Vue-按键修饰符

【2.4】案例:过滤筛选

<body>
<div id="app">
    <h1>过滤案例</h1>
    <input type="text" v-model="myText" @input="handleInput">
    <hr>
    <ul>
        <li v-for="item in newdataList">{{item}}</li>
    </ul>

</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            myText: '',
            dataList: ['a', 'at', 'atom', 'be', 'beyond', 'cs', 'csrf', 'atome', 'atomem'],
            newdataList: ['a', 'at', 'atom', 'be', 'beyond', 'cs', 'csrf', 'atome', 'atomem'],
        },
        methods: {
            handleInput(event) {
                console.log(event)
                this.newdataList = this.dataList.filter((item) => item.indexOf(this.myText) >= 0)
                //  this.dataList.filter((item) => 布尔值 : 数组过滤 array.filter(function(){return 布尔值})
                // item.indexOf(this.myText) >= 0 : 如果不存在indexof返回【-1】
            },
        },
        computed: {}
    })
</script>

Vue-过滤案例

【3】属性指令

  • 为标签动态属性
指令 释义
v-bind 直接写js的变量或语法
: 直接写js的变量或语法

例如:v-bind:class='js变量'可以缩写成::class='js变量'

【3.1】属性

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>属性指令</title>
    <script src="../js/vue/vue.js"></script>
</head>
<body>
<div id="app">
    <div>
        <!--    所有的属性都可以用v-bind或【:】-->
        <div v-bind:id="idDiv"></div>
        <img :src="imgUrl" :alt="">
        <a :href="imgUrl">跳转</a>
    </div>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            imgUrl: 'https://pic.netbian.com/uploads/allimg/240105/002731-17043856512195.jpg',
            idDiv: '1'
        },
        methods: {},
        computed: {}
    })
</script>
</html>

【3.2】style属性和class属性

  • 都是可以使用三种形式来进行属性的指定
    • 字符串
    • 数组:对于class属性,数组是最适合的
    • 对象:对于style属性,对象是最适合的
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>属性指令</title>
    <script src="../js/vue/vue.js"></script>
</head>
<style>
    .div1 {
        height: 300px;
        width: 300px;
        background-color: #0a53be;
    }

    .div2 {
        height: 300px;
        width: 300px;
        background-color: #0a53be;
    }

    .div3 {
        height: 300px;
        width: 300px;
        background-color: #0a53be;
    }
</style>
<body>
<div id="app">
    <h2>style属性三种方式</h2>
    <div style="display: flex;justify-content: space-around">
        <div v-bind:style="styleStr">
            <p>style属性:str</p>
        </div>
        <div :style="styleList">
            <p>style属性:list</p>
        </div>
        <div :style="styleObj">
            <p>style属性:obj</p>
        </div>
    </div>
    <hr>
    <h2>class属性的三种方式</h2>
    <div style="display: flex;justify-content: space-around">
        <div :class="classStr">
            <p>class属性:str</p>
        </div>
        <div :class="classList">
            <p>class属性:list</p>
        </div>
        <div :class="classObj">
            <p>class属性:obj</p>
        </div>
    </div>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            // 字符串形式
            styleStr: 'width: 300px;height: 300px;background-color: #c5e8ef',
            // 数组形式 : [{},{},{}]
            styleList: [{width: '300px'}, {height: '300px'}, {backgroundColor: '#c5e8ef'}],
            // 对象形式 : {k:v,k:v}  // 对于style,对象是最适合的
            styleObj: {width: '300px', height: '300px', backgroundColor: '#c5e8ef'},
            // 字符串形式
            classStr: 'div1 div2 div3',
            // 数组形式 ['','','']  // 对于class,数组是最适合的
            classList: ['div1', 'div2', 'div3'],
            // 对象形式 {k:true/false,k:true/false}
            classObj: {div1: true, div2: true, div3: true},
        },
        methods: {},
        computed: {}
    })
</script>
</html>

【3.3】案例:使用点击事件动态修改样式

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>属性指令</title>
    <script src="../js/vue/vue.js"></script>
</head>
<style>
    .div1 {
        height: 300px;
        width: 300px;
        background-color: #0a53be;
    }

    .div2 {
        height: 300px;
        width: 300px;
        background-color: #0a53be;
    }

    .div3 {
        height: 300px;
        width: 300px;
        background-color: #0a53be;
    }

    .div_add {
        font-size: 50px;
        font-family: FangSong;
    }
</style>
<body>
<div id="app">
    <h2>style属性三种方式</h2>
    <div style="display: flex;justify-content: space-around">
        <div v-bind:style="styleStr">
            <p>style属性:str</p>
        </div>
        <div :style="styleList">
            <p>style属性:list</p>
        </div>
        <div :style="styleObj">
            <p>style属性:obj</p>
        </div>
    </div>
    <hr>
    <h2>class属性的三种方式</h2>
    <div style="display: flex;justify-content: space-around">
        <div :class="classStr">
            <p>class属性:str</p>
        </div>
        <div :class="classList">
            <p>class属性:list</p>
        </div>
        <div :class="classObj">
            <p>class属性:obj</p>
        </div>
    </div>
    <h2>使用点击事件动态修改样式</h2>
    <div>
        <p>
            <button @click="handleStyle">添加样式</button>
        </p>
    </div>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            // 字符串形式
            styleStr: 'width: 300px;height: 300px;background-color: #c5e8ef',
            // 数组形式 : [{},{},{}]
            styleList: [{width: '300px'}, {height: '300px'}, {backgroundColor: '#c5e8ef'}],
            // 对象形式 : {k:v,k:v}  // 对于style,对象是最适合的
            styleObj: {width: '300px', height: '300px', backgroundColor: '#c5e8ef'},
            // 字符串形式
            classStr: 'div1 div2 div3',
            // 数组形式 ['','','']  // 对于class,数组是最适合的
            classList: ['div1', 'div2', 'div3'],
            // 对象形式 {k:true/false,k:true/false}
            classObj: {div1: true, div2: true, div3: true},
        },
        methods: {
            handleStyle() {
                // 字符串添加 样式 或 类
                // 对于样式,需要在前面添加【;】做分割
                this.styleStr += ';border-radius: 50%;'
                // 对于类 需要在前面添加空格【 】
                this.classStr += ' div_add'
                // 数组添加  // 数组添加可以使用push 或 +=
                this.styleList.push({borderRadius: '50%'})
                this.classList.push('div_add')
                // 对象添加
                this.styleObj['borderRadius'] = '50%'
                this.classObj['div_add'] = true
            }
        },
        computed: {}
    })
</script>
</html>

Vue-点击事件动态控制样式

【3.4】注意:修改样式未生效的情况

深入响应式原理 — Vue.js (vuejs.org)

  • Vue 的响应式系统无法自动检测到对数组元素或对象属性的直接赋值(例如 arr[0] = newValueobj.key = newValue)。
  • Vue 的响应式系统是基于 JavaScript 属性的 getter 和 setter 实现的,而直接的索引赋值或添加新属性不会触发 setter。
  • Vue 文档中有提到一些方法,如 Vue.set 或使用 Array.prototype.splice,来处理这些限制,确保响应式系统能够检测到所有的更新。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue set 修改样式</title>
    <script src="../js/vue/vue.js"></script>
</head>
<style>
    .div1 {
        height: 300px;
        width: 300px;
        background-color: #0a53be;
    }

    .div2 {
        height: 300px;
        width: 300px;
        background-color: chartreuse;
    }
</style>
<body>
<div id="app">
    <div style="display: flex;justify-content: space-around">
        <div>
            <h1>样式不生效的情况</h1>
            <div :class="classList"></div>
            <p>
                <button @click="handleClass">修改样式</button>
            </p>
        </div>
        <div>
            <h1>使用Vue.set使样式生效</h1>
            <h2>共有很多种方法可以使虚拟dom触发更新</h2>
            <p>【1】数组中:Vue.set(数组,索引,修改的值)</p>
            <p>【1.1】对象中:Vue.set(对象,属性名,修改的值)</p>
            <p>【2】vm.$set:与Vue.set用法一致</p>
            <p>【3】调用变更方法,会触发更新</p>
            <div :class="classList2"></div>
            <p>
                <button @click="handleClass2">使用【Vue.set】修改样式</button>
            </p>
        </div>
    </div>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            classList: ['div1'],
            classList2: ['div1']
        },
        methods: {
            handleClass() {
                // 修改class值
                this.classList[0] = 'div2'
                // 值已经改变了,但没能即时生效
                console.log('classList',this.classList)
            },
            handleClass2() {
                // 会触发响应式更新的修改操作
                // 使用Vue.set
                Vue.set(this.classList2, 0, 'div2')
                // 使用vm.$set
                vm.$set(this.classList2, 0, 'div1')
                // 调用数组的变更方法
                this.classList2.splice(0, 1, 'div2')
                console.log('classList2', this.classList2)
            }
        },
        computed: {}
    })
</script>
</html>

Vue-样式生效

  • 需要注意,当我们点击前面一个样式不生效的情况时,在dom上,它的值已经被改变了,只是没能更新
    当我们触发了vue的响应式更新时,将会查看页面上修改了的dom属性,并更新

Vue-更新dom属性

【三】流程控制

【1】条件渲染v-if v-else-if v-else

指令 释义
v-if 相当于: if
v-else 相当于:else
v-else-if 相当于:else if

【1.2】案例:根据分数判断评价

  • v-if v-else-if v-else包裹的标签视作一个标签即可,因为只有一个条件会符合条件
  • 【注】单独的v-if是允许出现的,因为就是判断布尔值决定标签是否渲染
    • v-else-if v-else是不允许单独出现的
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>流程控制</title>
    <script src="../js/vue/vue.js"></script>
</head>
<body>
<div id="app">
    <p>姓名:{{name}}</p>
    <p>分数:{{score}}</p>
    <p>评价:【
    <span v-if="score === 100">满分</span>
    <span v-else-if="score > 90">优秀</span>
    <span v-else-if="score > 80">良好</span>
    <span v-else-if="score > 60">合格</span>
    <span v-else>不合格</span>
    】</p>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            name: 'user',
            // 随机生成数字
            score: Math.floor(Math.random() * 100),
        },
        methods: {
            // 创建函数 方便演示时在前端生成分数
            handleScore(){
                this.score = Math.floor(Math.random() * 100)
            }
        },
        computed: {}
    })
</script>
</html>
Vue-v-if

【2】遍历渲染v-for

【2.1】遍历数组 遍历对象 遍历数字

<body>
<div id="app">
    <h1>v-for:数组</h1>
    <!-- 遍历数组产生两个值,对象+索引-->
    <!-- 如果只需要使用对象可以不加括号-->
        <!-- v-for="item in dataList"-->
    <ul v-for="(item,index) in dataList">
        <li>item:{{item}}|index:{{index}}</li>
    </ul>
    <h1>v-for:对象</h1>
    <!-- 遍历数组可以产生三个值,对象的值+对象的键+索引-->
    <ul v-for="(value,key,index) in dataObj">
        <li>对象的值:{{value}} |对象的键:{{key}} | 对象的索引:{{index}}</li>
    </ul>
    <h2>v-for:对象,单个值【遍历出每一个item的值】</h2>
    <ul v-for="value in dataObj">
        <li>对象的值:{{value}}</li>
    </ul>
    <h1>v-for:数字</h1>
<!--    遍历数字与python中的for i in range(num)差不多,不过首位是1-->
    <ul v-for="item in num">
        <li>{{item}}</li>
    </ul>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            // 数组
            dataList: [1, 2, 3],
            // 对象
            dataObj: {num1: 6, num2: 4, num3: 13},
            // 数字
            num: 5
        },
        methods: {},
        computed: {}
    })
</script>

image-20240428214412452

【4】案例

【4.1】v-if+v-for+v-else控制购物车商品的显示

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>v-if + v-for + v-else控制购物车商品的显示</title>
    <script src="../js/vue/vue.js"></script>
    <link rel="stylesheet" href="../css/bootstrap/bootstrap.css">
    <script src="../js/bootstrap/bootstrap.js"></script>
</head>
<body>
<div id="box">
    <h2 class="text-center">我的购物车</h2>
    <!--    点击按钮后,将购物车信息赋值给shopping-car-->
    <button @click="show">展示购物车</button>
    <br>
    <!--  如果有商品渲染商品-->
    <table v-if="!shopping_car.length==0" class="table table-hover">
        <tr>
            <td>商品名称</td>
            <td>价格</td>
        </tr>
        <tr v-for="item in shopping_car">
            <td>{{item.name}}</td>
            <td>{{item.price}}</td>
        </tr>
    </table>
    <!--  没有商品显示没有商品信息-->
    <table v-else class="table table-hover">
        <tr>
            <td>商品名称</td>
            <td>价格</td>
        </tr>
        <tr>
            <td>暂无信息</td>
            <td>暂无信息</td>
        </tr>
    </table>
</div>
</body>
<script>
    let vm = new Vue({
        el: '#box',
        data: {
            isActive: false,
            shopping_car: []
        },
        methods: {
            show() {
                if (this.shopping_car.length) {
                    this.shopping_car = []
                } else {
                    this.shopping_car = [
                        {name: '华为-遥遥领先', price: '2999元'},
                        {name: '苹果', price: '9元'},
                        {name: '小米', price: '999元'},
                    ]
                }
            }
        }
    })
</script>
</html>

Vue-条件控制案例

【5】其他知识(了解)

【5.1】更新策略

维护状态 — Vue.js (vuejs.org)

  • Vue.js 在使用 v-for 渲染元素列表时的更新策略。
  • 在默认情况下,Vue 使用 "就地更新" 策略。这意味着当数据项的顺序改变时,Vue 不会移动 DOM 元素以匹配数据项的新顺序,而是会就地更新每个元素,确保它们在 DOM 中的位置与数据项的索引位置相对应。换句话说,Vue 会尽可能地复用已经存在的 DOM 元素,而不是重新创建或移动它们。
  • 这种更新策略的好处是,在处理大型列表时能够更高效地进行 DOM 操作,因为不会频繁地创建、销毁或移动元素,而只是更新已存在的元素。这也可以提高性能并减少浏览器重新渲染的工作量,从而提升用户体验。
  • 类似于 Vue 1.x 中的 track-by="$index",Vue.js 在更新列表时会跟踪每个元素的索引位置,以便正确地应用 "就地更新" 策略。这意味着你不需要手动指定索引,Vue 会自动处理好这些细节。

【5.2】优化数据效率参数key

API — Vue.js (vuejs.org)

  • vue中使用的是虚拟DOM,会和原生的DOM进行比较,然后进行数据的更新,提高数据的刷新速度(虚拟DOM用了diff算法)

    • v-for循环数组、对象时,建议在控件/组件/标签写1个key属性,属性值唯一

    • 页面更新之后,会加速DOM的替换(渲染)

    • :key="变量"

【四】数组更新

【1】变更方法

  • 变更方法,顾名思义,会变更调用了这些方法的原始数组
  • Vue.js 在响应式地处理数组时,对数组的一些常用变更方法进行了包装,以便能够自动检测到数组的变化,并触发相应的视图更新。这些被包裹过的方法包括:
    1. push(): 将一个或多个元素添加到数组的末尾,并返回新的长度。
    2. pop(): 移除数组的最后一个元素,并返回该元素的值。
    3. shift(): 移除数组的第一个元素,并返回该元素的值,同时将数组长度减一。
    4. unshift(): 在数组的开头添加一个或多个元素,并返回新的长度。
    5. splice(): 在指定位置插入或删除元素,并返回被删除的元素组成的数组。
    6. sort(): 对数组元素进行排序,如果没有传递比较函数,则默认按照 Unicode 码点进行排序。
    7. reverse(): 将数组中的元素顺序颠倒,第一个元素变为最后一个,最后一个元素变为第一个。
  • 这些方法被 Vue.js 包装后,当你使用它们修改数组时,Vue.js 将能够侦测到数组的变化,并在必要时更新视图,以确保视图与数据的同步。这是 Vue.js 实现响应式的重要特性之一,使得开发者可以更轻松地处理数据的变化并实时更新用户界面。

【2】非变更方法

  • 非变更方法,它们不会变更原始数组,而总是返回一个新数组
  • 当使用非变更方法时,可以用新数组替换旧数组

Vue 使用一些智能的启发式方法(如虚拟 DOM 的 diff 算法)来尽可能重用现有的 DOM 元素,从而提高性能和效率。这意味着,即使整个数组被替换,如果新数组中包含与旧数组相同的元素,Vue 将尽量保持这些元素的 DOM 表示不变。

  • 常见的非变更方法及其功能:
  1. filter()
    • 功能:创建一个新数组,其中包含通过某个函数测试的所有元素。
  2. concat()
    • 功能:用于合并两个或多个数组。不会改变现有数组,而是返回一个新数组。
  3. slice()
    • 功能:从现有数组中返回选定的元素。不会改变现有数组。

【3】变更方法与非变更方法实例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>数组更新</title>
    <script src="../js/vue/vue.js"></script>
</head>
<body>
<div id="app">
    <h1>数组更新</h1>
    <ul v-for="item in dataList">
        <li>{{item}}</li>
    </ul>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            dataList: [2, 1, 9],
        },
        methods: {
            // 变更方法
            handlePush() {
                this.dataList.push(22)
            },
            handlePop() {
                this.dataList.pop()
            },
            handleSort() {
                this.dataList.sort()
            },
            // 非变更方法
            handleFilter() {
                // filter 方法返回布尔值 根据布尔值判断是否显示
                // 不改变原数组  // 需要声明一个新的变量或重新赋值
                return this.dataList.filter(
                    item => item < 5
                )
            }
        },
        computed: {}
    })
</script>
</html>

Vue-变更方法与非变更方法

【五】表单控制

【1】checkbox和radio

  • 当数据绑定的值为字符串时,接收一个值
  • 当数据绑定的值为数组时,接收多个值
<body>
<div id="app">
    <form>
        <p> 用户名: <input type="text" v-model="username"></p>
        <p>
            爱好:【checkbox:数组】
            <input type="checkbox" v-model="hobby" value="0">爱好1
            <input type="checkbox" v-model="hobby" value="1">爱好2
            <input type="checkbox" v-model="hobby" value="2">爱好3
        </p>
        <p>
            性别: 【radio:字符串】
            <input type="radio" v-model="gender" value="0">女
            <input type="radio" v-model="gender" value="1">男
        </p>
        <p>
            是否记住:【checkbox:字符串/布尔值】
            <input type="checkbox" v-model="is_remember">
        </p>
    </form>
    <hr>
    <div>
        <p>
            信息如下:
            username : {{username}} <br>
            hobby : {{hobby}} <br>
            gender : {{gender}} <br>
            is_remember : {{is_remember}} <br>
        </p>
    </div>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            username: '',
            hobby: [],
            gender: '',
            is_remember: true
        },
        methods: {},
        computed: {}
    })
</script>

Vue-表单控制

【2】购物车案例

【2.1】前端

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue/vue.js"></script>
    <script src="./js/bootstrap/bootstrap.js"></script>
    <link rel="stylesheet" href="./css/bootstrap/bootstrap.css">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
</head>
<body>
<div id="app">
    <div class="container text-center">
        <h1>{{username}}购物车</h1>
        <div class="row justify-content-md-center">
            <div class="col-6">
                <table class="table table-hover">
                    <thead>
                    <tr>
                        <th scope="col">商品id</th>
                        <th scope="col">商品名称</th>
                        <th scope="col">商品价格</th>
                        <th scope="col">商品数量</th>
                        <th scope="col">全选/全不选
                            <span><input type="checkbox" @change="checkAll" v-model="isAll"></span>
                        </th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr v-for="item in goodsList" v-if="item.count !== 0">
                        <td>{{item.id}}</td>
                        <td>{{item.name}}</td>
                        <td>{{item.price}}</td>
                        <td>
                            <!--                            <button class="bi bi-dash" @click="dwindleCount(item)"></button>-->
                            <button class="btn" @click="item.count>1?item.count--:item.count=1">-</button>
                            {{item.count}}
                            <button class="btn" @click="item.count++">+</button>
                        </td>
                        <td>
                            <input type="checkbox" @click="checkOne" v-model="goodsCheck"
                                   :value="item" @change="checkOne">
                        </td>
                    </tr>
                    </tbody>
                </table>
                <div>
                    <p>gross:{{goodTotal}}</p>
                    <button class="btn btn-success" @click="goodsSubmit">提交</button>
                </div>
            </div>
        </div>
    </div>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            username:'',
            isAll: false,
            goodsList:[],
            goodsCheck: []
        },
        methods: {
            // 提交数据
            goodsSubmit() {
                console.log(this.goodsCheck)
                alert('提交了数据')
            },
            // 全选或全不选
            checkAll() {
                if (this.isAll) {
                    this.goodsCheck = this.goodsList
                } else {
                    this.goodsCheck = []
                }
            },
            // 选中单个
            checkOne() {
                // 如果选中的商品长度与所有商品长度一致代表选中了所有商品
                this.isAll = this.goodsCheck.length === this.goodsList.length;
            },
            // 减少数量
            dwindleCount(item) {
                if (item > 1) {
                    item.count--
                } else {
                    item.count = 1;
                    alert('最低数量为1')
                }
            }
        },
        computed: {
            // 计算属性
            goodTotal() {
                let total = 0
                for (let item of this.goodsCheck) {
                    total += item.price * item.count
                }
                return total
            }
        },
        created() {
            fetch('http://127.0.0.1:5000/cart/1/').then(response => response.json()).then(
                res => {
                    console.log(res)
                    this.username=res.username
                    this.goodsList = res.result
                }
            )
        }
    })
</script>
</html>

【2.2】后端(flask)

import json

from flask import Flask, jsonify

app = Flask(__name__)


@app.route('/')
def index():
    res = jsonify({
        'code': 100,
        'msg': 'success',
        'result': {
            'name': 'lea4ning',
            'age': 20
        }
    })
    res.headers['Access-Control-Allow-Origin'] = '*'
    return res


@app.route('/cart/1/')
def get_cart():
    with open('../goods.json', 'r', encoding='utf-8') as f:
        data = json.load(f)
    res = jsonify({
        'code': 100,
        'msg': 'success',
        'username': 'lea4ning',
        'result': data
    })
    res.headers['Access-Control-Allow-Origin'] = '*'
    return res


if __name__ == '__main__':
    app.run()
  • ../goods.json
[
  {
    "id": 101,
    "name": "HuaWei",
    "price": 7999,
    "count": 3
  },
  {
    "id": 102,
    "name": "apple",
    "price": 7998,
    "count": 1
  },
  {
    "id": 103,
    "name": "Xiaomi",
    "price": 3999,
    "count": 3
  },
  {
    "id": 104,
    "name": "Oppo",
    "price": 1230,
    "count": 6
  }
]

【2.3】演示效果

Vue-购物车案例

posted @ 2024-05-07 14:42  Lea4ning  阅读(64)  评论(0编辑  收藏  举报