0.Vue的介绍及使用

1. 前端的发展史

1. HTML(5) CSS(3) JavaScript(ES5ES6): 编写一个个的页面 -> 给后端(Python) -> 
   后端嵌入模板语法 -> 后端渲染完数据 -> 返回数据给前端 -> 在浏览器中查看

2. Ajax的出现 -> 后台发送异步请求, Render+Ajax混合

3. 单用Ajax(加载数据, DOM渲染页面): 前后端分离的雏形

4. Angular框架的出现(JS的框架): 出现了前端工程化的概念(前端也是1个工程或1个项目)

5. React Vue: 当下最火的2个前端框架(Vue:国人喜欢用, React:外国人喜欢用)

6. 移动开发(Android+IOS) + Web(Web+微信小程序+支付宝小程序) + 桌面开发(Windows桌面):前端 -> 大前端

7. 一套代码在各个平台运行(大前端): 谷歌Flutter(Dart语言:和Java很像)可以运行在IOS Android PC端

8. uni-app(在Vue框架的基础性上): 一套编码 编到10个平台

详细的发展史:
https://zhuanlan.zhihu.com/p/337276087?utm_source=wechat_session&utm_medium=social&utm_oi=41967790587904

2. js/node.js

js  node.js
js: 就是一门解释型语言, 解释型的语言是需要解释器的, 只不过js解释器被集成到了浏览器中
node.js 一门后端语言把chrome的v8引擎(解释器), 安装到操作系统之上
js解释器在浏览器的开发者工具中

image-20220505104110931

node.js 需要下载安装到本地系统中

image-20220507004414474

2.1 es6新特性
1. 模板语法
模板语法的使用
var name = 'kid'
console.log(`我的名字叫${name}`)  // 我的名字叫kid
2. 箭头函数
箭头函数, 没有自己的this
var 函数名 =('参数')=>{函数体}
var f = () => { console.log('hello word!')  }

f()  // hello word!
var f = (text) => { console.log(text)  }


f('hello word!')  // hello word!
var 函数名 =参数=>{函数体} (一个参数时可以不省略括号)
var f = text=> { console.log(text)  }

f('hello word!')  // hello word!
var 函数名 =参数=> 函数体 (函数体只有一句代码)
var f =()=>console.log('hello word!')

f()  // hello word!
var 函数名 =参数=> 参数  (直接返回参数的话可以这样下)
var f = text=> text

var str = f('hello')

console.log(str)  // hello
3. 对象的定义
自定义对象的写法key可以加'', 也可以不加'':
var name = 'kid'

var age = 18
var obj = {'name': name, 'age': age}

console.log(obj)  // {name: 'kid', age: 18}
var obj = {name: name, age: age}

console.log(obj)  // {name: 'kid', age: 18}
var obj = {f: function(){console.log('xx')}}

obj.f()  // xx
新特性, 将变量名作为key, 变量值作为value
var obj = {name, age}
console.log(obj)  // {name: 'kid', age: 18}
var obj = {f(){console.log('xx')}}

obj.f()  // xx
2.2 遍历/循环取值
1. 基于索引循环
var array1 = [1, 2, 3, 4]
// 通过索引取值
for(let i=0; i<array1.length; i++){
    console.log(array1[i])
}
结果:
1
2
3
4
2. 迭代in
var array1 = [1, 2, 3, 4]
// 遍历 in 拿到的是索引, 通过索引取值
for (i in array1){console.log(array1[i])}
结果:
1
2
3
4
var obj = {name: 'kid', age: 18, gender: 'male'}
for(key in obj){
    console.log(key)
}
结果:
name
age
gender
3. 迭代of
对象无法使用
var array1 = [1, 2, 3, 4]
// 遍历 of 拿到的是值 
for (i of array1){console.log(i)}
结果:
1
2
3
4
4. 数组迭代方法
var array1 = [1, 2, 3, 4]
// forEach迭代取值得到 值 与 索引
array1.forEach(function(value, index){
    console.log(value, array1[index])
})
// 箭头函数
array1.forEach(a=(value, index)=>{
    console.log(value, array1[index])
})
结果:
1 1
2 2
3 3
4 4

3. Vue介绍

Vue是js的一个框架.

Vue: 读音/vjuː/, 类似于view, 是一套用于构建用户界面的渐进式框架.

与其它大型框架不同的是, Vue被设计为可以自底向上逐层应用.

Vue的核心库只关注视图层, 不仅易于上手, 还便于与第三方库或既有项目整合.

渐进式框架: 可以一点一点地使用它, 只用一部分, 也可以整个工程都使用它.
官网: https://cn.vuejs.org/
文档: https://cn.vuejs.org/v2/guide/
版本:
    1.X:使用得较少
    2.X:普遍使用
    3.X:刚出没多久, 只有Beta版

4. M-V-VM思想

MVVM 是Model-View-ViewModel的缩写, 它是一种基于前端开发的架构模式, 是一种事件驱动编程方式.

Model : vue对象的data属性的数据, 这里的数据要显示到页面中.
View : vue中数据要显示的HTML页面, 在vue中, 也称之为视图模板(HTML+CSS).
ViewModel: vue中编写代码时的vm对象, 它是vue.js的核心, 负责连接 View  Model数据的中转, 保证视图和数据的一致性.
代码中, data里面的数据与显示在标签中值以是一种双向数据绑定关系.
双向数据绑定: JS中变量变了, HTML中数据也跟着改变, HTML中数据改变, JS中变量也跟着改变.
这个操作是vm对象自动完成的.

5. 组件化开发/单页面开发

5.1 组件化开发
类似与Django中使用的DTL模板语言的include机制,每一个组件的内容都可以被替换和复用.
整个页面是一个组件, 页面中可划分多个小组件, 小组件中还可以使用组件.

img

5.2 单页面开发
只需要1个页面, 结合组件化开发来替换页面中的内容.

页面的切换只是组件的替换, 页面还是只有1个index.html文件.

6. Vue引入方式

6.1 CDN引入
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
6.2 文件引用
浏览器中打开cnd提供的地址 https://cdn.jsdelivr.net/npm/vue/dist/vue.js, 看到vue.js的所有代码
然后Ctrl+a全选, Ctrl+v复制, 在本地电脑上新建一个vue.js文件, 将复制的代码粘贴到改文件中.
<script src="文件存放地址"></script>
6.3 本地文件引用提示问题
将文件放在js下, 名字是小写的vue.js.

image-20220506214551096

7. 声明式渲染

Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统.
声明变量:
在引入Vue之后, 页面就有了一个Vue函数. 
js 定义对象需要加上关键字 new.
定义对象时传入参数, 
    el: 元素, 指定data中变量作用的标签, 
    data: 数据, 定义变量,
    methods: 方法, 定义函数.
