[TOC]

文本插值 - 双花括号

  • 先前文章中讨论的模板语法{{ }}吗? 这是数据绑定的基本形式,称为“文本插值”。
  • 可以使用伪指令v-once执行一次插值,尽管稍后会更新该属性的初始值。

    使用JavaScript 表达式值

  • 仅是单个表达式。 不是语句,不是流控件,不是任何用户定义的全局变量!

    • 只能使用单个表达式。模板语法内即使是一个简单的表达式也无法使用,例如“let level = 1

      让我们来看一些示例

  1. JavaScript String方法。{{ message.length }}
  2. js 允许访问模板表达式中的几个全局对象,即MathDate。 小心,不允许访问用户定义的全局变量
    • {{ Math.PI }}
    • {{ new Date() }}
  3. 流控制语句(如if-elseforwhiledo-while等)将不起作用,
  4. 唯一使用的是三元表达式。 始终建议将复杂的逻辑放入方法中。

{{ message === "Hi everyone!" ? "Welcome to the World of Vue" : "Hola" }}

解释Html 代码

For more info. on Vue, click <span>{{vueLink}}</span>

<script>
    var app = new Vue({
        el: "#app",
        data: {
            message: "Vue",
            vueLink: "<a href='https://vuejs.org/' style='color:green'>here</a>"
        }
    });
</script>
  • 显示的结果为 For more info. on Vue, click ``<a href='https://vuejs.org/' style='color:green'>here</a>
  • 默认情况下,Vue 始终将模板语法中的数据视为纯文本。并且这种行为可以防止任何第三方将不需要的代码注入您的网站。

如果您真的相信提供 HTML 代码的源代码是安全的,并希望将其呈现给 DOM,请使用另一个指令v-html

  • 使用v-html指令会将<span>标记的内容替换为vueLink数据属性的值,并将其解释为纯 HTML。 因此,超链接以指定的绿色显示。
    For more info. on Vue, click <span v-html="vueLink"></span>
    

属性绑定

  • Html中的标签有些属性,我们也可以绑定。
  • 假设我们想将链接绑定到href属性。
  • 让我们尝试使用文本插值技术(模板语法)来执行此操作,然后检查结果。
    • 点击链接后会在链接后添加 file:///C:/Users/fulsun/Desktop/vuestudy/%7B%7BvueLink%7D%7D
    • %7B%7BvueLink%7D%7D 对应的就是字符串 “{{vueLink}}”
    • 不会像在 Vue 实例的数据对象中指定的那样正常跳转,而是将href属性的双引号内的值当做字符串,并解析为 URL {{ vueLink }}。 显然,绑定从未发生过。
    • 因此,这就是 Vue 的工作方式。 我们不能将模板语法/大括号括起来用于 HTML 属性绑定。
    • 但是,如果我们仍然想将某些东西动态绑定到属性上怎么办?
      • Vue 附带了另一个用于此目的的指令v-bind
      • 在这种情况下,使用v-bind指令告诉 Vue.js 将data属性的值绑定到该指令后面的属性名称。 ```html
``` ### 场景: 动态显示图像 - 将 Vue 的图像放置在与代码相同的文件夹中,并将其在数据对象中的位置指定为`logo`。 将`数据绑定 - 图1`标记的`src`属性绑定到`logo`属性的值。 - 点击按钮切换图片 ```html 数据绑定 - 图2 ``` ### 根据数据值启用或禁用输入字段 - 在 Vue 实例的数据对象中,让我们拥有`isInputDisabled`属性,并将其值设置为`true`,让我们将其绑定到输入标签的`disable`属性。 ```html


- 这会将禁用的属性绑定到所提到的属性的值,并禁用输入字段。使用 Chrome 开发者工具检查该元素会显示其相应的 HTML 代码,现在让我们将`isInputDisabled`的值更改为`false`。页面可以正确输入
- 有趣的是,如果禁用的属性值为`false`,`null`或`undefined`,则属性甚至不包含在呈现的`<input>`元素中(使用开发人员工具检查该元素)。

