IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> VUE2.x -> 正文阅读

[JavaScript知识库]VUE2.x

一. VUE介绍

介绍 — Vue.js

概念

????????一个动态构建用户界面的 渐进式 JS框架. 遵循MVVM模式

????????主流三大框架

????????????????VUE React Angular

????????动态构建用户界面(数据 -> 界面)

????????渐进式(自底向上慢慢改进)

????????MVVM模式(面试)

????????????????实现 数据 与 视图 的双向绑定

????????????????Model(数据模型)

????????????????View(视图)

????????????????VM(View Model控制器)

链接

????????官网 Vue.js - 渐进式 JavaScript 框架 | Vue.js

????????V2文档 介绍 — Vue.js

????????V3文档 简介 | Vue.js

优点

????????Angular的模板语法和数据绑定

????????React的组件化和虚拟DOM

特点

????????声明式渲染(声明式地描述最终输出的 HTML 和 JavaScript 状态间的关系)

????????????????变量:保存数据

????????????????函数:操作数据

????????响应式(即 数据驱动)

????????????????在数据改变时响应式地更新 DOM

????????????????数据改变时,DOM视图会随之更改

????????组件化开发(拼积木)

二. 快速开始

安装配置

????????卸载后要手动删掉nodemodules包

????????新建目录

????????初始化 npm init -y

????????安装2.x版本

????????????????在线版 CDN

????????????????下载版 npm i vue@2 vue - npm

vue三步曲

????????1. 引入vue.js

????????2. 编写页面容器

????????3. 创建vue实例

????????????????this:方法的this指向对应的实例

????????????????????????看this指向谁 = 看实例是谁

????????????????????????button.click 指向button

????????????????????????vm.handleClick 指向 vm

三、VUE实例

VUE选项

????????vue3 组合式api

????????vue2 选项式api(构造函数选项)

????????????????el

????????????????data 定义数据

????????????????methods 方法(改变数据)

????????Vue构造函数创建vue实例

????????????????1. data中声明的变量会挂载到vm实例上,作为vm的属性

????????????????2. methods中声明的函数会挂载到vm实例上,作为vm的方法

四、MVVM模型

MVVM

????????数据,视图,ViewModel

????????核心思想:双向绑定

????????????????数据改变 影响 视图

????????????????视图改变 影响 数据

五、模板语法

简介

vm.$mount("#app")

????????编译模板,挂载(使用模板生成的DOM,替换旧的DOM节点)

innerHtml 与 outerHtml

模板:由vue解析的HTML字符串内容

????????如何确定模板(理解)

????????????????1. el选项:指定容器作为模板

????????????????2. template选项:指定模板

????????????????3. render函数选项(渲染函数):指定模板

????????????????优先级:render函数 > template > el

????????vue工作流程(理解)

????????????????1. 编译模板

????????????????2. 挂载

分类 (插值 指令)

插值语法

????????主要用于文本节点

????????语法 {{}}

????????插值表达式

????????????????1. 是个js表达式

????????????????2. 写什么(vm实例上的属性和方法)

指定语法

????????语法 v-

????????属性节点

????????指令表达式

with语法

????????人为改变this指向

????????this指向window,但可以直接获取obj中的成员,不需要this.成员

????????with (obj) { }

const obj = { name: 'xiaoming' }

function test() {
  with (obj) {
    console.log(name)   // 'xiaoming'
  }
}
test()

常用指令

单向绑定????????v-bind :

样式绑定???????? :class='' :style=''

双向绑定???????? v-model

原始html????????v-html="content"

方法绑定???????? v-on:click='' @click=''

条件渲染???????? v-if='布尔值/变量'

列表渲染???????? v-for='(value, index) in obj' ????????:key='唯一值(id)'

属性绑定 :

????????将DOM元素的属性和vue中的状态绑定

语法

? ?v-bind:href="url"

????????简写(常用):href="url"

????????指令(属性名)=指令表达式(属性值)

????????????????1. 可以是基本数据 30 '30' true

????????????????2. 可以是vm上的属性和方法

????????????????3. 有效的 js表达式

事件绑定 @

语法

????????v-on:click='handleClick'

????????简写 @事件名='表达式'

表达式

????????不加括号(70%)

????????加括号(20%)目的:为了传参

????????加括号,使用$event(10%)

????????????????目的:传参同时传事件对象

????????????????@click="add(3, $event)"
????????????????add(n, e) { }

注意点

????????1. methods 中不要用箭头函数(不绑定this)(普通函数中this指向vm)