var app3 = new Vue({参数..}) 得到一个ViewModel对象

模板语法插值语法: {{变量名}}
使用变量: 在el指定的标签中使用插值语法使用变量.
7.1 简单使用
* 1. 新建一个Python项目, 在项目下新建一个html文件

image-20220507004520980

image-20220507004457017

* 2. 引用vue文件, 写入测试代码

image-20220507004622877

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>声明式渲染</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>

<!-- 插值语法使用变量 -->
<div id="app">
    <!--插值语法使用变量-->
    {{ message }}
    <!--插值语法调用函数-->
    {{ func()}}
</div>

<!--定义Vue对象-->
<script>
    // 生成一个vue的对象
    var app = new Vue({
        // 元素, 找打对应的标签
        el: '#app',
        // 数据, 在data中定义的数据, html中el指定的标签中 使用{{变量名}} 取值
        data: {
            message: 'hello word!'
        },
        // 方法, 在methods定义需要使用的函数 函数名(){函数体}
        methods: {
            func() {
                console.log('hello word!')
            }
        }
    })
</script>
</body>
</html>

image-20220506224731791

7.2 数据的双向绑定
双向数据绑定: JS中变量变了, HTML中数据也跟着改变, HTML中数据改变, JS中变量也跟着改变.
这个操作是vm对象自动完成的.
v-model指令可以在表单 input、textarea以及select元素上创建双向数据绑定, 后面详细说.
vm对象._data 获取data属性, data属性的值是一个自定义对象.
vm对象._data['属性']  vm对象._data.属性 获取自定义对象中的属性值.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>插值语法</title>
    <script src="Vue.js"></script>
</head>
<body>
<!-- 插值语法使用js的三目运算 -->
<div id="app">
    <input type="text" v-model="str">
    <p>input中输入的值:{{str}}</p>
</div>


<!--定义Vue对象-->
<script>
    var app = new Vue({
        // 元素, 找打对应的标签
        el: '#app',
        data: {
            str: ''
        }
    })
</script>
</body>
</html>

2022-05-05_00517

2022-05-05_00518

8. 模板语法

8.1 插值语法
插值是在标签内使用的, 值可以是一个变量, 也可是是一个函数.
<xx> {{变量}} </xx>
插值语法中可以简单的使用js的代码.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>插值语法</title>
    <script src="Vue.js"></script>
</head>
<body>
<!-- 插值语法使用js的三目运算 -->
<div id="app">
    <ul>
        <li>{{ num }}</li>
        <li>{{ str }}</li>
        <li>{{ array1[0] }}</li>
        <li>{{ obj.name }}</li>
        <li>数学运算:{{ 1 + 2 }}</li>
        <li>三目运算符: {{ 10 > 20 ? '是' : '否' }}</li>
    </ul>

</div>


<!--定义Vue对象-->
<script>
    var app = new Vue({
        // 元素, 找打对应的标签
        el: '#app',
        data: {
            // 定义数值类型
            num: 11,
            // 定义字符串
            str: 'hello word!',
            // 定义数组
            array1: [1, 2, 3],
            // 自定义对象
            obj: {'name': 'kid'}
        }
    })
</script>
</body>
</html>

image-20220505160351020

8.2 文本指令
指令释义
v-html让HTML渲染成页面(可以渲染字符中的html代码)
v-text标签内容显示js变量对应的值(不可以渲染字符中的html代码, 原样展示字符串)
v-show放1个布尔值:为真 标签就显示.为假 标签就不显示(使用display:none, 标签存在, 占位子, 不显示)
v-if放1个布尔值:为真 标签就显示.为假 标签就不显示(直接操作DOM,删除/插入 标签)
1. 显示值
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"> 
    <title>Vue的简单使用</title>
    <script src="Vue.js"></script>
</head>
<body>
<div id="div">
    <ul>
        <li v-html="link"></li>

        <li v-text="link"></li>
    </ul>
</div>


<!--定义Vue对象-->
<script>
    var app = new Vue({
        // 元素, 找打对应的标签
        el: '#div',
        data: {
            link: '<a href="https://www.baidu.com">百度一下 你就知道</a>'
        }
    })
</script>
</body>
</html>
2.隐藏标签

image-20220505123617534

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue的简单使用</title>
    <script src="Vue.js"></script>
</head>
<body>
<div id="div">
    <ul>
        <li v-show="is_show">123</li>

        <li v-if="is_if">456</li>
    </ul>
</div>


<!--定义Vue对象-->
<script>
    var app = new Vue({
        // 元素, 找打对应的标签
        el: '#div',
        data: {
            is_show: false,
            is_if: false,
        }
    })
</script>
</body>
</html>

2022-05-05_00503

8.3 事件指令
指令释义
v-on触发事件(不推荐)
@触发事件(推荐 v-on: 简写–> @)
@[event]触发event事件(可以是其他任意事件)
Event 对象代表事件的状态, 比如事件在其中发生的元素, 键盘按键的状态, 鼠标的位置, 鼠标按钮的状态.
在实例ViewModel对象时, 为methods参数提供一个函数. 在函数中写事假触发之后执行的代码!
在methods中写的第一层函数不需要写function关键字.
1.触发实践(不带参数)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>点击事假(函数不带参数)</title>
    <script src="Vue.js"></script>
</head>
<body>
<div id="div">
    <!--click点击事件, 函数不需要传递参数, 可以省略括号-->
    <button v-on:click="handleClick1">按键1</button>
    <button @click="handleClick1">按键2</button>
</div>


<!--定义Vue对象-->
<script>
    var app = new Vue({
        // 元素, 找打对应的标签
        el: '#div',
        // 在方法中定义函数
        methods: {
            // 点击处理
            handleClick1() {
                console.log('点击事件1')
            }
        }
    })
</script>
</body>
</html>
两个按键都可以触发点击事件.

image-20220505153613831

2.触发实践(带参数)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>点击事假(函数带参数)</title>
    <script src="Vue.js"></script>
</head>
<body>
<div id="div">
    <!--click点击事件, 参数正常传递-->
    <button @click="handleClick1(1, 2)">计算1+2</button>
</div>


<!--定义Vue对象-->
<script>
    var app = new Vue({
        // 元素, 找打对应的标签
        el: '#div',
        methods: {
            // 点击处理
            handleClick1(x, y) {
                console.log(x + y)
            }
        }
    })
</script>
</body>
</html>

image-20220505154037503

3.this参数
在Vue对象中methods中定义的第一层函数使用this, 代指的是Vue对象.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue的简单使用</title>
    <script src="Vue.js"></script>
</head>
<body>
<div id="div">
    <!-- 传入事件 -->
    <button @click="handleClick">按键</button>
    <p v-show="is_show">点击按键, 看这一行的变化!</p>
