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 全局定义自定义指令

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

假以时日♪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值