Vue笔记:Vue基础

目录

前言

Vue.js 是一套构建用户界面的渐进式框架,你可以选择使用它的一部分功能,也可以使用全部功能。

以下代码的环境:https://codepen.io/pen

hello Vue

Vue.js是以JavaScrip作为应用的入口,HTML只是提供一个渲染的锚点 。

1.引入vue.js库

这将暴露出一个全局类——Vue,你可以用它来创建一个Vue实例。

<script src="https://cdn.jsdelivr.net/npm/vue"></script>

2.创建Vue实例

Vue是一个封装了响应式开发、模板编译等诸多特性的基础类,你通过提供一些配置项,来创建一个实例:

var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!',
  }
})

这里的app下有两个配置项:

  • el:挂载Vue实例到一个已存在的DOM元素上。
  • data:Vue 实例的数据对象,用于数据绑定。

3.添加html标签

<div></div>

4.Vue挂载:通过标签id将Vue实例到DOM元素上

<div id="app"></div>

5.数据绑定:将Vue实例data数据通过指令插入到标签

<div id="app">{{ message }}</div>

6.浏览器显示

 上面介绍了Vue实例的el、data配置项,以下是Vue实例的其他常用配置项

 Vue 实例常用选项

选项名说明类型
el 通过 CSS 选择器或者 HTMLElement 实例的方式,提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标 string/Element
template 字符串模板,将会替换挂载的元素 string
render 字符串模板的代替方案,该渲染函数接收一个createElement方法作为第一个参数用来创建 VNode (createElement: () => VNode) => VNode
data Vue 实例的数据对象,用于数据绑定 Object/Function
组件只支持Function
props 用于接收来自父组件的数据 Array<string>/Object
methods Vue 实例的事件,可用于事件绑定 { [key: string]: Function }
computed 计算属性,用于简化模板的复杂数据计算 { [key: string]: Function or { get: Function, set: Function } }
watch 观察 Vue 实例变化的一个表达式或计算属性函数 { [key: string]: string or Function or Object or Array }
directives 自定义指令 Object
filters 过滤器 Object
components 组件 Object

Vue 实例中的这些选项,大多数都可以作为全局实例属性来获取或者访问:

const vm = new Vue({
  // ...一些选项
});

vm.$data; // 获取 data
vm.$props; // 获取 props
vm.$el; // 获取挂载元素
vm.$options; // 获取 Vue 实例的初始选项
vm.$parent; // 获取父实例
vm.$root; // 获取根实例
vm.$children; // 获取当前实例的直接子组件
vm.$refs; // 获取持有注册过 ref 特性 的所有 DOM 元素和组件实例

vm.$watch; // 观察 Vue 实例变化的一个表达式或计算属性函数
vm.$set; // 向响应式对象中添加一个属性,并确保这个新属性同样是响应式的,且触发视图更新
vm.$delete; // 删除对象的属性。如果对象是响应式的,确保删除能触发更新视图

Vue挂载

1.el:通过el挂载到已存在的DOM元素上,上面已介绍。

2.template:给 Vue 实例提供字符串模板,该模板将会替换挂载的元素。

3.render:字符串模板 template 的代替方案,该渲染函数接收一个createElement方法作为第一个参数用来创建 VNode,我们先了解一下Vue整体流程:

从上图中,不难发现一个Vue的应用程序是如何运行起来的,模板通过编译生成AST,再由AST生成Vue的render函数(渲染函数),渲染函数结合数据生成Virtual DOM树,Diff和Patch后生成新的UI。从这张图中,可以接触到Vue的一些主要概念:

  • 模板:Vue的模板基于纯HTML,基于Vue的模板语法,我们可以比较方便地声明数据和UI的关系。
  • AST:AST是Abstract Syntax Tree的简称,Vue使用HTML的Parser将HTML模板解析为AST,并且对AST进行一些优化的标记处理,提取最大的静态树,方便Virtual DOM时直接跳过Diff。
  • 渲染函数:渲染函数是用来生成Virtual DOM的。Vue推荐使用模板来构建我们的应用界面,在底层实现中Vue会将模板编译成渲染函数,当然我们也可以不写模板,直接写渲染函数,以获得更好的控制 (这部分是我们今天主要要了解和学习的部分)。
  • Virtual DOM:虚拟DOM树,Vue的Virtual DOM Patching算法是基于Snabbdom的实现,并在些基础上作了很多的调整和改进。
  • Watcher:每个Vue组件都有一个对应的watcher,这个watcher将会在组件render的时候收集组件所依赖的数据,并在依赖有更新的时候,触发组件重新渲染。你根本不需要写shouldComponentUpdate,Vue会自动优化并更新要更新的UI。