</div>


<!--定义Vue对象-->
<script>
    var app = new Vue({
        // 元素, 找打对应的标签
        el: '#div',
        data: {
            is_show: true
        },
        methods: {
            // 点击处理
            handleClick() {
                // 点击就取反
                this.is_show = !this.is_show
            }
        }
    })
</script>
</body>
</html>

GIF 2022-5-5 15-51-13

8.4 属性指令
属性指令: 是给标签的属性设置值时使用的.
属性指令中可以使用简单js代码, eg: 三目运算符...
指令释义
v-bind直接写js的变量或语法(不推荐)
:直接写js的变量或语法(推荐)
v-bind:class='js变量'可以缩写成::class='js变量'
1. 使用实例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>属性指令</title>
    <script src="Vue.js"></script>
</head>
<body>
<div id="d1">
    <!--完整写法-->
    <img v-bind:src="url" alt="百度.png" height="100">
    <!--省略写法-->
    <img :src="url" alt="百度.png" height="100">
</div>

<!--定义Vue对象-->
<script>
    var app = new Vue({
        // 元素, 找打对应的标签
        el: '#d1',
        data: {
            // 百度的图片地址
            url: 'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=205441424,1768829584&fm=26&gp=0.jpg'
        }
    })
</script>
</body>
</html>
2. 属性切换实例
定义两个样式, 通过按键切换样式.
:class="is_true? 'red' : 'orange' "
is_true为真 class='red'
is_true为假 class='orange'
* "变量" --> 得到的值需要是一个字符串, class="". 下节详情说明!
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>属性指令</title>
    <script src="Vue.js"></script>
    <style>
        .red {
            background-color: red;
        }
        .orange {
            background-color: orange;
        }

    </style>
</head>
<body>
<div id="d1">
    <!-- 按键改变is_true的值 -->
    <button @click="ClickEvent">换颜色</button>
    <!--三目运算 判断is_true的值, 取出使用的属性-->
    <div style="width: 100px; height: 100px;" :class="is_true?'red':'orange'"></div>
</div>

<!--定义Vue对象-->
<script>
    var app = new Vue({
        // 元素, 找打对应的标签
        el: '#d1',
        data: {
        // 定义一个变量
            is_true: true,
        },
        methods: {
            ClickEvent(){
                // 点击一次取反一次
                this.is_true = !this.is_true
            }
        }
    })
</script>
</body>
</html>

GIF 2022-5-5 19-59-39

9. Class 与 Style 样式操作

:属性名="js变量" 
:class= "js变量"-->得到的值 字符串 / 数组 /对象{red: true}  
:style= "js变量"-->得到的值 字符串 / 数组[{color: 'red'},]  / 对象{color: 'red'}  
推荐使用对象, 对象可以指定需要的开关的属性, 数组无法指定元素名删除	, 所有不方便, 字符串更加难添加删除值.
9. 1 Class
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>class</title>
    <script src="Vue.js"></script>
    <style>
        /* 字体颜色 */
        .color {
            color: orange;
        }

        /* 背景颜色 */
        .red {
            background-color: red;
        }

        /* 字体 */
        .font {
            font-size: 60px;
        }

    </style>
</head>
<body>
<div id="d1">
    <p :class="Attributes1">p1</p>

    <p :class="Attributes2">p2</p>

    <p :class="Attributes3">p3</p>

    <p>p2的操作按键: </p>
    <p>
        <button @click="DelColor">去掉字体颜色</button>
        <button @click="DelRed">去掉背景颜色</button>
        <button @click="DelFont">去掉字体设置</button>
    </p>
    <p>
        <button @click="AddColor">字体颜色</button>
        <button @click="AddRed">背景颜色</button>
        <button @click="AddFont">字体设置</button>
    </p>

</div>

<!--定义Vue对象-->
<script>
    var app = new Vue({
        // 元素, 找打对应的标签
        el: '#d1',
        data: {
            //
            Attributes1: 'color red font',
            Attributes2: ['color', 'red', 'font'],
            Attributes3: {'color': true, 'red': true, 'font': true}
        },
        methods:{
            DelColor(){
                this.Attributes3.color = false
            },
            DelRed(){
                this.Attributes3.red = false
            },
            DelFont(){
                this.Attributes3.font = false
            },

            AddColor(){
                this.Attributes3.color = true
            },
            AddRed(){
                this.Attributes3.red = true
            },
            AddFont(){
                this.Attributes3.font = true
            }
        }
    })
</script>
</body>
</html>
9.2 style
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>class</title>
    <script src="Vue.js"></script>
</head>
<body>
<div id="d1">
    <p :style="Attributes1">p1</p>

    <p :style="Attributes2">p2</p>

    <p :style="Attributes3">p3</p>
</div>

<!--定义Vue对象-->
<script>
    var app = new Vue({
        // 元素, 找打对应的标签
        el: '#d1',
        data: {
            Attributes1: 'color: orange; background: red; font-size: 60px;',
            Attributes2: [{color: 'orange'}, {background: 'red'}, {fontSize: '60px'}],
            Attributes3: {color: 'orange', background: 'red', fontSize: '60px'}
        }
    })
</script>
</body>
</html>

10. 条件渲染

指令释义
v-if相当于: if
v-else相当于:else
v-else-if相当于:else if
条件渲染在标签属性中使用, 当满足条件时才渲染标签.
v-if="条件"
10.1 实例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>if判断</title>
    <script src="Vue.js"></script>
</head>
<body>
<div id="d1">
    <p>你的成绩是{{num}}, 评价为:
        <span v-if="num >= 86">优秀</span>
        <span v-else-if="num >= 60">良好</span>
        <span v-else-if="num < 60">不及格</span>
        <span v-else>成绩录入值无法判断</span>
    </p>


</div>

<!--定义Vue对象-->
<script>
    var app = new Vue({
        // 元素, 找打对应的标签
        el: '#d1',
        data: {
            num: 'a'
        },
    })
</script>
</body>
</html>
num的值为90:  你的成绩是90, 评价为: 优秀
num的值为80:  你的成绩是80, 评价为: 良好
num的值为59:  你的成绩是59, 评价为: 不及格
num的值为a:  你的成绩是a, 评价为: 成绩录入值无法判断

11. v-for遍历

指令释义
v-for从遍历的对象中取值
v=for=" i in 可遍历的对象" 取一个值
v=for=" (x, y) in 可遍历的对象" 取两个值
11.1 遍历数字
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>v-for遍历值</title>
    <script src="Vue.js"></script>
</head>
<body>

<div id="d1">
    <!--遍历数字-->
    <span v-for="i in num">{{i}}</span>
</div>