????????2. methosd 定义的函数不能和 data的变量同名。所以加个handle或get以避免同名

事件修饰符 可连写

????????.stop 阻止冒泡

????????.prevent 阻止默认行为

????????.once 事件只可执行一次

按键修饰符

????????.enter

????????.tab

????????.delete (捕获“删除”和“退格”键)

????????.esc

????????.space

????????.up

????????.down

????????.left

????????.right

????????键盘的左右 与鼠标的左右

????????系统按键 .ctrl .alt .shift .meta <input @keyup.alt.enter="clear" />

????????.exact 修饰符允许你控制由精确的系统修饰符组合触发的事件。

????????鼠标 .left .right .middle

双向绑定 v-model

语法

????????v-model="变量"

修饰符

????????.lazy

????????????????类似防抖

????????????????数据全部输入完(失焦)后,改变一次

????????.number

????????????????转换为数字类型

????????.trim

????????????????去除首尾空格

应用 (表单)🟢

1. 文本:text, password

????????绑定value属性

????????监听input事件

2. 单选/复选框

????????绑定checked属性

????????监听input事件

3. 下拉框

????????监听change事件

????????绑定option对应的value属性

<script>
  const vm = new Vue({
    el: '#app',
    data: {
      name: '',
      password: '',
      age: 0,
      gender: '男',
      hobbies: ['sleep'], // 多选框跟一个数组绑定
      city: '',
      sign: '1111',
      test: 'abc',
    },
  })
</script>
<!--
  1. 数据的改变 影响 视图
  2. 视图的改变 影响 数据
-->

<!-- v-model应用于表单元素(input, select, textarea)
  1. input和textarea: 绑定value属性, 监听input事件
  2. checkbox radio: 绑定checked属性, 监听change事件
  3. select: 绑定value属性, 监听change事件
-->
<div id="app">
  用户名: <input type="text" v-model.trim.lazy="name" /> <br />
  密码: <input type="password" v-model="password" /> <br />
  年龄: <input type="text" v-model.number="age" /> <br />

  <!-- 一对单选框需要使用v-model绑定到同一个状态 
  v-model在单选框中, 跟checked属性绑定的. 具体的值还是要通过value指定
  -->
  性别: <input type="radio" id="male" v-model="gender" value="男" />
  <label for="male">男</label>
  <input type="radio" id="female" v-model="gender" value="女" />
  <label for="female">女</label> <br />
  爱好:
  <input type="checkbox" id="eat" v-model="hobbies" value="eat" />
  <label for="eat">吃饭</label>
  <input type="checkbox" id="sleep" v-model="hobbies" value="sleep" />
  <label for="sleep">睡觉</label> <br />
  城市:
  <!-- 下拉框: 
  1. 没有指定option的value属性, 使用option中的文本做为值
  2. 指定option的value属性, 使用value属性值做为数据(更推荐这种写法)
  -->
  <select v-model="city">
    <!-- value为'', 跟初始值一致, 为了默认选中 -->
    <option value="" disabled>请选择</option>
    <option value="wuhan">武汉</option>
    <option value="beijing">北京</option>
    <option value="shanghai">上海</option>
  </select>
  <br />
  个人签名: <textarea v-model="sign"></textarea>
</div>

注意点

1. 单选

????????同一级单选按钮,绑定同一个属性名

????????通过value指定绑定的属性值

2. 复选

????????单个复选框 绑定一个布尔值

????????多个复选框(一组) 绑定同一个属性名(数组或集合set)

????????通过value指定绑定的属性值

3. 下拉框

????????没有指定option的value,使用option中的文本作属性值

????????指定option的value,使用value做属性值

????????常用法: value="" diabled

????????通过变量值与value匹配来指定默认选项

4. 文本域

????????使用v-model实现双向绑定

????????不能使用{{}}语法 :单向(数据 -> 视图)

条件渲染 v-if v-show

定义

????????当指令表达式的返回值为真,渲染DOM

语法

????????v-if v-else-if v-else

????????????????有更高切换开销

????????????????需要实现逻辑时用

????????v-show

????????????????有更高初始渲染开销

????????????????需要频繁切换显示时用

注意事项

  • v-if 可以跟 v-else,v-else-if 配合使用
  • 如果同时切换渲染多个元素,可在外层使用 <template v-if="flag">
  • 取反 !flag

1. 当条件为真, v-if 和v-show没有区别