![image.png](https://cdn.nlark.com/yuque/0/2020/png/385886/1600915811151-4f18a3d9-15be-4502-8a87-3a18038cc440.png#align=left&display=inline&height=284&margin=%5Bobject%20Object%5D&name=image.png&originHeight=284&originWidth=1198&size=24639&status=done&style=none&width=1198)

<a name="m520n"></a>
## 双向数据绑定

- 到目前为止,我们已经了解了如何使用插值,如何将`v-bind`用于属性绑定,缺少的部分是`v-model`,它用于双向数据绑定。
- _双向数据绑定_:这只是模型(Vue 实例中的`data`对象)和视图之间的关系。 对视图所做的任何更改(例如,由用户执行)将立即反映在基础 Vue 模型中,并将在视图中呈现此数据的所有位置进行更新。
-  换一种说法
   - 使用对`data`属性(模型)所做的更改来更新视图
   - 只要在视图中进行更改,数据属性(模型)就会更新

<a name="v5cks"></a>
### v-model指令

- 通常使用表单输入和控件创建这种双向绑定。 而`v-model`是用于实现该目标的指令
- 具体来说,以下是`v-model`所使用的确切 HTML 元素,
   - `<input>`
   - `<textarea>`
   - `<select>`
   - 组件
<a name="FC3OU"></a>
### 示例

- 让我们以`<input>`元素为例,在网页上显示一个文本字段。 让我们在 Vue 实例的`data`对象中也具有“`message`”属性,该属性用作我们的 Vue 模型,并具有`<p>`标签以使用语法(文本插值)呈现值。 
   1.  现在,我们要用`message`属性的值填充文本字段,例如“`hi`”,即使用模型更新视图。
   1. 每当用户在文本字段中更改值“`hi`”时,都必须在数据属性`message`中进行更新,
   1. 在我们的示例中,即使用视图和视图的更改来更新模型,同时将其呈现在`<p>`标签中
- 通过将`v-model`指令添加到`<input>`标记并将“`message`”属性绑定到它,可以完成所有这三个步骤,
```html
<!DOCTYPE html>
<html>
<head>
    <title>Hello Vue!</title>
    <!-- including Vue with development version CDN -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
    <h2>Welcome</h2>
    <div>
        <!-- two-way binding with v-model -->
        Greeting Message:
        <input type="text" v-model="message"></input>
        <p>The message is: {{ message }}</p>
    </div>
</div>
<!-- including index.js file -->
<script>
    var app = new Vue({
        el: "#app",
        data: {
            message: "hi"
        }
    });
</script>
</body>
</html>

修饰符

v-model带有三个修饰符。

用法:遵循v-model指令,添加一个点并指定修饰符。

  • .lazy – 在更改事件(而非输入事件)之后将输入与数据同步

    <input v-model.lazy="message">
    <!-- 在输入过程中下方的数据没有改变,回车或移动鼠标后才触发修改 -->
    
  • .number – 用于将有效的输入字符串转换为数字

    • 这里的 number 指令并不是限制用户输入,而是将用户输入的数据尝试绑定为 js 中的 number 类型
    • 举个例子,如果用户输入300,data 中绑定的其实是'300'(string),添加 number 指令后可以得到 300(number)的绑定结果。
    • 而如果用户输入的不是数字,这个指令并不会产生任何效果。
      <div id="app">
      <h2>Welcome</h2>
      <div>
      <!-- two-way binding with v-model -->
      Greeting Message:
      <input v-model.number="message"></input>
      <p>The message is: {{ message }}</p>
      <p>The message type is: {{ typeof message }}</p>
      </div>
      </div>
      <!-- including index.js file -->
      <script>
      var app = new Vue({
      el: "#app",
      data: {
       message: "hi"
      }
      });
      </script>
      
      image.png
  • .trim – 自动修剪用户输入

    • 自动过滤用户输入的首尾空白字符
    • 中间的会保留一个空格,多的会被过滤掉
      <input v-model.trim="message">
      
      image.png

表单输入绑定

  • 单个用 面量 接收
  • 多个值使用 空数组 接收

    单选按钮

  • 将多个选项绑定到模型的一个字面变量中, ```html

    Radio buttons




    Selected option: {{ selected }}
``` ![image.png](https://cdn.nlark.com/yuque/0/2020/png/385886/1601019465965-28edc2da-c686-449c-ab1c-ec0140986d10.png#align=left&display=inline&height=101&margin=%5Bobject%20Object%5D&name=image.png&originHeight=101&originWidth=320&size=3612&status=done&style=none&width=320) ### 单格复选框 - 将变量绑定到boolean值 ```html

Single checkbox with a boolean value

``` ![image.png](https://cdn.nlark.com/yuque/0/2020/png/385886/1601019577473-260c6db1-9f00-4ad0-9aa1-cd9d1a06e025.png#align=left&display=inline&height=187&margin=%5Bobject%20Object%5D&name=image.png&originHeight=187&originWidth=344&size=6036&status=done&style=none&width=344) ### 多个复选框 - 将数据绑定到模型的空数组变量上 - 有四个输入元素均为`checkbox`类型,并且每个元素都具有与**数组**`checkedFilms`”的双向绑定。 - 该数组的初始值在 Vue 实例的`data`属性中为空。 在这里`v-model`的工作方式是,在数组`checkedFilms`中填充所选复选框的值。 ```html

Multiple checkboxes with values of an array


Selected pixar films are: {{ checkedFilms }}
``` ![image.png](https://cdn.nlark.com/yuque/0/2020/png/385886/1601019819042-853c7723-f52e-45bd-80b2-b8ffbb6777ad.png#align=left&display=inline&height=105&margin=%5Bobject%20Object%5D&name=image.png&originHeight=105&originWidth=501&size=7228&status=done&style=none&width=501) ### 单选下拉菜单 - 这是一个正常的下拉列表,您可以在其中选择一个选项。将值绑定到 `select` 标签上。 ```html

Single select dropdown

I love: {{ singleSelect }}
``` ![image.png](https://cdn.nlark.com/yuque/0/2020/png/385886/1601020294361-38d67b0e-837f-42e9-98d2-4bb2473b34df.png#align=left&display=inline&height=171&margin=%5Bobject%20Object%5D&name=image.png&originHeight=171&originWidth=595&size=16262&status=done&style=none&width=595) ### 多选下拉菜单 - `data`属性中`multiselect`变量的初始值是一个空数组。将值绑定到 `select` 标签上。 ```html

Multiselect dropdown


I know to: {{ multiselect }}
``` ![image.png](https://cdn.nlark.com/yuque/0/2020/png/385886/1601020545803-4f8f19de-c946-4664-a95f-d00b48a19c5a.png#align=left&display=inline&height=152&margin=%5Bobject%20Object%5D&name=image.png&originHeight=152&originWidth=395&size=5995&status=done&style=none&width=395) ### 动态选项的下拉菜单 - 在实时场景中,下拉菜单的选项并不总是已知的。 另外,对值进行硬编码永远不是一个好习惯。 - 因此,在必须处理动态数据的情况下,可以将`v-bind`与`v-model`一起使用。 也可以利用`v-for`指令遍历我们可能要处理的所有选项。 - 将值绑定到 `select` 标签上。 ```html

Handling dynamic options

Selected letter: {{ dynamicSelection }}
``` ![image.png](https://cdn.nlark.com/yuque/0/2020/png/385886/1601020919910-29d26292-4e36-432e-9aba-557e5b6dc1e5.png#align=left&display=inline&height=90&margin=%5Bobject%20Object%5D&name=image.png&originHeight=90&originWidth=260&size=3194&status=done&style=none&width=260) ## 类绑定 - **类绑定**。 换句话说,我们将通过使用 Vue 将数据绑定到 HTML 元素的`class`属性来对其进行处理。 - 因为可能需要我们经常操作元素的类列表。 就像任何其他数据绑定一样,使用“`v-bind`”或其快捷方式“`:`”可用于处理这种情况。 表达式可以计算为**字符串,对象或数组**。 - 如果之前有class会将绑定的class添加到列表 ```html
Hello!!
# 渲染结果:
Hello!!
``` - 最简单的绑定(这里的active加不加单引号都可以,以下也一样都能渲染) ``` :class="{ 'active': isActive }" ``` - 判断是否绑定一个active ``` :class="{'active':isActive==-1}" 或者 :class="{'active':isActive==index}" ``` - 绑定并判断多个class,需要逗号隔开就行:(这里的activeTwo加不加引号都可以,也一样都能渲染,如下) ```json :class="{ 'active': isActive, 'sort': isSort }" # 第二种 : 也可以把后面绑定的对象写在一个变量放在data里面 :class="classObject" data() { return { classObject:{ active: true, sort:false } } } # 第三种(使用computed属性)
export default { data() { return { isActive: true, }; }, computed: { classObject: function () { return { active: this.isActive, } } } 结果渲染为:
# 第四种 数组方法
data() { return { activeClass: "active", errorClass: "disActive" }; }, 结果渲染为:
# 第五种:(数组与三元运算符结合判断选择需要的class) # (注意:三元运算符后面的“:”两边的class需要加上单引号,否则不能正确渲染)
data() { return { isActive: false, }; }, 结果渲染为:
# 数组对象结合动态判断 //前面这个active在对象里面可以不加单引号,后面这个sort要加单引号 :class="[{ active: isActive }, 'sort']" 或者 :class="[{ active: isActive==1 }, 'sort']" 或者 :class="[{ active: isActive==index }, 'sort']" ``` - 假设我们有名为“succesStyle,bcgStyle”的类,其样式在`style.css`样式表中定义如下 ```html ``` - 使用 Vue,通过将其作为对象传递给`v-bind:class`来动态切换此类非常容易 - classname: true 表示渲染这个div的class为classname - classname: false表示不渲染这个class,使用默认的输出。 ### 内联方式绑定 ```html

Welcome

Hello!!

The value of successFlag is {{ successFlag }}

``` ![image.png](https://cdn.nlark.com/yuque/0/2020/png/385886/1601024074136-5919a0b2-6aeb-443a-976d-2dca1b1d39ab.png#align=left&display=inline&height=234&margin=%5Bobject%20Object%5D&name=image.png&originHeight=234&originWidth=489&size=9702&status=done&style=none&width=489) ### 对象方式绑定 ```html

Welcome

Hello!!

The value of successFlag is {{ successFlag }}

``` ![image.png](https://cdn.nlark.com/yuque/0/2020/png/385886/1601024221111-a1222b55-505e-46c6-8cd8-35db43e52400.png#align=left&display=inline&height=163&margin=%5Bobject%20Object%5D&name=image.png&originHeight=163&originWidth=393&size=4882&status=done&style=none&width=393) ### 数组方式绑定 ```html

Welcome

Hello!!

The value of successFlag is {{ successFlag }}

``` ## 过滤器 格式化变量内容的输出。(日期格式化,字母大小写,数字再计算等等) ```javascript

{{message}}

{{message | toupper }}


现在的vue.js学习进度是{{num}}({{num | topercentage}})。

``` ![image.png](https://cdn.nlark.com/yuque/0/2020/png/385886/1601298651281-5061b762-aeb0-468f-a803-2445587e64e0.png#align=left&display=inline&height=187&margin=%5Bobject%20Object%5D&name=image.png&originHeight=187&originWidth=460&size=7294&status=done&style=none&width=460) ## computed:计算属性 - 官网: [https://cn.vuejs.org/v2/guide/computed.html](https://cn.vuejs.org/v2/guide/computed.html) - 处理元数据,便于进行二次利用。(比如:消费税自动计算功能) - 这里我们声明了一个计算属性 `priceInTax `。我们提供的函数将用作 property `vm.``priceInTax` 的 getter 函数: - 你可以打开浏览器的控制台,自行修改例子中的 vm。`vm.``priceInTax` 的值始终取决于 `vm.price` 的值。 ![image.png](https://cdn.nlark.com/yuque/0/2020/png/385886/1601299972366-afef602a-03e6-474e-bc63-1ea0ab981a6d.png#align=left&display=inline&height=77&margin=%5Bobject%20Object%5D&name=image.png&originHeight=77&originWidth=683&size=5722&status=done&style=none&width=683) - 可以像绑定普通 property 一样在模板中绑定计算属性。Vue 知道 `vm.``priceInTax` 依赖于 `vm.``price`,因此当 `vm.``price`发生改变时,所有依赖的绑定也会更新。 ```javascript
今年3月3日发卖的任天堂新一代主机Switch的价格是:{{price}}元,
含税价格为:{{priceInTax}}元,折合人民币为:{{priceChinaRMB}}元。

今年3月3日发卖的任天堂新一代主机Switch的价格是:29980元, 含税价格为:32378.4元,折合人民币为:1933元。


<a name="a0FVs"></a>
### 与方法的区别

- 我们可以使用方法来实现上面的功能, 将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。
- 不同的是**计算属性是基于它们的响应式依赖进行缓存的**。**只在相关响应式依赖发生改变时它们才会重新求值**。这就意味着只要 privce还没有发生改变,多次访问 `priceInTax`计算属性会立即返回之前的计算结果,而不必再次执行函数。
- 每当触发重新渲染时,**调用方法将总会再次执行函****数**。

```javascript
含税价格为:{{priceInTax()}}元

methods:{
  priceInTax: function () {
      return this.price * 1.08;
    }
}

我们为什么需要缓存?

  • 假设我们有一个性能开销比较大的计算属性 A,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 A
    • 如果没有缓存,我们将不可避免的多次执行 A 的 getter!
    • 如果你不希望有缓存,请用方法来替代。

$watch侦听属性

  • Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动:侦听属性
  • 当你有一些数据需要随着其它数据变动而变动时,你很容易滥用 watch
  • 然而,通常更好的做法是使用计算属性而不是命令式的 watch 回调。
  • 使用 watch计算全名,当firstName,lastName 改变会自动触发函数 ```javascript
    {{ fullName }}