<!--定义Vue对象-->
<script>
    var app = new Vue({
        // 元素, 找打对应的标签
        el: '#d1',
        data: {
            num: 5
        }
    })
</script>
</body>
</html>

image-20220505225142576

11.2 遍历字符串
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>v-for遍历值</title>
    <script src="Vue.js"></script>
</head>
<body>

<div id="d1">
    <span v-for="i in str">{{i}}</span>
</div>

<!--定义Vue对象-->
<script>
    var app = new Vue({
        // 元素, 找打对应的标签
        el: '#d1',
        data: {
            str: 'hello'
        }
    })
</script>
</body>
</html>

image-20220505225404389

11.3 遍历数组
取值:
v=for="i in 可遍历的对象"
取值和索引:
v=for=" (值, 索引) in 可遍历的对象"   值前, 索引后
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>v-for遍历值</title>
    <script src="Vue.js"></script>
</head>
<body>

<div id="d1">
    <p v-for="(i, index) in array1">值:{{i}} 索引:{{index}}</p>
</div>

<!--定义Vue对象-->
<script>
    var app = new Vue({
        // 元素, 找打对应的标签
        el: '#d1',
        data: {
            array1: [1, 2, 3, 4, 5]
        }
    })
</script>
</body>
</html>

image-20220505225838972

在v-for循环数组对象时, 建议在控件/组件/标签写1:key属性, 属性值唯一即可.
页面更新之后, 会加速DOM的替换(渲染)
:key="变量"

:key值 的解释
vue中使用的是虚拟DOM, 会和原生的DOM进行比较, 然后进行数据的更新, 提高数据的刷新速度(虚拟DOM用了diff算法)
不加:key时, 修改数组时会重新对整个数组重新渲染.
:key时, 修改数组时只对修改部分重新渲染, 所以效率高.
11.4 遍历对象
取值:
v=for="i in 可遍历的对象"
取和键:
v=for=" (值, 键) in 可遍历的对象"   值前, 键后
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>v-for遍历值</title>
    <script src="Vue.js"></script>
</head>
<body>

<div id="d1">
    <p v-for="(value, key) in obj">值:{{value}} 键:{{key}}</p>
</div>

<!--定义Vue对象-->
<script>
    var app = new Vue({
        // 元素, 找打对应的标签
        el: '#d1',
        data: {
            obj: {'name': 'kid', 'age': 18}
        }
    })
</script>
</body>
</html>

image-20220505230552646

11.5 数组套对象
先从数组中取出对象, 对象.属性取值.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>v-for遍历值</title>
    <script src="Vue.js"></script>
</head>
<body>

<div id="d1">
    <table border="1px">
        <thead>
        <tr>
            <th>姓名</th>
            <th>年龄</th>
            <th>性别</th>
        </tr>
        </thead>

        <tbody>

        <tr v-for="obj in array_obj">
            <td>{{obj.name}}</td>
            <td>{{obj.age}}</td>
            <td>{{obj.gender}}</td>
        </tr>
        </tbody>
    </table>
</div>

<!--定义Vue对象-->
<script>
    var app = new Vue({
        // 元素, 找打对应的标签
        el: '#d1',
        data: {
            array_obj: [
                {'name': "kid", 'age': 18, 'gender': '男'},
                {'name': "qq", 'age': 19, 'gender': '女'},
                {'name': "qzq", 'age': 20, 'gender': '男'},
            ]
        }
    })
</script>
</body>
</html>

image-20220505231543627

11.6 表单渲染
v-if+v-for+v-else控制购物车商品的显示
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>购物车展示</title>
    <script src="Vue.js"></script>
</head>
<body>

<div id="d1">
    <h1>购物车</h1>
    <table border="1px">
        <thead>
        <tr>
            <th>商品</th>
            <th>价格</th>
        </tr>
        </thead>

        <tbody v-if="shop.length==0">
        <tr>
            <td>暂无信息</td>
            <td>暂无信息</td>
        </tr>
        </tbody>

        <tbody v-else>

        <tr v-for="obj in shop">
            <td>{{ obj.name }}</td>
            <td>{{ obj.price }}</td>
        </tr>
        </tbody>

    </table>

    <br>
    <button @click="show">一键添加</button>
</div>

<!--定义Vue对象-->
<script>
    var app = new Vue({
        // 元素, 找打对应的标签
        el: '#d1',
        data: {
            shop: []
        },
        methods: {
            show() {
                this.shop = [
                    {'name': '苹果', 'price': '12'},
                    {'name': '芒果', 'price': '15'},
                    {'name': '西瓜', 'price': '30'},
                ]
            },
        }
    })
</script>
</body>
</html>

GIF 2022-5-5 23-46-03

12. 数组的更新与检测

Vue作者重写数组的一些方法, 使得列表在变动只能被检测, 并更新渲染.
可以检测到的数组操作方法:
push:最后位置添加
pop:最后位置删除
shift:第一个位置删除
unshift:第一个位置添加
splice:切片
sort:排序
reverse:反转
检测不到变动的数组操作:
数组[索引]=改值
filter():过滤
concat():追加另一个数组
slice()
map()
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>数组</title>
    <script src="Vue.js"></script>
</head>
<body>

<div id="d1">
    <p v-for="i in array1">第{{i}}行</p>
</div>

<!--定义Vue对象-->
<script>
    var app = new Vue({
        // 元素, 找打对应的标签
        el: '#d1',
        data: {
            array1: [1, 2, 3]
        },
    })
</script>
</body>
</html>

image-20220506094857359

值修改了, 没有重新渲染. 
Vue中提供了一个set属性, 用于修改值, 并触发发渲染!
Vue.set(对象, index, value) 更新数组(数据会更新,页面也会发生改变)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>数组</title>
    <script src="Vue.js"></script>
</head>
<body>

<div id="d1">
    <p v-for="i in array1">第{{i}}行</p>
</div>

<!--定义Vue对象-->
<script>
    var app = new Vue({
        // 元素, 找打对应的标签
        el: '#d1',
        data: {
            array1: [1, 2, 3]
        },
    })
</script>
</body>
</html>

image-20220506095516803

13. 输入框双向绑定数据

输入框中使用v-model='变量'的方式将 value属性的值绑定给变量.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>数组</title>
    <script src="Vue.js"></script>
</head>
<body>

<div id="d1">
    <input type="text" v-model="text"> --> {{text}}
</div>

<!--定义Vue对象-->
<script>
    var app = new Vue({
        // 元素, 找打对应的标签
        el: '#d1',
        data: {
            text: ''
        }
    })
</script>
</body>
</html>

image-20220506103111592

14. 事件处理

事件释义
input当输入框进行输入的时候 触发的事件
change当元素的值发生改变时 触发的事件
blur当输入框失去焦点的时候 触发的事件
change  blur 最本质的区别:
change值发生改变才触发, 
如果输入框为空, 失去焦点后, change不会触发, 但是blur会触发.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>input事件</title>
    <script src="Vue.js"></script>