2. 当条件为假, v-if 不会创建DOM, v-show通过css的display属性隐藏

<div id="app">
  <div v-if="flag2">通过v-if渲染</div>
  <div v-else-if="flag">v-else-if</div>
  <div v-else>通过v-else渲染</div>

  <div v-show="flag">通过v-show渲染</div>
</div>

<script>
  const vm = new Vue({
    el: '#app',
    data: {
      flag: true,
      flag2: false,
    },
  })
</script>

列表渲染 v-for

遍历语句

  • for...of 多用于数组
  • for...in 多用于对象

定义

????????循环遍历数组或对象,渲染多个元素

语法

????????数组

????????????????v-for="item in items"

????????????????????????获取元素

????????????????v-for="(item, index) in items"

????????????????????????获取元素和索引

????????对象

????????????????v-for="value in obj"

????????????????????????获取对象的值列表

????????????????v-for="(value, key) in obj"

????????????????????????值列表/键列表

????????????????v-for="(value, key, index) in items"

????????????????????????值列表/键列表/索引

key

????????定义: 虚拟DOM中表示

????????作用: 在更新数据时,依据key来对比新旧DOM,提高对比的效率

????????应用

????????????????在渲染列表时绑定唯一标识

????????????????数据不会更改(不增删打乱原序)时,可以使用index索引做key

注意

????????????????v-for不要与v-if在同一元素连用,如果需要,可以在v-if外面套一层<template v-for"todo in todos">

<!-- 遍历数组 -->
<li v-for="item in items">{{item}}</li>
<li v-for="(item, index) in items">
  {{index}}-{{item}}
</li>

<!-- 遍历对象 -->
<ul>
  <li v-for="value in obj">{{value}}</li>
  <li v-for="(value, key) in obj">
    {{key}}-{{value}}
  </li>
  <li v-for="(value, key, index) in obj">
    {{index}}-{{key}}-{{value}}
  </li>
</ul>

<!-- 嵌套遍历 -->
<tr v-for="stu in stus">
  <td v-for="item in stu">{{item}}</td>
</tr>

<script>
const vm = new Vue({
  el: '#app',
  data: {
    // 数组名称一般使用名词的复数形式
    items: ['test1', 'test2', 'test3'],
    obj: {
      name: '小明',
      age: 20,
    },
    stus: [
      { id: 1, name: 'xiaoming', age: 20 },
      { id: 2, name: 'xiaomei', age: 18 },
      { id: 3, name: 'xiaopang', age: 2 },
    ],
  },
})
</script>

v-if 与 v-for 在vue2和vue3中的不同

  • 在vue3中, v-if有更高的优先级
  • 在vue2中, v-for有更高的优先级

样式绑定 :class :style

绑定class属性

????????对象

????????????????<span :class="obj"></span>

????????obj: { red: true }

????????数组(推荐)

????????????????<span :class="arr"></span>

????????????????arr: ['red', 'blue']

绑定style属性

????????<span :style="obj">