上图中,render函数可以作为一道分割线,render函数的左边可以称之为编译期,将Vue的模板转换为渲染函数render函数的右边是Vue的运行时,主要是基于渲染函数生成Virtual DOM树,Diff和Patch。

详细可以查看:https://www.jianshu.com/p/7508d2a114d3

数据绑定

数据绑定就是原始数据驱动页面变化,原始数据发生变化,数据重新编译,页面会重新渲染。

Vue 中数据绑定的常用方式

语法说明
插值语法{{}} 文本插值,可配合过 Javascript 表达式和过滤器使用
v-once 一次性插值,数据改变时插值处的内容不会更新
v-html 可输出真正的 HTML,不会被转义为普通文本
v-bind:(简写: 可用于绑定 DOM 属性、或一个组件 prop 到表达式
v-text 纯文本插值,接收字符串
v-pre 显示html里面的原始内容

插值语法{{}}

如果你熟悉django 模板,django里面服务端渲染模板也是这样做的,通过{{ }}的方式渲染动态数据。

在插值表达式中不仅可以渲染,还可以做一些简单的运算,参考如下:

v-once:该指令表示元素和组件只渲染一次,不会随着数据的改变而改变,当原始数据变化,页面不会更新。

我这里在控制台,修改name属性的值为"Ling",页面就会更新为Ling。

当你修改<h2>姓名:{{name}}</h2>为<h2 v-once>姓名:{{name}}</h2>时,就无法达到刚才的效果。

v-html:显示html,有时候从服务端传递来的字符串可能是html,这个时候不能当作字符串显示,如果你想以html显示,必须指定。

html部分:

<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">
    <h2 >{{ url }}</h2>
    <h2  v-html="url"></h2>
</div>

js部分:

var app = new Vue({
  el: '#app',//挂载到div dom上
  data: {
     url: '<a href="https://www.baidu.com/">百度一下</a>',
  }
})

v-text:显示纯文本,接收字符串。

js部分

var app = new Vue({
  el: '#app',//挂载到div dom上
  data: {
     name: "ling",
  }
})

html部分

<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">
    <h2  >姓名:{{name}}</h2>
    <h2 v-text >姓名:{{name}}</h2>
</div>

v-pre:显示html里面的原始内容。

js部分

var app = new Vue({
  el: '#app',//挂载到div dom上
  data: {
     message: 'hello world',
  }
})

html部分

<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">
    <h2 v-pre>{{ url }}</h2>
</div>

v-bind:给html属性、style,class绑定动态值。

v-bind绑定属性

js部分

var app = new Vue({
  el: '#app',//挂载到div dom上
  data: {
     imgurl: 'https://www.baidu.com/img/flexible/logo/pc/result.png',
     url: 'https://www.baidu.com'
  }
})

html部分

<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">
  <img v-bind:src="imgurl" alt=""></br>
  <a v-bind:href="url">百度一下</a>
</div>
v-bind的简写(:)
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">
  <img :src="imgurl" alt=""></br>
  <a :href="url">百度一下</a>
</div>

v-bind绑定style

  • 对象语法(常用)

    • ·:style="{color: currentColor, fontSize: fontSize + 'px'}"
    • style后面跟的是一个对象类型,对象的key是CSS属性名称,对象的value是具体赋的值,值可以来自于data中的属性。
  • 数组语法(不常用)

    • <div v-bind:style="[baseStyles, overridingStyles]"></div>
    • style后面跟的是一个数组类型,多个值以,分割即可。
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">

    <!-- '50px' 不加 '' 会被当成一个变量去解析 -->
    <h1 :style="{fontSize: '50px'}">{{massage}}</h1>
    
    <h1 :style="{color:iscolor,'background-color':isback,fontSize:issize+'px'}">{{massage}}</h1>

    <!-- 可以放在一个methods -->
    <h1 :style="getStyle()">{{massage}}</h1>

    <!-- 数组的形式  -->
    <h1 :style="[style1,style2]">{{massage}}</h1>
</div>
   var app = new Vue({
        el: '#app',
        data: {
            massage: 'aqing',
            iscolor: "red",
            isback: 'yellow',
            issize: 50,
            
            style1: {
                backgroundColor: 'red'
            },
            style2: {
                fontSize: '50px'
            },
        },
        methods: {
            getStyle() {
                return {
                    color: this.iscolor,
                    backgroundColor: this.isback,
                    fontSize: this.issize + 'px'
                }
            }
        }
    })

v-bind绑定class

用法一:直接通过{}绑定一个类

<h2 :class="{'active': isActive}">vue1</h2>

用法二:也可以通过判断,传入多个值

<h2 :class="{'active': isActive, 'line': isLine}">vue3</h2>

用法三:和普通的类同时存在,并不冲突 ,一般在该属性必须有的情况下,才使用和普通的类同时存在

注:如果isActive和isLine都为true,那么会有title/active/line三个类

<h2 class="title" :class="{'active': isActive, 'line': isLine}">Hello World</h2>

你可以看到,v-bind:class 指令也可以与普通的 class attribute 共存,而通过控制数据data的isactive,isline的ture或者false。来确定对应的class是否存在。

<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">
      <h1 class="active">vue1</h1>
      <h1 :class="active">vue2</h1>
  
      <h1 :class="{ active: isactive, line: isline}">vue3</h1>
      <h1 class="title" :class="{ 'active': isactive, 'line': isline}">vue4</h1>
</div>
   var app = new Vue({
        el: '#app',
        data: {
              active: 'active',

              isactive: true,
              isline: true,
          },
    })

用法四:数组形式

<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">
      <div v-bind:class="[activeClass, errorClass]">vue</div>
</div>
   var app = new Vue({
        el: '#app',
        data: {
              activeClass: 'active',
              errorClass: 'text-danger',
              isactive: true,
              isline: true,
          },
    })

如果你也想根据条件切换列表中的 class,可以用三元表达式:

<div v-bind:class="[isActive ? activeClass : '', errorClass]">vue</div>

这样写将始终添加 errorClass,但是只有在 isActive 是 true 时才添加 activeClass

不过,当有多个条件 class 时这样写有些繁琐。所以在数组语法中也可以使用对象语法:

<div v-bind:class="[{ active: isActive }, errorClass]">vue</div>

事件绑定

可以用v-on指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码,可用@缩写。

<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">
  <button v-on:click="addCounter">Add 1</button>
  <!-- 以下为缩写 -->
  <button @click="addCounter">Add 1</button>
  <p>The button above has been clicked {{ counter }} times.</p>
</div>
   var app = new Vue({
        el: '#app',
        data: {
            counter: 0,
          },
        methods: {
            addCounter() {
              this.counter += 1;
                }
              }
    })

事件修饰符

Vue 为v-on提供了事件修饰符:

修饰符说明
.stop event.stopPropagation(),阻止事件继续传播
.prevent event.preventDefault(),阻止默认事件
.capture 添加事件监听器时使用事件捕获模式
.once 只绑定一次
.enter/.tab/.esc/.space/.ctrl/.[keyCode] 按键修饰符

使用方式很简单,在绑定事件后面加上修饰符就可以:

<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>

<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>

<!-- Alt + C -->
<input @keyup.alt.67="clear" />

计算属性和侦听器

计算属性

模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。

<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="example">
  <p>Original message: {{ message }}</p>
   <p>Original message: {{ message.split('').reverse().join('') }}</p>
  <p>Computed reversed message: {{ reversedMessage }}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="example">
  <p>Original message: {{ message }}</p>
   <p>Original message: {{ message.split('').reverse().join('') }}</p>
  <p>Computed reversed message: {{ reversedMessage }}</p>
</div>

计算属性缓存 vs 方法

两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。

简单来说:计算属性会进行缓存,如果多次使用时,计算属性只会调用一次。

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

// 在组件中
methods: {
  reversedMessage: function () {
    return this.message.split('').reverse().join('')
  }
}

条件渲染、列表渲染

条件渲染

条件渲染相关指令主要包括v-ifv-else-ifv-elsev-show这几个,用于条件性地渲染、隐藏一块内容。

一个简单的示例:点击登录转换按钮,切换为邮箱登录。

<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">

  <span v-if="isuser">
    <label for="user">手机登陆</label>
    <input type="text" id="user" placeholder="手机登陆">
  </span>

  <span v-else>
    <label for="emial">邮箱登陆</label>
    <input type="text" id="emial" placeholder="邮箱登陆">
    </span>
  <button @click="isuser=!isuser">登录转换</button>
</div>
var app = new Vue({
    el: '#app',
    data: {
      isuser: true
    }
  })

v-else-if

v-else-if,顾名思义,充当 v-if 的“else-if 块”,可以连续使用:

<div v-if="type === 'A'">
  A
</div>
<div v-else-if="type === 'B'">
  B
</div>
<div v-else-if="type === 'C'">
  C
</div>
<div v-else>
  Not A/B/C
</div>

类似于 v-elsev-else-if 也必须紧跟在带 v-if 或者 v-else-if 的元素之后。

key

使用v-if指令有个需要注意的地方是,在原始数据发生变化时重新编译渲染的 过程中会优先使用现有的元素进行调整,而并非删除原有的元素再重新插入一个元素。这样的算法背景下,当我们绑定的数据发生变更时,可能会存在这样的情况:

当点击切换按钮时,<input>元素只会更新属性值idplaceholder,但原先输入的内容还在。

如果我们不希望Vue出现类似重复利用已有的元素的问题,可以给对应的input添加key,需要保证key的不同。

<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">

  <span v-if="isuser">
    <label for="user">手机登陆</label>
    <input type="text" id="user" placeholder="手机登陆" key="userkey">
  </span>

  <span v-else>
    <label for="emial">邮箱登陆</label>
    <input type="text" id="emial" placeholder="邮箱登陆" key="emall">
    </span>
  <button @click="isuser=!isuser">登录转换</button>
</div>

v-show

v-showv-if不一样,v-if会在条件具备的时候才进行渲染,而v-show的逻辑是一定渲染,但在条件具备的时候才显示:

用法大致一样:

<h1 v-show="ok">Hello!</h1>

v-if当条件为false时,压根不会有对应的元素在DOM中。

v-show当条件为false时,仅仅是将元素的display属性设置为none而已,带有v-show的元素始终会被渲染并保留在 DOM 中。

​ 

一般来说,v-if有更高的切换开销(因为要不停地重新渲染),而v-show有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用v-show较好;如果在运行时条件很少改变,则使用v-if较好。

列表渲染

列表渲染相关的指令主要是v-for这个指令,用来渲染列表。

<!-- 遍历数组时 -->
<!-- 其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名,可选的第二个参数 index 为当前项的索引 -->
<ul>
  <li v-for="(item, index) in items">
    {{index}}: {{ item.message }}
  </li>
</ul>

<!-- 遍历对象时 -->
<!-- 在遍历对象时,会按 Object.keys() 的结果遍历 -->
<!-- 其中 object 是源数据对象,而 value 则是被遍历的对象值,可选的第二个参数 key 为当前值的键名,可选的第三个参数 index 为当前项的索引 -->
<div v-for="(value, key, index) in object">
  {{ index }}.{{ key }}: {{ value }}
</div>

<!-- 还能遍历数字 -->
<p v-for="n in 10">{{n}}</p>

遍历数组

<ul id="example-1">
  <li v-for="item in items" :key="item.message">
    {{ item.message }}
  </li>
</ul>
var example1 = new Vue({
  el: '#example-1',
  data: {
    items: [
      { message: 'Foo' },
      { message: 'Bar' }
    ]
  }
})

遍历对象

<ul id="v-for-object" class="demo">
  <li v-for="value in object">
    {{ value }}
  </li>
</ul>
new Vue({
  el: '#v-for-object',
  data: {
    object: {
      title: 'How to do lists in Vue',
      author: 'Jane Doe',
      publishedAt: '2016-04-10'
    }
  }
})

你也可以提供第二个的参数为 property 名称 (也就是键名):

<div v-for="(value, name) in object">
  {{ name }}: {{ value }}
</div>

还可以用第三个参数作为索引:

<div v-for="(value, name, index) in object">
  {{ index }}. {{ name }}: {{ value }}
</div>

 双向绑定

v-model指令在表单<input><textarea><select>元素上创建双向数据绑定。实际上v-model是语法糖,它的背后本质上是包含两个操作:

  • 1.v-bind绑定一个value属性

  • 2.v-on指令给当前元素绑定input事件

v-model 会忽略所有表单元素的 valuecheckedselected attribute 的初始值而总是将 Vue 实例的数据作为数据来源。你应该通过 JavaScript 在组件的 data 选项中声明初始值。

v-model 在内部为不同的输入元素使用不同的 property 并抛出不同的事件:

  • text 和 textarea 元素使用 value property 和 input 事件;
  • checkbox 和 radio 使用 checked property 和 change 事件;
  • select 字段将 value 作为 prop 并将 change 作为事件。

它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理:

文本

<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>

多行文本

<span>Multiline message is:</span>
<p style="white-space: pre-line;">{{ message }}</p>
<br>
<textarea v-model="message" placeholder="add multiple lines"></textarea>

在文本区域插值 (<textarea>{{text}}</textarea>) 并不会生效,应用 v-model 来代替。

复选框

单个复选框,绑定到布尔值:

<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">{{ checked }}</label>

多个复选框,绑定到同一个数组:

<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
<br>
<span>Checked names: {{ checkedNames }}</span>
new Vue({
  el: '...',
  data: {
    checkedNames: []
  }
})

单选按钮

<div id="example-4">
  <input type="radio" id="one" value="One" v-model="picked">
  <label for="one">One</label>
  <br>
  <input type="radio" id="two" value="Two" v-model="picked">
  <label for="two">Two</label>
  <br>
  <span>Picked: {{ picked }}</span>
</div>
new Vue({
  el: '#example-4',
  data: {
    picked: ''
  }
})

选择框

单选时:

<div id="example-5">
  <select v-model="selected">
    <option disabled value="">请选择</option>
    <option>A</option>
    <option>B</option>
    <option>C</option>
  </select>
  <span>Selected: {{ selected }}</span>
</div>
new Vue({
  el: '...',
  data: {
    selected: ''
  }
})

如果 v-model 表达式的初始值未能匹配任何选项,<select> 元素将被渲染为“未选中”状态。在 iOS 中,这会使用户无法选择第一个选项。因为这样的情况下,iOS 不会触发 change 事件。因此,更推荐像上面这样提供一个值为空的禁用选项。

多选时 (绑定到一个数组):

<div id="example-6">
  <select v-model="selected" multiple style=" 50px;">
    <option>A</option>
    <option>B</option>
    <option>C</option>
  </select>
  <br>
  <span>Selected: {{ selected }}</span>
</div>
new Vue({
  el: '#example-6',
  data: {
    selected: []
  }
})

用 v-for 渲染的动态选项:

<select v-model="selected">
  <option v-for="option in options" v-bind:value="option.value">
    {{ option.text }}
  </option>
</select>
<span>Selected: {{ selected }}</span>
new Vue({
  el: '...',
  data: {
    selected: 'A',
    options: [
      { text: 'One', value: 'A' },
      { text: 'Two', value: 'B' },
      { text: 'Three', value: 'C' }
    ]
  }
})

值绑定

对于单选按钮,复选框及选择框的选项,v-model 绑定的值通常是静态字符串 (对于复选框也可以是布尔值):

<!-- 当选中时,`picked` 为字符串 "a" -->
<input type="radio" v-model="picked" value="a">

<!-- `toggle` 为 true 或 false -->
<input type="checkbox" v-model="toggle">

<!-- 当选中第一个选项时,`selected` 为字符串 "abc" -->
<select v-model="selected">
  <option value="abc">ABC</option>
</select>

但是有时我们可能想把值绑定到 Vue 实例的一个动态 property 上,这时可以用 v-bind 实现,并且这个 property 的值可以不是字符串。

复选框

<input
  type="checkbox"
  v-model="toggle"
  true-value="yes"
  false-value="no"
>
// 当选中时
vm.toggle === 'yes'
// 当没有选中时
vm.toggle === 'no'

这里的 true-value 和 false-value attribute 并不会影响输入控件的 value attribute,因为浏览器在提交表单时并不会包含未被选中的复选框。如果要确保表单中这两个值中的一个能够被提交,(即“yes”或“no”),请换用单选按钮。

单选按钮

<input type="radio" v-model="pick" v-bind:value="a">
// 当选中时
vm.pick === vm.a

选择框的选项

<select v-model="selected">
    <!-- 内联对象字面量 -->
  <option v-bind:value="{ number: 123 }">123</option>
</select>
// 当选中时
typeof vm.selected // => 'object'
vm.selected.number // => 123

修饰符

.lazy

在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步 (除了上述输入法组合文字时)。你可以添加 lazy 修饰符,从而转为在 change 事件_之后_进行同步:

<!-- 在“change”时而非“input”时更新 -->
<input v-model.lazy="msg">

.number

如果想自动将用户的输入值转为数值类型,可以给 v-model 添加 number 修饰符:

<input v-model.number="age" type="number">

这通常很有用,因为即使在 type="number" 时,HTML 输入元素的值也总会返回字符串。如果这个值无法被 parseFloat() 解析,则会返回原始的值。

.trim

如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符:

<input v-model.trim="msg">
原文地址:https://www.cnblogs.com/-wenli/p/13726457.html