</head>
<body>

<div id="d1">
    Input: <input type="text" v-model="text1" @input="Input">
    <hr>
    Change <input type="text" v-model="text2" @change="Change">
    <hr>
    Blur<input type="text" v-model="text3" @blur="Blur">
</div>

<!--定义Vue对象-->
<script>
    var app = new Vue({
        // 元素, 找打对应的标签
        el: '#d1',
        data: {
            text1: '',
            text2: '',
            text3: '',
        },
        methods: {
            Input() {
                console.log('input触发器:', this.text1)
            },
            Change() {
                console.log('change触发器:',this.text2)
            },
            Blur() {
                console.log('blur触发器:',this.text3)
            }
        }
    })
</script>
</body>
</html>
每输入一个值触发一次

image-20220506105741448

每次改变了值, 退出聚焦, 触发

2022-05-06_00529

每次退出聚焦, 触发, 展示款内的值

image-20220506110231414

15 文本过滤

15.1 filter过滤
var array1 = ['a', 'ab', 'abc', 'abcd', 'abcde']

// filter 会遍历数组, 交给函数做处理, 返回True, 过滤成功返回true, 否则返回false
var array2 = array1.filter(function (item){
    // 字符串长度大于2的保留
    if (item.length>2){
        return true
    }
})
console.log(array2) //  ['abc', 'abcd', 'abcde']
15.2 字符串包含字符串
indexOf 判断字符串是否包含某个字符串, 如果包含返回它最开始匹配所在的索引, 否则返回-1.
var str1 = 'abc'

str1.indexOf('ab')  // 0

str1.indexOf('bc')  // 1

str1.indexOf('ac')   // -1
15.3 输入联动过滤
注意点: Vue对象中定义的第一层函数的this是Vue, 第二层定义的函数使用的this就是Windows.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>输入联动过滤</title>
    <script src="Vue.js"></script>
</head>
<body>

<div id="d1">
    在过滤框中输入值:
    <!--输入-->
    <input type="text" @input="in_filter" v-model="text">
    <p>所有的数据:</p>
    <ul>

        <!-- 遍历过滤好的数组 -->
        <li v-for="i in array2">{{i}}</li>
    </ul>
</div>

<!--定义Vue对象-->
<script>
    var app = new Vue({
        el: '#d1',
        data: {
            text: '',
            // 需要过滤的列表
            array1: ['a', 'ab', 'abc', 'x', 'xy', 'xyz'],
            // 第一次展示的列表, 与接收过滤array1过滤后的列表
            array2: ['a', 'ab', 'abc', 'x', 'xy', 'xyz'],
        },
        methods: {
            in_filter() {
                // 对数组进行过滤 将数组的组遍历交给函数处理

                // 第二层函数的this是windows对象不是Vue对象  将Vue对象 保存到变量中
                var _this = this
                this.array2 = this.array1.filter(function (item) {
                    // 判断 输入的 是否被 遍历的值包含, 如果包含了过滤成功返回该值
                    if (item.indexOf(_this.text) > -1) {
                        return true
                    }
                })
            }
        }
    })
</script>
</body>
</html>

GIF 2022-5-6 14-02-32

15.4 箭头函数
es6中为了解决this的问题, 设计了一个箭头函数, 箭头函数, 没有自己的this. 那么会调用上层的this.
var app = new Vue({
    methods: {
        in_filter() {
            // Vue {_uid: 2, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
            console.log(this)

            function f() {
                // Window {window: Window, self: Window, document: document, name: '', location: Location, …}
                console.log(this)
            }

            f()
        }
    }
})


app.in_filter()
var app = new Vue({
    methods: {
        in_filter() {
            // Vue {_uid: 3, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
            console.log(this)

            var f =()=>{
                // Vue {_uid: 3, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
                console.log(this)
            }

            f()
        }
    }
})


app.in_filter()

16. 事件修饰符

事件修饰符释义
.stop只处理自己的事件,父控件冒泡的事件不处理(阻止事件冒泡)
.self只处理自己的事件,子控件冒泡的事件不处理
.prevent阻止a链接的跳转
.once事件只会触发一次(适用于抽奖页面)
使用修饰符时,顺序很重要.相应的代码会以同样的顺序产生

 v-on:click.prevent.self 会阻止所有的点击
 v-on:click.self.prevent 只会阻止对元素自身的点击
16.1 冒泡
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>事件冒泡</title>
    <script src="Vue.js"></script>
</head>
<body>

<div id="d1">
        <ul @click="clickA('父控件')">
        父控件
        <li @click="clickA('子控件1')">子控件1</li>
        <li @click="clickA('子控件2')">子控件2</li>
        <li @click="clickA('子控件3')">子控件3</li>
    </ul>
</div>
<!--定义Vue对象-->
<script>
    var app = new Vue({
        el: '#d1',
        methods: {
            clickA(name) {
                alert(`${name}被点击了`)
            }
        }
    })
</script>
</body>
</html>
子控件的事件触发之后, 父控件也被触发, 子控件在父控件的范围内. 这种情况被称之为冒泡.

GIF 2022-5-6 15-01-56

16.2 阻止冒泡
方式1: 在父控件中使用事件后加上.self, 父控件不会被子控件触发.
@click.self
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>事件冒泡</title>
    <script src="Vue.js"></script>
</head>
<body>

<div id="d1">
        <ul @click.self="clickA('父控件')">
        父控件
        <li @click="clickA('子控件1')">子控件1</li>
        <li @click="clickA('子控件2')">子控件2</li>
        <li @click="clickA('子控件3')">子控件3</li>
    </ul>
</div>
<!--定义Vue对象-->
<script>
    var app = new Vue({
        el: '#d1',
        methods: {
            clickA(name) {
                alert(`${name}被点击了`)
            }
        }
    })
</script>
</body>
</html>

GIF 2022-5-6 15-05-13

方式2: 为子控件单独加上阻止事件冒泡.
@click.stop
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>事件冒泡</title>
    <script src="Vue.js"></script>
</head>
<body>

<div id="d1">
    <ul @click="clickA('父控件')">
        父控件
        <li @click.stop="clickA('子控件1')">子控件1</li>
        <li @click="clickA('子控件2')">子控件2</li>
        <li @click="clickA('子控件3')">子控件3</li>
    </ul>
</div>
<!--定义Vue对象-->
<script>
    var app = new Vue({
        el: '#d1',
        methods: {
            clickA(name) {
                alert(`${name}被点击了`)
            }
        }
    })
</script>
</body>
</html>

GIF 2022-5-6 15-08-46