????????obj: {

????????color: 'blue',

????????// 小驼峰/加引号

????????fontSize: '40px',

????????'font-size': '40px'

????????}

    <style>
      .red {
        color: red;
      }
      .blue {
        color: blue;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <div :class="str">绑定字符串</div>
      <div :class="arr">绑定数组</div>
      <div :class="flag?'red':'blue'">绑定表达式</div>
      <div :class="obj">绑定对象</div>
      
      <div :style="styleObj">绑定对象</div>
    </div>
    <script>
      const vm = new Vue({
        el: '#app',
        data: {
          str: 'red',
          arr: ['red', 'blue'],
          flag: true,
          obj: {
            red: true,
            blue: true,
          },
          styleObj: {
            color: 'white',
            // css中如果存在-, 要加''
            'font-size': '100px', 
            // 也可以使用小驼峰法书写
            backgroundColor: 'skyblue', 
          },
        },
      })
    </script>
  </body>

样式绑定案例:京东tab栏🟢

css 优先级

样式绑定的三种写法

  • 直接在行内三元运算符(结构条理比较清晰)
  • 对象(在开源中较流行)
  • 数组
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <!-- 
      一. vue三步曲
      二. 编写静态页面(HTML+CSS)
      三. 编写逻辑(JS)
    -->
    <script src="../node_modules/vue/dist/vue.js"></script>
    <style>
      /* 初始化 重置样式 */
      * {
        margin: 0;
        padding: 0;
      }
      li {
        list-style: none;
      }
      /* 功能 */
      .tab {
        /* 居中的效果 */
        margin: 50px auto;
        width: 700px;
        height: 40px;
        min-width: 700px;
        /* 盒子模型 */
        border: 1px solid #eee;
        border-bottom: 1px solid #e4393c;

        background-color: #f7f7f7;
        box-sizing: border-box;
      }
      .tab-list {
        display: flex;
        height: 100%;
      }
      .tab-list .tab-item {
        /* flex: 作为tab-list的子元素, 平分剩余空间 */
        flex: 1;
        /* 控制子元素(水平垂直居中) */
        display: flex;
        justify-content: center;
        align-items: center;

        color: #666;
        cursor: pointer;
      }
      .tab-item:nth-of-type(4) {
        /* 设置第4个li元素的最小宽度 */
        flex-basis: 120px;
      }
      .tab-item:hover {
        color: #e4393c;
      }
      /* .tab-item.active 不能加空格. 表示同时选中*/
      .tab-list .current {
        color: #fff;
        background-color: #e4393c;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <!-- 2.1 静态页面结构 -->
      <div class="tab">
        <ul class="tab-list">
          <!-- <li
            v-for="(item,index) in items"
            @click="active = index"
            class="tab-item"
            :class="index == active ? 'current': ''" 
          > -->

          <!-- <li
            v-for="(item,index) in items"
            @click="active = index"
            :class="{'tab-item': true, current: index==active}"
          > -->
          <li
            v-for="(item,index) in items"
            @click="active = index"
            :class="['tab-item', index==active?'current': '']"
          >
            {{item}}
          </li>
        </ul>
      </div>
    </div>
    <script>
      const vm = new Vue({
        el: '#app',
        data: {
          items: [
            '商品介绍', '规格与包装', '售后保障', '商品评价(100万+)', '手机社区'
          ],
          active: 0,
        },
      })
    </script>
  </body>
</html>

六. 计算属性与侦听器

6.1 计算属性 computed

概念

????????是基于现有属性计算后的属性

作用

????????对原始数据进行加工,返回加工结果

????????????????复杂的内容运算尽量写在computed中

????????????????多因一果

????????????????优先于侦听

特点

????????有缓存

????????调试方便

<div id="app">
  <h3>使用计算属性: {{computedMsg}}</h3>
</div>
<script>
  const vm = new Vue({
    el: '#app',
    computed: {
      // 计算属性名: 函数(求计算属性的值)
      computedMsg() {
        // 该函数的返回值, 做为访问计算属性的结果
        return this.msg.split('').reverse().join('')
      },
  }})

扩展 ( get set方法 ) ?

应用: get监听全选与否(arr.every), set进行全选与否动作

6.2 侦听器

特点

  • 在watch对应的回调函数中, 可以获取到新值旧值

作用

  • 监听vm实例上的属性,属性变化时,调用设置的回调

使用

  • 侦听的属性(vm上已经存在的属性):回调函数
  • 一因多果
    • 关注一个已经存在的属性,变化时执行回调,可以获取到改变前后的新旧值

参数

  • deep: true

????????????????深度监听的开启

????????????????vue2默认不开启深度侦听,vue3默认开启

  • immediate: true

????????????????开始侦听后立即调用一次

得到更新后的DOM

//得到更新后的DOM
this.$nextTick(function () {
  console.log('dom新:', app.innerHTML);
});
<!-- 侦听器, 监听vm实例上的属性, 当属性变化时, 调用设置的回调 -->
<!-- 侦听器: 一因多果 -->
<div id="app">
  姓: 
  <input type="text" v-model="lastName" /> 
  <br />
  名: 
  <input type="text" v-model="firstName" />
  <br />
  全名(使用watch实现): {{fullName}}
</div>
<script>
  // 1. 默认是浅层次的侦听(只会侦听data中第一层数据的变化)
  // 2. 如果希望深层次侦听, 需要设置deep: true这个选项
  //    如果侦听对象(引用)类型, 是不能获取旧值
  const vm = new Vue({
    el: '#app',
    data: {
      lastName: '',
      firstName: '',
      fullName: '',
      obj: {
        a: {
          b: {
            c: '1',
          },
        },
      },
    },
    watch: {
      // 在侦听的回调中可以得到新值和旧值
      // 侦听的属性(vm上已经存在的属性): 回调函数
      lastName(newValue, oldValue) {
        console.log('更新之后: ', newValue)
        console.log('更新之前: ', oldValue)
        this.fullName = this.lastName + this.firstName
      },
      firstName() {
        this.fullName = this.lastName + this.firstName
      },
      // obj() {
      //   console.log('只有当obj重新赋值时, 才会被侦听到')
      // },
      // watch 对象语法
      obj: {
        deep: true, // 开启深度侦听
        immediate: true, // 在侦听时立即执行回调函数
        handler: function (newValue, oldValue) {
          console.log('更新之前', oldValue)
          console.log('更新之后', newValue)
          // 通过handler指定回调
          console.log(
            '开启深度侦听, 不管多少层, 只要数据变化, 都可以被侦听到...'
          )
        },
      },
    },
  })
</script>

?$nextTick 数据异步更新

  • watch的回调在DOM更新之前执行, 在回调中得到的是旧的DOM
  • 如果需要得到更新之后的DOM, 使用 $nextTick
<div id="app">{{msg}}</div>
<script>
  const vm = new Vue({
    el: '#app',
    data: {
      msg: 'hello',
    },
    watch: {
      msg() {
        // watch回调在DOM更新前执行,回调中得到的是旧DOM

        // 使用$nextTick得到更新之后的DOM
        this.$nextTick(function () {
          // 注册的该函数会在DOM更新之后执行
          console.log(app.innerHTML)
        })
      },
    },
  })
</script>

6.3 计算属性与侦听器 区别

是否会在vm实例中挂载新属性

????????????????computed会

????????????????watch不会

对应关系

????????????????computed是多对一, 可以同时监听多个值改变, 最终计算得到一个新的属性

????????????????watch是一对多, 主要监听一个属性的变化, 执行多种逻辑

能否获取新旧值?

????????????????computed不能

????????????????watch能

6.4 过滤器

概念

????????用于对数据格式化的 一个 函数

语法

????????{{ 表达式 | 过滤器1 | 过滤器2 ...}}

分类

  • 全局过滤器
  • 局部过滤器

其它

????????vue3去掉了

????????????????用一个带参数的计算属性来替代

????????对数据格式化的一个函数

<div id="app">{{ price | formatPrice }}</div>
<script>
  // 全局过滤器(就是一个函数)
  // Vue.filter('formatPrice', function (price) {
  //   return '¥' + price.toFixed(2)
  // })
  // Vue.filter('test', function (value) {
  //   return value + '元'
  // })

  // 局部过滤器
  const vm = new Vue({
    el: '#app',
    data: {
      price: 90,
    },
    filters: {
      formatPrice: function (price) {
        return '¥' + price.toFixed(2) + '元'
      },
    },
  })
</script>

? defineProperty?

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <!-- defineProperty: ES5就支持 -->
    <script>
      // defineProperty: 定义属性

      const obj = {}

      let value
      // 第一个参数: 要操作的对象
      // 第二个参数: 要添加的属性
      // 第三个参数: 描述符对象
      Object.defineProperty(obj, 'msg', {
        // 自定义msg的访问和设置过程
        get: function () {
          // 当访问msg属性时, 会执行该函数, 返回值做为msg的属性值
          console.log('获取msg的值:', value)
          return value
        },
        set: function (newValue) {
          // 当设置msg属性时, 会执行该函数
          console.log('设置msg的值: ', newValue)
          value = newValue
        },
      })

      obj.msg = 200
      console.log(obj.msg)
    </script>
  </body>
</html>

? 封装一个函数?

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">hello</div>
    <script>
      // 定义响应式
      function defineReactive(target, key, value) {
        Object.defineProperty(target, key, {
          get: function () {
            return value
          },
          set: function (newValue) {
            value = newValue
            // 重新渲染页面 (执行render函数)
            app.innerHTML = newValue
          },
        })
      }

      function Vue(options) {
        // 1. 数据劫持(将data中的原始对象->转换成响应式对象)
        // 响应式对象: 自定义getter和setter
        const keys = Object.keys(options.data)
        keys.forEach((key) => {
          // 重新定义data上属性, 添加getter和setter
          defineReactive(options.data, key, options.data[key])
        })

        console.log(options.data)
        // 添加到this上, 叫_data(响应式对象)
        this._data = options.data

        // 2. 数据代理
        keys.forEach((key) => {
          defineReactive(this, key, this._data[key])
        })
      }

      const vm = new Vue({
        data: {
          msg: 'hello',
          name: 'xiaoming',
        },
      })

      console.log(vm)
      // vm._data.msg = 'world'
      // vm.msg = 'world'
    </script>
  </body>
</html>

? 组件/实例选项的顺序

1. 全局感知 (要求组件以外的知识)

  • name

2. 模板依赖 (模板内使用的资源)

  • components
  • filters

3. 接口 (组件的接口)

  • props/propsData

4. 本地状态 (本地的响应式 property)

  • data
  • computed

5. 事件 (通过响应式事件触发的回调)

  • watch
  • 生命周期钩子 (按照被调用的顺序)
    • beforeCreate
    • created
    • beforeMount
    • mounted
    • beforeUpdate
    • updated
    • beforeDestroy
    • destroyed

6. 非响应式的 property (不依赖响应系统的实例 property)

  • methods

购物车案例?

  • 表格边框样式
  • for,for of ,for in, forEach
    • for (let value of obj/arr)
    • for (let key in obj/arr)
    • arr.forEach( (value, index) =>{ } )
  • 数组方法:总金额: 数组.reduce()
  • js中小驼峰命名 和 下划线命名,哪个用的更多
  • 10:02 计算属性的缓存优点
  • 立即执行函数没有括号能运行吗
  • 价格格式化方法*3
    • <td>
      {{book.price | formatPrice}}
      </td>
    • <td>{{((p)=>{return '¥' + p.toFixed(2)})(book.price)}}</td>
    • <td>{{computedPrice(book.price)}}</td>
  • 为key绑定id
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Document</title>
  <script src="../node_modules/vue/dist/vue.js"></script>
  <!-- 
    一. vue的三步曲 
    二. 编写静态页面 
    三. 实现业务逻辑 
  -->
  <style>
    table,
    tr,
    th,
    td {
      border: 1px solid #ddd;
      border-collapse: collapse;
      border-spacing: 0;
    }
    .cart {
      min-width: 650px;
    }
    .cart caption {
      font-weight: 700;
    }
    .cart th {
      padding: 5px 20px;
      background-color: #f7f7f7;
      color: #666;
    }
    .cart td {
      padding: 5px 20px;
    }
    .cart .total {
      text-align: right;
    }
  </style>
</head>
<body>
<div id="app">
  <table class="cart">
    <caption>
      购物车
    </caption>
    <!-- 表头 -->
    <tr>
      <th v-for="listItem in listItems">{{listItem}}</th>
    </tr>
    <tr v-for="(book,index) in books" :key="book.id">
      <td>{{book.id}}</td>
      <td>{{book.name}}</td>
      <td>{{book.publish_date}}</td>
      <!-- 使用带返回值的计算属性 -->
      <td>{{computedPrice(book.price)}}</td>
      <td>
        <button @click="book.number>1 ? book.number-- : 1">-</button>
        {{book.number}}
        <button @click="book.number++">+</button>
      </td>
      <td>
        <button @click="books.splice(index, 1)">移除</button>
      </td>
    </tr>
    <tr v-if="books.length" class="total">
      <td colspan="6">总价格: {{total | format_price}}</td>
    </tr>
    <tr v-else>
      <td colspan="6">购物车中没有商品</td>
    </tr>
  </table>
</div>

<script>
  const vm = new Vue({
    el: '#app',
    filters: {
      format_price: function (price) {
        return '¥' + price.toFixed(2)
      },
    },
    data: {
      listItems: ['', '书籍名称', '出版日期', '价格', '购买数量', '操作'],
      books: [
        {
          id: 1,
          name: '算法导论',
          publish_date: '2006-09',
          price: 85,
          number: 5,
        },
        {
          id: 2,
          name: 'Unix编程艺术',
          publish_date: '2006-02',
          price: 59,
          number: 2,
        },
        {
          id: 3,
          name: '编程珠玑',
          publish_date: '2008-10',
          price: 39,
          number: 2,
        },
      ],
    },
    computed: {
      total() {
        // 总金额: 数组.reduce()
        let total = this.books.reduce((previous, current) => {
          previous += current.price * current.number
          return previous
        }, 0)
        return total
      },
      // 带参数的计算属性 (返回一个函数)
      computedPrice() {
        return (p) => {
          return '¥' + p.toFixed(2)
        }
      },
    },
  })
</script>
</body>
</html>

七. 自定义指令

概念

  • 指令是用来做dom操作的,如果vue现有的指令不能满足开发要求, 我们可以创建自定义指令 (directive )

自定义指令格式

  • vue实例内部定义 and 全局定义自定义指令

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-10-31 11:46:33  更:2022-10-31 11:48:18 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/17 15:58:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码