16.3 阻止网页跳转
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>网页跳转</title>
    <script src="Vue.js"></script>
</head>
<body>

<div id="d1">
    <a href="https://www.baidu.com">会员入口</a>
</div>
</body>
</html>

GIF 2022-5-6 15-12-01

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>网页跳转</title>
    <script src="Vue.js"></script>
</head>
<body>

<div id="d1">
    <a href="https://www.baidu.com" @click.prevent="clickA">会员入口</a>
</div>
<!--定义Vue对象-->
<script>
    var app = new Vue({
        el: '#d1',
        methods: {
            clickA() {
                alert('网页不跳转')
            }
        }
    })
</script>
</body>
</html>
网页不跳转

GIF 2022-5-6 15-14-51

vue的代码在前端是看不见的可以在函数中定义一些方法, 控件网页的跳转.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>网页跳转</title>
    <script src="Vue.js"></script>
</head>
<body>

<div id="d1">
    <a href="https://www.baidu.com" @click.prevent="clickA">会员入口</a>
</div>
<!--定义Vue对象-->
<script>
    var app = new Vue({
        el: '#d1',
        methods: {
            clickA() {
                alert('30s会员体验')
                // 控制网页的跳转
                location.href='https://www.baidu.com'
            }
        }
    })
</script>
</body>
</html>

GIF 2022-5-6 15-23-11

16.4 只触发一次
事件只会触发一次(适用于抽奖页面)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>商品秒杀 </title>
    <script src="Vue.js"></script>
</head>
<body>

<div id="d1">
    <h1>限时秒杀活动</h1>
    <button @click.once="clickA">点击秒杀</button>

</div>
<!--定义Vue对象-->
<script>
    var app = new Vue({
        el: '#d1',
        methods: {
            clickA() {
                alert('秒杀成功!')
            }
        }
    })
</script>
</body>
</html>

GIF 2022-5-6 15-27-52

17. 按键修饰符

修饰符释义
.keyup按键被按下后弹起时触发一次.
.keydown按键被按下后时触发(长按不弹起会连续触发)
.keyup.部分按键名指定某个按键被按下后弹起触发一次.
部分按键名:
.alt
.ctrl
.delete
.dowm
.enter
.esc
.exact
.left
.meta
.right
.shift
.space
.tab
.up
.capture
$event,可以获取到该事件的事件对象.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>按键触发</title>
    <script src="Vue.js"></script>
</head>
<body>

<div id="d1">
    输入框:<input type="text" @keyup="clickA($event)">
</div>
<!--定义Vue对象-->
<script>
    var app = new Vue({
        el: '#d1',
        methods: {
            clickA(event) {
                console.log(event)
            }
        }
    })
</script>
</body>
</html>

image-20220506155906767

按下的键被存放在key属性中.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>按键</title>
    <script src="Vue.js"></script>
</head>
<body>

<div id="d1">
    输入框:<input type="text" @keyup="clickA($event)">


</div>
<!--定义Vue对象-->
<script>
    var app = new Vue({
        el: '#d1',
        methods: {
            clickA(event) {
                console.log(`按键${event.key}被按下了`)
            }
        }
    })
</script>
</body>
</html>
通过对象.key取到被按下的按键.

image-20220506160737578

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>按键</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>

<div id="d1">
    输入框:<input type="text" @keyup.enter="clickA($event)">


</div>
<!--定义Vue对象-->
<script>
    var app = new Vue({
        el: '#d1',
        methods: {
            clickA(event) {
                console.log(`按键${event.key}被按下了`)
            }
        }
    })
</script>
</body>
</html>
指定按键按下弹起被触发.

image-20220506161909835

18. v-model双向绑定

v-model指令可以在表单 input、textarea以及select元素上创建双向数据绑定.
v-model原理其实是背后有两个操作:
v-bind绑定value属性的值,
v-on绑定input事件监听到函数中, 函数会获取最新的值赋值到绑定的属性.
18.1 选择框
radio的值为布尔类型值.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>选择框</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>

<div id="d1">
    <input type="checkbox" v-model="radio">我已阅读xx协议!
    <p>radio的值:{{radio}}</p>

</div>
<!--定义Vue对象-->
<script>
    var app = new Vue({
        el: '#d1',
        data: {
            radio: true
        }
    })
</script>
</body>
</html>

GIF 2022-5-6 16-46-06

18.2 单选框
单选框是单个值, 可以是字符串可以是数字.
在选中值的时候, 会修改js变量的值为value设置的值.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>单选框</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>

<div id="d1">
    <input type="radio" v-model="radio" value=1><input type="radio" v-model="radio" value=2><input type="radio" v-model="radio" value=3>保密
    <p>你的选择:{{radio}}</p>
</div>
<!--定义Vue对象-->
<script>
    var app = new Vue({
        el: '#d1',
        data: {
            radio: 3
        }
    })
</script>
</body>
</html>

GIF 2022-5-6 16-55-58

18.3 多选框
多选框的值是一个数组.
在选中值的时候, 会修改js变量的值为value设置的值.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>单选框</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>

<div id="d1">
    <input type="checkbox" v-model="radio" value=''><input type="checkbox" v-model="radio" value=''><input type="checkbox" v-model="radio" value=''><p>你的选择:{{radio}}</p>
</div>
<!--定义Vue对象-->
<script>
    var app = new Vue({
        el: '#d1',
        data: {
            radio: []
        }
    })
</script>
</body>
</html>

GIF 2022-5-6 17-03-12

如果定义的值不是数组,  选中后会变成布尔值, 其他的选框被一起选中.

GIF 2022-5-6 17-06-24

19. v-model进阶

以下修饰是为input输入框准备的. 装饰在v-model后面
修饰符释义
.lazy等待input框 失去焦点之后再变化
.number数字开头, 只保留数字, 后面的字母不保留. 字母开头, 都保留.
.trim去除首位的空格
19.1 lazy
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>lazy</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>

<div id="d1">
    <input type="text" v-model.lazy="text"> ---> {{text}}

</div>
<!--定义Vue对象-->
<script>
    var app = new Vue({
        el: '#d1',
        data: {
            text: ''
        }
    })
</script>
</body>
</html>
v-model双向绑定每次都直接更新, 这样太耗费资源, 使用lazylazy等待input框失去焦点之后再变化.

GIF 2022-5-6 17-21-22

19.2 number
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>number</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>

<div id="d1">
    <input type="text" v-model.number="text"> ---> {{text}}

</div>
<!--定义Vue对象-->
<script>
    var app = new Vue({
        el: '#d1',
        data: {
            text: ''
        }
    })
</script>
</body>
</html>
数字开头, 只保留数字, 后面的字母不保留. 字母开头,都保留

GIF 2022-5-6 17-24-25

19.3 trim
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>trim</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>

<div id="d1">
    <input type="text" v-model.trim="text"> ---> {{text}}

</div>
<!--定义Vue对象-->
<script>
    var app = new Vue({
        el: '#d1',
        data: {
            text: ''
        }
    })
</script>
</body>
</html>
去除首位的空格

GIF 2022-5-6 17-29-14

20. 购物车练习

20.1 添加商品
利用多选框 + 实现添加商品,计算价格.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>购物车练习1</title>
    <script src="js/vue.js"></script>

</head>
<body>

<div id="d1">
    <h1>购物车</h1>
    <table border="1px">
        <thead>
        <tr>
            <th>商品名称</th>
            <th>商品价格</th>
            <th>购买数量</th>
            <th>选中/取消</th>
        </tr>
        </thead>

        <tbody>
        <!--遍历将对象取出-->
        <tr v-for="obj in shopping_cart">
            <td>{{ obj.name }}</td>
            <td>{{ obj.price }}</td>
            <td>{{ obj.number }}</td>
            <!--多择框, 使用v-model 绑定值  :value设置值为当前对象, 在勾选的时候, 将当前对象添加到列表中-->
            <th><input type="checkbox" v-model="my_list" :value="obj"></th>
        </tr>
        </tbody>
    </table>
    <br>
    选中的商品清单:{{ my_list }}
    <br>
    <!--插值语法调用函数, 在修改双向绑定的值, 也会被重新渲染-->
    总价格: {{ TotalCost() }}
</div>
<!--定义Vue对象-->
<script>
    var app = new Vue({
        el: '#d1',
        data: {
            // 购物车展示的数据
            shopping_cart: [
                {name: '牙膏', price: 25, number: 2},
                {name: '牙刷', price: 4.5, number: 2},
                {name: '水杯', price: 6, number: 2},
                {name: '毛巾', price: 6.5, number: 2},
                {name: '洗发水', price: 35, number: 1},
                {name: '沐浴露', price: 65, number: 1},
            ],

            // 多选择款存储的值, 需要是一个数组
            my_list: []
        },
        methods: {
            // 定义一个函数 返回计算好之后的清单的总价格
            TotalCost() {
                var money = 0
                // js 代码遍历列表得到的是一个索引
                for (i in this.my_list) {
                    // 通过索引拿到对象
                    obj = this.my_list[i]

                    // += 价格 * 数量
                    money += obj.price * obj.number

                }
			   // 将清单价格返回
                return money
            }
        }
    })
</script>
</body>
</html>

GIF 2022-5-6 22-35-57

20.2 全选
设计一个全选/取消全选的 选项
核心代码:(修改my_list的值)
if(this.all_check){
    // 将shopping_cart的值直接赋值给my_list, 就实现了全选
    this.my_list = this.shopping_cart
    // my_list的值为空类别就取消去选了
}else{
    this.my_list = []
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>购物车练习2</title>
    <script src="js/vue.js"></script>

</head>
<body>

<div id="d1">
    <h1>购物车</h1>
    <table border="1px">
        <thead>
        <tr>
            <th>商品名称</th>
            <th>商品价格</th>
            <th>购买数量</th>
            <th>选中/取消</th>
        </tr>
        </thead>

        <tbody>
        <!--遍历将对象取出-->
        <tr v-for="obj in shopping_cart">
            <td>{{ obj.name }}</td>
            <td>{{ obj.price }}</td>
            <td>{{ obj.number }}</td>
            <!--多择框, 使用v-model 绑定值  :value设置值为当前对象, 在勾选的时候, 将当前对象添加到列表中-->
            <th><input type="checkbox" v-model="my_list" :value="obj"></th>
        </tr>
        <tr>
            <!-- colspan="3"水平占三格  align="center" 居中 -->
            <td colspan="3" align="center">全选/全不选</td>
            <!--单选 使用v-model 绑定值, 绑定一个文本变化事件, -->
            <td align="center"><input type="checkbox" v-model="all_check" @change="select_all"></td>
        </tr>
        </tbody>
    </table>
    <br>
    是否全选: {{all_check}}
    <br>
    选中的商品清单:{{ my_list }}
    <br>
    <!--插值语法调用函数, 在修改双向绑定的值, 也会被重新渲染-->
    总价格: {{ TotalCost() }}
</div>
<!--定义Vue对象-->
<script>
    var app = new Vue({
        el: '#d1',
        data: {
            // 购物车展示的数据
            shopping_cart: [
                {name: '牙膏', price: 25, number: 2},
                {name: '牙刷', price: 4.5, number: 2},
                {name: '水杯', price: 6, number: 2},
                {name: '毛巾', price: 6.5, number: 2},
                {name: '洗发水', price: 35, number: 1},
                {name: '沐浴露', price: 65, number: 1},
            ],

            // 多选择款存储的值, 需要是一个数组
            my_list: [],

            // 单选框的值true或false 默认不全选为false
            all_check: false,
        },
        methods: {
            // 定义一个函数 返回计算好之后的清单的总价格
            TotalCost() {
                var money = 0
                // js 代码遍历列表得到的是一个索引
                for (i in this.my_list) {
                    // 通过索引拿到对象
                    obj = this.my_list[i]

                    // += 价格 * 数量
                    money += obj.price * obj.number

                }
			   // 将清单价格返回
                return money
            },

            // 点击全选/取消全选触发的函数
            select_all(){
                if(this.all_check){
                    // 将shopping_cart的值直接赋值给my_list, 就实现了全选
                    this.my_list = this.shopping_cart

                    // my_list的值为空类别就取消去选了
                }else{
                    this.my_list = []
                }
            }
        }
    })
</script>
</body>
</html>

GIF 2022-5-6 23-55-57

现在完成了一半了, 
    1. 全选后, 在单独取消, 取消全选.
    2. 手动一个个选中, 变成全选.
核心代码:(改变this.all_check的值)
// 手动选择触发全选/取消全选
Manual_trigger() {
    // 判断my_list的列表长度是都等于shopping_cart的长度, 长度一样则全选, 否则取消全选
    if (this.my_list.length === this.shopping_cart.length){
        this.all_check = true
    } else {
        this.all_check = false
    }
}
使用三目运算简化代码:
// 条件成功this.all_check的值为true, 否则为false
this.all_check = (this.my_list.length === this.shopping_cart.length)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>按键触发</title>
    <script src="js/vue.js"></script>

</head>
<body>

<div id="d1">
    <h1>购物车</h1>
    <table border="1px">
        <thead>
        <tr>
            <th>商品名称</th>
            <th>商品价格</th>
            <th>购买数量</th>
            <th>选中/取消</th>
        </tr>
        </thead>

        <tbody>
        <!--遍历将对象取出-->
        <tr v-for="obj in shopping_cart">
            <td>{{ obj.name }}</td>
            <td>{{ obj.price }}</td>
            <td>{{ obj.number }}</td>
            <!--多择框, 使用v-model 绑定值  :value设置值为当前对象, 在勾选的时候, 将当前对象添加到列表中-->
            <th><input type="checkbox" v-model="my_list" :value="obj" @change="Manual_trigger"></th>
        </tr>
        <tr>
            <!-- colspan="3"水平占三格  align="center" 居中 -->
            <td colspan="3" align="center">全选/全不选</td>
            <!--单选 使用v-model 绑定值, 绑定一个文本变化事件, -->
            <td align="center"><input type="checkbox" v-model="all_check" @change="select_all"></td>
        </tr>
        </tbody>
    </table>
    <br>
    是否全选: {{all_check}}
    <br>
    选中的商品清单:{{ my_list }}
    <br>
    <!--插值语法调用函数, 在修改双向绑定的值, 也会被重新渲染-->
    总价格: {{ TotalCost() }}
</div>
<!--定义Vue对象-->
<script>
    var app = new Vue({
        el: '#d1',
        data: {
            // 购物车展示的数据
            shopping_cart: [
                {name: '牙膏', price: 25, number: 2},
                {name: '牙刷', price: 4.5, number: 2},
                {name: '水杯', price: 6, number: 2},
                {name: '毛巾', price: 6.5, number: 2},
                {name: '洗发水', price: 35, number: 1},
                {name: '沐浴露', price: 65, number: 1},
            ],

            // 多选择款存储的值, 需要是一个数组
            my_list: [],

            // 单选框的值true或false 默认不全选为false
            all_check: false,
        },
        methods: {
            // 定义一个函数 返回计算好之后的清单的总价格
            TotalCost() {
                var money = 0
                // js 代码遍历列表得到的是一个索引
                for (i in this.my_list) {
                    // 通过索引拿到对象
                    obj = this.my_list[i]

                    // += 价格 * 数量
                    money += obj.price * obj.number

                }
                // 将清单价格返回
                return money
            },

            // 点击全选/取消全选触发的函数
            select_all() {
                if (this.all_check) {
                    // 将shopping_cart的值直接赋值给my_list, 就实现了全选
                    this.my_list = this.shopping_cart

                    // my_list的值为空类别就取消去选了
                } else {
                    this.my_list = []
                }
            },

            // 手动选择触发全选/取消全选
            Manual_trigger() {
                // 判断my_list的列表长度是都等于shopping_cart的长度, 长度一样则全选, 否则取消全选

                // 方式1
                // if (this.my_list.length === this.shopping_cart.length){
                //     this.all_check = true
                // } else {
                //     this.all_check = false
                // }


                // 方式2 条件成功this.all_check的值为true, 否则为false
                this.all_check = (this.my_list.length === this.shopping_cart.length)
            }
        }
    })
</script>
</body>
</html>

GIF 2022-5-7 0-08-44

20.3 商品数量的加减
在购买数量的表单内添加 - +两个按键.
+ 没有上限, -不能最少为1.
核心代码:
<td>
    <!--写一个函数, 值大于1自减, 并限制值最小为1-->
    <button @click="count(obj)">-</button> 
    {{ obj.number }} 
    <!--属性指令直接自增-->
    <button @click="obj.number++">+</button>
</td>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>按键触发</title>
    <script src="js/vue.js"></script>

</head>
<body>

<div id="d1">
    <h1>购物车</h1>
    <table border="1px">
        <thead>
        <tr>
            <th>商品名称</th>
            <th>商品价格</th>
            <th>购买数量</th>
            <th>选中/取消</th>
        </tr>
        </thead>

        <tbody>
        <!--遍历将对象取出-->
        <tr v-for="obj in shopping_cart">
            <td>{{ obj.name }}</td>
            <td>{{ obj.price }}</td>
            <td> <button @click="count(obj)">-</button> {{ obj.number }} <button @click="obj.number++">+</button> </td>
            <!--多择框, 使用v-model 绑定值  :value设置值为当前对象, 在勾选的时候, 将当前对象添加到列表中-->
            <th><input type="checkbox" v-model="my_list" :value="obj" @change="Manual_trigger"></th>
        </tr>
        <tr>
            <!-- colspan="3"水平占三格  align="center" 居中 -->
            <td colspan="3" align="center">全选/全不选</td>
            <!--单选 使用v-model 绑定值, 绑定一个文本变化事件, -->
            <td align="center"><input type="checkbox" v-model="all_check" @change="select_all"></td>
        </tr>
        </tbody>
    </table>
    <br>
    是否全选: {{all_check}}
    <br>
    选中的商品清单:{{ my_list }}
    <br>
    <!--插值语法调用函数, 在修改双向绑定的值, 也会被重新渲染-->
    总价格: {{ TotalCost() }}
</div>
<!--定义Vue对象-->
<script>
    var app = new Vue({
        el: '#d1',
        data: {
            // 购物车展示的数据
            shopping_cart: [
                {name: '牙膏', price: 25, number: 2},
                {name: '牙刷', price: 4.5, number: 2},
                {name: '水杯', price: 6, number: 2},
                {name: '毛巾', price: 6.5, number: 2},
                {name: '洗发水', price: 35, number: 1},
                {name: '沐浴露', price: 65, number: 1},
            ],

            // 多选择款存储的值, 需要是一个数组
            my_list: [],

            // 单选框的值true或false 默认不全选为false
            all_check: false,
        },
        methods: {
            // 定义一个函数 返回计算好之后的清单的总价格
            TotalCost() {
                var money = 0
                // js 代码遍历列表得到的是一个索引
                for (i in this.my_list) {
                    // 通过索引拿到对象
                    obj = this.my_list[i]

                    // += 价格 * 数量
                    money += obj.price * obj.number

                }
                // 将清单价格返回
                return money
            },

            // 点击全选/取消全选触发的函数
            select_all() {
                if (this.all_check) {
                    // 将shopping_cart的值直接赋值给my_list, 就实现了全选
                    this.my_list = this.shopping_cart

                    // my_list的值为空类别就取消去选了
                } else {
                    this.my_list = []
                }
            },

            // 手动选择触发全选/取消全选
            Manual_trigger() {
                // 判断my_list的列表长度是都等于shopping_cart的长度, 长度一样则全选, 否则取消全选
                // 方式2 条件成功this.all_check的值为true, 否则为false
                this.all_check = (this.my_list.length === this.shopping_cart.length)
            },

            // 购买数量-
            count(obj){
                if (obj.number === 1){
                    alert('不能再少了')
                }else{
                    obj.number--
                }
            }
        }
    })
</script>
</body>
</html>

GIF 2022-5-7 0-41-25

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值