Vue基础学习

📚 Vue 学习目录

🚀 Vue.js基础学习 - 📝 Vue.js进阶 - 🔦 webpack学习

📦 Vue-CLI学习 - 📌 Vue-router学习 - 🔮 Vuex学习 - 🎀 Nuxt.js 学习

什么是Vue

Vue是一套用于构建用户界面的渐进式JavaScript框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,方便与第三方库或既有项目整合。

最简单的一个Vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE html>
<!-- html代码,view层,模板 -->
<html>
<head>
<meta charset="utf-8">
<title>第一个Vue</title>
</head>
<body>

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

<!-- 引入相关文件,然创建实例,在实例中写各种方法就ok了 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
//vue实例
var vue = new Vue({
el:"#app", //挂载元素
data:{
msg:"Hello world"
}
});
/* vm就是new出来的实例 */
console.log(vue.$data);//也就是数据data,后面还有很多挂载在vm(new出来的)实例上的属性
</script>
</body>
</html>

结果:

1
Hello World

Vue实例,每一个应用都是通过Vue这个构造函数创建根实例(root instance)启动New Vue(选项对象)。需要传入选项对象,对象包含挂在元素,数据,模板、方法等。

  • el:挂载元素选择器 — String|HtmlElement
  • data:代理数据 — Object|Function
  • methods:定义方法 — Object
  • template:模板、它会替换 <div id="app"></div>里面的内容

Vue代理data数据,每个vue实例都会代理其data对象里所有的属性,这些被代理的属性是响应的。新添加的属性不具备响应功能,改变后不会更新视图。
Vue实例自身属性和方法,暴露自身的属性和方法,以"$"开头的,例如:$el、$data ...

解释:我们通过引入vue.js文件、创建Vue对象绑定idapp的div、在data写入msg对象、值为Hello world,最后在div中通过&#123;&#123;&#125;&#125;(双大括号)绑定了data中msg的值。在控制台中通过 vue.msg = "Hello" 可以动态修改msg的内容。


vue-cli的基本使用

暂时不用 后面通过Vue-cli创建时再使用

  • 安装Vue-cli

    1
    npm install -g @vue/cli

    等待安装完成

    • 卸载
    1
    npm uninstall -g @vue/cli
  • 验证vue版本

    1
    2
    3
    4
    vue -V 或者 vue --version

    ps:
    -V: 大写字母V
  • 创建Vue项目

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    vue create [项目名]

    ps:
    项目名中不要包含大写字母
    可加参数:
    -p, --preset <presetName> 忽略提示符并使用已保存的或远程的预设选项
    -d, --default 忽略提示符并使用默认预设选项
    -i, --inlinePreset <json> 忽略提示符并使用内联的 JSON 字符串预设选项
    -m, --packageManager <command> 在安装依赖时使用指定的 npm 客户端
    -r, --registry <url> 在安装依赖时使用指定的 npm registry
    -g, --git [message] 强制 / 跳过 git 初始化,并可选的指定初始化提交信息
    -n, --no-git 跳过 git 初始化
    -f, --force 覆写目标目录可能存在的配置
    -c, --clone 使用 git clone 获取远程预设选项
    -x, --proxy 使用指定的代理创建项目
    -b, --bare 创建项目时省略默认组件中的新手指导信息
    -h, --help 输出使用帮助信息
  • 初学者配置:

    Vue CLI v4.3.1
    ? Please pick a preset: Manually select features
    ? Check the features needed for your project: Babel, Router, CSS Pre-processors
    ? Use history mode for router? (Requires proper server setup for index fallback in production) Yes
    ? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): Less
    ? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files
    ? Save this as a preset for future projects? No

  • 运行

    1
    npm run serve
  • 工程目录

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    ├── README.md
    ├── index.html
    ├── src
    │ ├── App.vue
    │ ├── assets
    │ │ ├── img
    │ │ └── logo.png
    │ ├── components
    │ │ └──Helloworld.vue
    │ ├── views
    │ │ └── Home.vue
    │ ├── main.js
    │ ├── router // 路由配置文件
    │ │ └── router.js
    │ └── store
    │ └──store.js
    └── babel.config.js
    └── package.json
    └── package-lock.json
    • public存放静态文件
    • public/index.html生成项目的入口文件,webpack打包的js,css也会自动注入到该页面中
    • src存放各种vue文件的地方
    • src/assets用于存放各种静态文件,如图片,css
    • src/compnents用于存放我们的公共组件
    • src/views用于存放我们写好的各种页面
    • src/App.vue主vue组件 引入其他组件,app.vue是项目的主组件,所有页面都是在app.vue下切换的
    • src/main.js入口文件,作用是初始化vue实例,也可以在此文件中引用组件库或者全局变量
    • src/router.js路由文件,是为各个页面的地址路径
    • src/store.js状态文件
    • package.json模块基本信息,项目开发所需要模块,版本,项目名称

基本指令

  • mustache语法 &#123;&#123;&#125;&#125;

    通过双大括号 &#123;&#123;&#125;&#125; 绑定data里面的值:&#123;&#123;&#125;&#125; 里面的值为data里面的数据、也可以是表达式

    1
    2
    3
    {{ msg }}

    {{ msg + " : " + type }}
  • v-once 这个指令不需要任何表达式,它的作用就是定义它的元素或组件只会渲染一次,包括元素或者组件的所有字节点。首次渲染后,不再随着数据的改变而重新渲染。也就是说使用v-once,那么该块都将被视为静态内容。

    1
    <h2 v-once >{{ message }}</h2>
  • v-html 会把传入的数据解析成html代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <div id="app">
    <h2 v-html="url"></h2>
    </div>

    const app = new Vue({
    el : '#app',
    data : {
    url : '<a href="http://www.baidu.com"> 百度一下 <a/>'
    }
    })
  • v-text 用于渲染普通文本 (最好不用这个)、因为会覆盖标签里的内容

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <div id="app">
    <h2>{{msg}} + "!"</h2>
    <h2 v-text="msg">哈哈哈</h2>
    </div>

    const app = new Vue({
    el : '#app',
    data : {
    msg: "Hello world"
    }
    })

    渲染结果:

    Hello world!
    Hello world
  • v-pre 可以理解为不渲染标签里的内容

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <div id="app">
    <h2 v-pre>{{msg}}</h2>
    </div>

    const app = new Vue({
    el : '#app',
    data : {
    msg: "Hello world"
    }
    })

    渲染结果:

    {{ msg }}

  • v-cloak 会在 Vue 实例编译结束时,从绑定的 HTML 元素上被移除。指令是解决屏幕闪动的好方法、但在大型、工程化的项目不需要使用 (不常用)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    html:
    <div id="app" v-cloak>
    {{msg}}
    </div>

    css:
    [v-cloak]{
    display: none;
    }

    javascript:
    const app = new Vue({
    el : '#app',
    data : {
    msg: "Hello world"
    }
    })

数据绑定 v-bind

v-bind是用于绑定数据和元素属性的: v-bind:[属性名]="data中的键名"、属性名可以为标签属性自定义属性,简写为 :xxx
html属性不能使用 &#123;&#123;&#125;&#125; (双大括号)形式绑定,只能使用v-bind指令

基本语法

  • v-bind语法

    通过 v-bind 绑定数据 v-bind:[属性]="data中的键名"

    1
    2
    3
    <div v-bind:title="title" v-bind:type="type">我是第一个div</div>

    <div v-bind:title="title1 + ' ' title2" v-bind:type="type">我是第二个div</div>

    可以简写成 :[属性]

    1
    <div :title="title" :type="type">我是一个简写的div</div>

    也可以写函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <div id="app">
    <p v-bind:title="getTitle()"通过函数获取title</p>
    </div>


    var vm = new Vue({
    el: '#app',
    data: {
    getTitle: function () {
    return 'title1 title2';
    }
    }
    });
  • 动态绑定

    v-bind:[data中的键名]="data中的键名"

    1
    <div v-bind:[attrName]="title">我是用于动态绑定</div>
  • 示例

    查看代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    <template>
    <div>
    <!--template里面只能有一个子元素、也就是这里的直接div-->
    <h1>数据绑定:v-bind</h1>
    <!-- {{ }} 里面的值为data里面的数据、也可以是表达式-->
    <p>{{ msg }}</p>
    <p>{{ msg + " : " + type }}</p>
    <!-- 通过v-bind 绑定数据 v-bind:[属性]="data中的键名" -->
    <div v-bind:title="title" v-bind:type="type">我是一个div</div>
    <!-- 可以简写成 :[属性] -->
    <div :title="title" :type="type">我是一个简写的div</div>
    <!--动态绑定 v-bind:[data中的键名]="data中的键名" -->
    <div v-bind:[attrName]="title">我是用于动态绑定</div>
    </div>
    </template>

    <script>
    export default {
    name: "Study01",
    data() {
    return {
    msg: "这里是msg的内容",
    type: "这里是type的内容",
    title: "这里是title的内容",
    attrName: "title"
    }
    },
    //钩子函数:mounted是挂载是触发的函数
    mounted() {
    setTimeout(()=>{
    //通过这个动态修改值
    this.msg = "通过this.[data中的键名]可以动态修改内容"
    },3000)
    }
    }
    </script>

    渲染结果(3秒后的):

    1
    2
    3
    4
    5
    6
    7
    8
    <div>
    <h1>基本语法</h1>
    <p>通过this.[data中的键名]可以动态修改内容</p>
    <p>通过this.[data中的键名]可以动态修改内容 : 这里是type的内容</p>
    <div title="这里是title的内容" type="这里是type的内容">我是一个div</div>
    <div title="这里是title的内容" type="这里是type的内容">我是一个简写的div</div>
    <div title="这里是title的内容">我是用于动态绑定</div>
    </div>

Vue生命周期

生命周期是否获取dom节点是否可以获取data是否获取methods
beforeCreate
created
beforeMount
mounted

Class 与 Style 绑定

绑定Class
  • 绑定一个class值

    1
    2
    3
    4
    <div :class="ClassA">我的class绑定了一个</div>

    <div class="title" :class="ClassA">我的class绑定了两个</div>
    结果: class="title ClassA" 会合并
  • 数组法绑定多个class值

    1
    <div :class="[ClassA,ClassB]">我的class绑定了多个</div>
  • 对象法绑定多个class值

    1
    <div :class="ClassObj">我的class通过对象绑定了多个</div>
  • 对象方式{ xxx:boolean }绑定的是键名、值为true时显示、反之不显示、一定要注意显示的是键名

    1
    2
    <div :class="{CA:true,CB:true}">我的class通过对象绑定了多个</div>
    <div class="{CA:isA,CB:isB}">我的class通过对象绑定了多个</div>
  • data

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    data(){
    return{
    //绑定Class
    ClassA : "ClassA",
    ClassB : "ClassB",
    ClassObj:{
    //对象法: 绑定的是键名、值为true时显示、反之不显示、一定要注意显示的是键名
    CA:true,
    CB:false
    },
    isA:true,
    isB:false
    }
    }
绑定Style
  • 基本语法

    :style="{ 属性名(可以使用驼峰命名或者-):'属性值', 属性名(可以使用驼峰命名或者-):'属性值' }"

    1
    <div :style="{fontSize:'26px',color:'red'}">我通过Style绑定多个CSS样式</div>
  • 通过对象法绑定

    1
    2
    3
    4
    5
    6
    7
    <div :style="StyleObj">我的style通过对象绑定了多个</div>

    //绑定Style
    StyleObj:{
    fontSize:'15px',
    color:'blue'
    }
  • 通过数组法绑定

    1
    2
    3
    4
    5
    6
    <div :style="[StyleObj]">我的style通过对象绑定了多个</div>

    //绑定Style
    StyleObj:{
    color:'blue'
    }
示例
查看代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<template>
<div>
<h1>绑定Class</h1>
<!-- 绑定一个class值 -->
<div :class="ClassA">我的class绑定了一个</div>
<!-- 数组法绑定多个class值 -->
<div :class="[ClassA,ClassB]">我的class绑定了多个</div>
<!-- 对象法绑定多个class值 -->
<div :class="ClassObj">我的class通过对象绑定了多个</div>
<!--同样:绑定的是键名、值为true时显示、反之不显示、一定要注意显示的是键名-->
<div :class="{CA:true,CB:true}">我的class通过对象绑定了多个</div>
<div class="{CA:isA,CB:isB}">我的class通过对象绑定了多个</div>

<h1>绑定Style</h1>
<!--fontSize使用的是驼峰命名-->
<div :style="{fontSize:'26px',color:'red'}">我通过Style绑定多个CSS样式</div>
<div :style="StyleObj">我的style通过对象绑定了多个</div>
</div>
</template>

<script>
export default {
name: "Study02",
data(){
return{
//绑定Class
ClassA : "ClassA",
ClassB:"ClassB",
ClassObj:{
//对象法: 绑定的是键名、值为true时显示、反之不显示、一定要注意显示的是键名
CA:true,
CB:false
},
isA:true,
isB:false,
//绑定Style
StyleObj:{
fontSize:'15px',
color:'blue'
}
}
}
}
</script>

渲染结果:

1
2
3
4
5
6
7
8
9
10
11
12
<div>
<h1>绑定Class</h1>
<div class="ClassA">我的class绑定了一个</div>
<div class="ClassA ClassB">我的class绑定了多个</div>
<div class="CA">我的class通过对象绑定了多个</div>
<div class="CA CB">我的class通过对象绑定了多个</div>
<div class="{CA:isA,CB:isB}">我的class通过对象绑定了多个</div>

<h1>绑定Style</h1>
<div style="font-size: 26px; color: red;">我通过Style绑定多个CSS样式</div>
<div style="font-size: 15px; color: blue;">我的style通过对象绑定了多个</div>
</div>

条件渲染

v-if

  • 基本语法

    v-if="data中的键名" v-if中为true将会显示元素、false会删除元素

    v-else-if="data中的键名" v–else-if中为true将会显示元素、false会删除元素

    v-else 都不符合将会显示

    1
    2
    3
    <div v-if="isShow">isShow为true我将会显示</div>
    <div v-else-if="isShow2">isShow为false,isShow2为true我将会显示</div>
    <div v-else>都为false我将会显示</div>
  • 小问题:实现动态切换标签 input复用问题

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <div id="app">
    <span v-if="isUser">
    <label for="username">用户账户</label>
    <input type="text" id="username" placeholder="用户账户">
    </span>
    <span v-else="isUser">
    <label for="email">用户邮箱</label>
    <input type="text" id="email" placeholder="用户邮箱">
    </span>
    <button @click="isUser=!isUser">切换类型</button>
    </div>

    const app = new Vue({
    el:'#app',
    data:{
    isUser:true
    }

    当我们在input中输入了内容后点击按钮切换类型、发现input中的数据并没有清空:Vue在进行DOM复用的时候,处于性能考虑,会尽可能的复用已经存在的元素,而不是重新创建。在未使用key的时候,在虚拟DOM上会在切换类型的时候,将第一个input直接保留放在切换后的input上,由于没有key标识,里面的内容依然保留。所以我们需要给input添加一个key(唯一值)属性可以

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <div id="app">
    <span v-if="isUser">
    <label for="username">用户账户</label>
    <input type="text" id="username" placeholder="用户账户" key="username">
    </span>
    <span v-else="isUser">
    <label for="email">用户邮箱</label>
    <input type="text" id="email" placeholder="用户邮箱" key="email">
    </span>
    <button @click="isUser=!isUser">切换类型</button>
    </div>

v-show

  • 基本语法

    v-show="布尔值"

    v-show值为true将会显示标签、false将会添加style=”display: none;” 不会删除元素

    1
    <div v-show="isShow">isShow为true我将会显示、为false将会隐藏</div

    问题:通过外层包裹div显示多个div会多渲染一个<div></div>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <div v-show="isShow3">
    <div>我是内容1</div>
    <div>我是内容2</div>
    </div>

    渲染结果为
    <div>
    <div>我是内容1</div>
    <div>我是内容2</div>
    </div>

    解决:通过template包裹的不会显示

    另一个问题:isShow4为假的时候同样会被显示,原因:在Vue单文件组件的template标签上使用v-if不生效的原因,简单解释一下就是单文件Vue只能包含一个template、所以最好用于v-for。

    1
    2
    3
    4
    <template v-show="isShow4">
    <div>我是内容1</div>
    <div>我是内容2</div>
    </template>
  • 示例

    查看代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    <template>
    <div>
    <h1>v-if添加判断</h1>
    <!-- v-if中添加为true将会显示元素、false会删除元素 -->
    <div v-if="isShow">isShow为true我将会显示</div>
    <div v-else-if="isShow2">isShow为false,isShow2为true我将会显示</div>
    <!-- 以上添加不符合将显示 -->
    <div v-else>都为false我将会显示</div>

    <h1>v-show</h1>
    <!-- v-show值为true将会显示标签、false将会添加style="display: none;" 不会删除元素 -->
    <!-- 问题:通过外层包裹div显示多个div会多渲染一个<div></div>-->
    <div v-show="isShow3">
    <div>我是内容1</div>
    <div>我是内容2</div>
    </div>
    <p>-------------------------------------</p>
    <!-- 解决:通过template包裹的不会显示-->
    <!-- 另一个问题:isShow4为假的时候同样会被显示,原因:https://blog.csdn.net/HermitSun/article/details/105189022 -->
    <template v-show="isShow4">
    <div>我是内容1</div>
    <div>我是内容2</div>
    </template>
    </div>
    </template>

    <script>
    export default {
    name: "Study02",
    data() {
    return {
    isShow: true,
    isShow2: false,
    isShow3: false,
    isShow4: true
    }
    },
    mounted() {
    setTimeout(() => {
    //2秒后将isShow设为false
    this.isShow = false
    this.isShow2 = true
    }, 2000);
    setTimeout(() => {
    //4秒后将isShow2设为false
    this.isShow2 = false
    }, 4000);
    }
    }
    </script>

    渲染结果(4秒后):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <div>
    <h1>v-if添加判断</h1>
    <div>都为false我将会显示</div>
    <h1>v-show</h1>
    <div style="display: none;">
    <div>我是内容1</div>
    <div>我是内容2</div>
    </div>
    <p>-------------------------------------</p>
    <div>我是内容1</div>
    <div>我是内容2</div>
    </div>

v-for

  • 基本语法

    1个参数时:[变量名、随便取] in [data中的可遍历数据键名]

    2个参数时:([变量名],[索引名]) in [data中的可遍历数据键名]

    3个参数时:([变量名],[键名],[索引名]) in [data中的可遍历数据键名]

    注意:Vue建议添加 key , key 代表唯一、更好渲染DOM

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <div v-for="array in arrays">{{array}}</div>

    <div v-for="(array,index) in arrays" :key="index">{{index}} - {{array}}</div>

    <div v-for="(array,key,index) in arrays" :key="index">{{index}} - {{key}} - {{array}}</div>

    data() {
    return {
    arrays: [1, 2, 3, 4, 5]
    }
    }

    数组中那些方法是响应式的

    方法: push() pop() shift() unshift() splice() sort() reverse() ...

    不是响应式的:通过数组索引之间修改数据、通过这个修改页面中的数据不会更新

    1
    2
    3
    4
    5
    methods:{
    updateArray(){
    this.array[0] = 18;
    }
    }
  • 遍历对象

    对象也可以被遍历 由于:key值为index会与上面相同、所以绑定key

    in 也可以用 of 进行替换

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    <div v-for="(obj,key,index) in objs" :key="key">{{index}} - {{key}} - {{obj}}</div>

    <ul :style="{textAlign:'left'}">
    <li v-for="person of people">{{person.name}} - {{person.sex}} - {{person.age}}</li>
    </ul>

    data() {
    return {
    objs: {
    name: "zykj",
    sex: "男",
    age: 18
    },
    people:[
    {
    name: "zykj",
    sex: "男",
    age: 18
    },
    {
    name: "skx",
    sex: "男",
    age: 16
    },
    {
    name: "y",
    sex: "女",
    age: 19
    }]
    }
    }
  • 为什么要绑定 key

    参考资料: VUE中演示v-for为什么要加key

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    <div>
    <input type="text" v-model="name">
    <button @click="add">添加</button>
    </div>
    <ul>
    <li v-for="(item, i) in list">
    <input type="checkbox"> {{item.name}}
    </li>
    </ul>


    data: {
    name: '',
    newId: 3,
    list: [
    { id: 1, name: '李斯' },
    { id: 2, name: '吕不韦' },
    { id: 3, name: '嬴政' }
    ]
    },
    methods: {
    add() {
    //注意这里是unshift
    this.list.unshift({ id: ++this.newId, name: this.name });
    this.name = '';
    }
    }

    当选中吕不为时,添加楠楠后选中的确是李斯,并不是我们想要的结果,我们想要的是当添加楠楠后,选中的是吕不为、此时我们需要绑定key

    添加前

    添加后

    可以简单的这样理解:加了key(一定要具有唯一性)、id的checkbox跟内容进行了一个关联。是我们想达到的效果

    原理 :

    为什么要在v-for中添加key

  • 示例

    查看代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    <template>
    <div>
    <h1>v-for遍历</h1>
    <!-- [变量名、随便取] in [data中的可遍历数据键名] -->
    <div v-for="array in arrays">{{array}}</div>

    <!-- 2个参数时:([变量名],[索引名]) in [data中的可遍历数据键名] -->
    <!--Vue建议添加key,key代表唯一、更好渲染DOM-->
    <div v-for="(array,index) in arrays" :key="index">{{index}} - {{array}}</div>
    <!-- 3个参数时:([变量名],[键名],[索引名]) in [data中的可遍历数据键名] -->
    <div v-for="(array,key,index) in arrays" :key="index">{{index}} - {{key}} - {{array}}</div>

    <!--对象也可以被遍历 由于:key值为index会与上面相同、所以绑定key-->
    <div v-for="(obj,key,index) in objs" :key="key">{{index}} - {{key}} - {{obj}}</div>

    <ul :style="{textAlign:'left'}">
    <!-- in 也可以用 of 进行替换 -->
    <li v-for="person of people">{{person.name}} - {{person.sex}} - {{person.age}}</li>
    </ul>
    </div>
    </template>

    <script>
    export default {
    name: "Study04",
    data() {
    return {
    arrays: [1, 2, 3, 4, 5],
    objs: {
    name: "zykj",
    sex: "男",
    age: 18
    },
    people:[
    {
    name: "zykj",
    sex: "男",
    age: 18
    },
    {
    name: "skx",
    sex: "男",
    age: 16
    },
    {
    name: "y",
    sex: "女",
    age: 19
    }]
    }
    }
    }
    </script>

    渲染结果:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <div>
    <h1>v-for遍历</h1>
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <div>4</div>
    <div>5</div>
    <div>0 - 1</div>
    <div>1 - 2</div>
    <div>2 - 3</div>
    <div>3 - 4</div>
    <div>4 - 5</div>
    <div>0 - name - zykj</div>
    <div>1 - sex - 男</div>
    <div>2 - age - 18</div>
    <ul style="text-align: left;">
    <li>zykj - 男 - 18</li>
    <li>skx - 男 - 16</li>
    <li>y - 女 - 19</li>
    </ul>
    </div>

事件监听

v-on

  • 基本语法

    v-on:xxx="函数名\表达式"或者简写 @xxx="函数名\表达式" 如:@click="xxx"、@sumbit="xxx"、@input="xxx"(表单输入事件)

    methods中写对象的函数方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    <div>当前number:{{number}}</div>

    <button v-on:click="add">点我number加一哟</button>

    <button @click="reduce">点我number减一哟</button>
    <!-- $event为事件对象、当第一个参数为自定义参数时、想获得事件对象可以添加第二参数$event-->
    <button @click="reduce(2,$event)">点我number减2哟</button>

    methods: {
    add() {
    this.number++;
    },
    reduce(val,event) {
    //当有两个参数时
    if (typeof val == 'number') {
    this.number -= val;
    //默认有一个事件 MouseEvent
    console.log(event);
    }
    // if(typeof val == 'object'){
    //只有一个参数时
    else {
    this.number--;
    console.log(val);
    }
    }
    }

    注意点:

    1. 当函数没有参数时、可以简写成 @click="getName" , 当然 @click="getName()" 也是可以的

    2. 函数参数:

      无传入参数时:默认有一个 event事件对象

      1
      2
      3
      4
      5
      6
      <button v-on:click="add">点我number加一哟</button>

      add(event) {
      console.log(event);
      this.number++;
      }

      有参数传入时、又想手动传入事件对象、可以传入 $event

      1
      2
      3
      4
      5
      6
      <button v-on:click="add(2,$event)">点我number加n哟</button>

      add(num,event) {
      this.number -= num;
      console.log(event);
      }
  • $set$delete

    当我们想动态添加属性和删除数据时、使用$set或者 $delete

    1. 不能直接通过 this.xxx[0] = { … } 添加
    2. 可以使用 $set(target, key, value)添加 (target可以是对象或数组[那么对应的key就是索引],key 可以是字符串或数字,可以是任何类型)
    3. js 方法数组名.splice(起始位置,删除个数,添加元素) 删除添加
    4. 可以使用 $delete(target, key)添加,target: 可以是对象[那么对应的key就是属性名]或数组,key : 可以是字符串或数字
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    <ul :style="{textAlign:'left'}">
    <li v-for="person of people" :key="people.id">{{person.name}} - {{person.sex}} -{{person.age}}</li>
    </ul>

    <button @click="AddPerson">添加一个人</button>
    <button @click="RemovePerson">删除一个人</button>
    <button @click="UpdatePerson">更新一个人</button>

    methods: {
    AddPerson() {
    //push()向数组的末尾添加一个或更多元素,并返回新的长度。 头部添加unshift
    this.people.push({
    create: Date.now(),
    name: "zykj",
    sex: "男",
    age: 18
    })
    },
    RemovePerson() {
    //pop()删除并返回数组的最后一个元素。头部删除shift
    this.people.pop();
    },
    UpdatePerson() {
    //Vue 不允许在已经创建的实例上动态添加新的根级响应式属性
    // this.people[0] = {
    // create: Date.now() ,
    // name: "zykj",
    // sex: "男",
    // age: 18
    // } // 这是错误的

    //如果我们需要在运行过程中实现属性的添加,set 方法
    //参数:(target, key, value) (target可以是对象或数组,可以是字符串或数字,可以是任何类型)
    //这里的0代表索引
    // this.$set(this.people,0,{
    // create: Date.now() ,
    // name: "我修改了数据",
    // sex: "女",
    // age: 15
    // })

    //或者原生的js方法:就是通过splice删除一个元素,并且添加一个元素
    this.people.splice(0, 1, {
    create: Date.now(),
    name: "我修改了数据",
    sex: "女",
    age: 15
    })
    }
    }

set 与 delete

Vue 不允许在已经创建的实例上动态添加新的根级响应式属性。

Vue 不能检测到对象属性的添加或删除,最好的方式就是在初始化实例前声明根级响应式属性,哪怕只是一个空值。

如果我们需要在运行过程中实现属性的添加或删除,则可以使用全局 Vue,Vue.set 和 Vue.delete 方法。

  • Vue.set

    Vue.set 方法用于设置对象的属性,它可以解决 Vue 无法检测添加属性的限制,语法格式如下:

    1
    Vue.set( target, key, value )

    参数说明:

    • target: 可以是对象或数组
    • key : 可以是字符串或数字
    • value: 可以是任何类型
  • Vue.delete

    Vue.delete 用于删除动态添加的属性 语法格式如下:

    1
    Vue.delete( target, key )

    参数说明:

    • target: 可以是对象或数组
    • key : 可以是字符串或数字
  • 示例

    查看代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    <template>
    <div>
    <h1>事件监听v-on</h1>
    <h2>操作数组</h2>
    <div>当前number:{{number}}</div>
    <!-- 通过v-on绑定一个点击事件add、在methods上写add方法 -->
    <button v-on:click="add">点我number加一哟</button>
    <!-- v-on也可以简写成@ -->
    <button @click="reduce">点我number减一哟</button>
    <!-- $event为事件对象、当第一个参数为自定义参数时、想获得事件对象可以添加第二参数$event-->
    <button @click="reduce(2,$event)">点我number减2哟</button>

    <div v-if="isShow">我是v-if</div>
    <div v-else>我是v-else</div>
    <button @click="toggle">切换isShow的值</button>

    <ul :style="{textAlign:'left'}">
    <li v-for="person of people" :key="people.id">{{person.name}} - {{person.sex}} - {{person.age}}</li>
    </ul>
    <button @click="AddPerson">添加一个人</button>
    <button @click="RemovePerson">删除一个人</button>
    <button @click="UpdatePerson">更新一个人</button>
    <p>----------------------------------------------------</p>
    <h2>操作对象</h2>
    <ul>
    <li v-for="(obj,key,index) in objs">{{ index }} - {{key}} - {{obj}}</li>
    </ul>
    <button @click="AddAttr">添加属性</button>
    <button @click="DeleteAttr">删除属性</button>
    <button @click="UpdateAttr">修改属性</button>
    </div>
    </template>

    <script>
    export default {
    name: "Study05",
    data() {
    return {
    number: 1,
    isShow: true,
    people: [
    {
    create: 1,
    name: "zykj",
    sex: "男",
    age: 18
    },
    {
    create: 2,
    name: "skx",
    sex: "男",
    age: 16
    },
    {
    create: 3,
    name: "y",
    sex: "女",
    age: 19
    }
    ],
    objs: {
    name: "zykj",
    sex: "男",
    age: 20
    },
    }
    },
    methods: {
    add() {
    this.number++;
    },
    //默认有一个事件 MouseEvent
    //reduce(event) {
    reduce(val, event) {
    //当有两个参数时
    if (typeof val == 'number') {
    this.number -= val;
    console.log(event);
    }
    // if(typeof val == 'object'){
    //只有一个参数时
    else {
    this.number--;
    console.log(val);
    }
    },
    toggle() {
    this.isShow = this.isShow ? false : true;
    },
    AddPerson() {
    //push()向数组的末尾添加一个或更多元素,并返回新的长度。 头部添加unshift
    this.people.push({
    create: Date.now(),
    name: "zykj",
    sex: "男",
    age: 18
    })

    },
    RemovePerson() {
    //pop()删除并返回数组的最后一个元素。头部删除shift
    this.people.pop();
    },
    UpdatePerson() {
    //Vue 不允许在已经创建的实例上动态添加新的根级响应式属性
    // this.people[0] = {
    // create: Date.now() ,
    // name: "zykj",
    // sex: "男",
    // age: 18
    // }

    //如果我们需要在运行过程中实现属性的添加,set 方法
    //参数:(target, key, value) (target可以是对象或数组,可以是字符串或数字,可以是任何类型)
    //这里的0代表索引
    // this.$set(this.people,0,{
    // create: Date.now() ,
    // name: "我修改了数据",
    // sex: "女",
    // age: 15
    // })

    //或者原生的js方法:就是通过splice删除一个元素,并且添加一个元素
    this.people.splice(0, 1, {
    create: Date.now(),
    name: "我修改了数据",
    sex: "女",
    age: 15
    })
    },
    AddAttr(){
    this.$set(this.objs,"hobby","打代码")
    },
    DeleteAttr(){
    //方法1:
    //(target, key)target: 可以是对象或数组,key : 可以是字符串或数字
    //this.$delete(this.objs,"sex")

    //方法2:
    let _obj = {...this.objs}; // ... 扩展运算符这里用于复制对象
    delete _obj.age;
    this.objs = {..._obj};
    },
    UpdateAttr(){
    this.objs.age = 18
    }
    }
    }
    </script>

    渲染结果:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    <div>
    <h1>事件绑定v-on</h1>
    <h2>操作数组</h2>
    <div>当前number:1</div>
    <button>点我number加一哟</button>
    <button>点我number减一哟</button>
    <button>点我number减2哟</button>
    <div>我是v-if</div>
    <button>切换isShow的值</button>
    <ul style="text-align: left;">
    <li>zykj - 男 - 18</li>
    <li>skx - 男 - 16</li>
    <li>y - 女 - 19</li></ul>
    <button>添加一个人</button>
    <button>删除一个人</button>
    <button>更新一个人</button>
    <p>----------------------------------------------------</p>
    <h2>操作对象</h2>
    <ul>
    <li>0 - name - zykj</li>
    <li>1 - sex - 男</li>
    <li>2 - age - 18</li>
    </ul>
    <button>添加属性</button>
    <button>删除属性</button>
    <button>修改属性</button>
    </div>

    扩展运算符复习: https://zykjofficial.tk/posts/8cde864d/#扩展运算符-…变量

事件修饰符

修饰符

在事件处理程序中调用 event.preventDefault()event.stopPropagation() 是非常常见的需求。尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。

为了解决这个问题,Vue.js 为 v-on 提供了事件修饰符。修饰符是由点开头的指令后缀来表示的。

  • .stop - 调用 event.stopPropagation()。阻止冒泡。 例: v-on:click.stop="xxx" , v-on:submit.stop="xxx"

  • .prevent - 调用 event.preventDefault()。 阻止默认行为。

  • .capture - 添加事件侦听器时使用捕获模式。 两种模式 捕获模式冒泡模式

  • .self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。

  • .native - 监听组件根元素的原生事件。用于自定义控件。也就是说在自定义组件中添加事件需要加上

  • .once - 只触发一次回调。

  • .left - (2.2.0) 只当点击鼠标左键时触发。

  • .right - (2.2.0) 只当点击鼠标右键时触发。

  • .middle - (2.2.0) 只当点击鼠标中键时触发。

  • .passive - (2.3.0) 以 { passive: true } 模式添加侦听器、passive这个修饰符会执行默认方法

    原因:浏览器只有等内核线程执行到事件监听器对应的JavaScript代码时,才能知道内部是否会调用preventDefault函数来阻止事件的默认行为,所以浏览器本身是没有办法对这种场景进行优化的。这种场景下,用户的手势事件无法快速产生,会导致页面无法快速执行滑动逻辑,从而让用户感觉到页面卡顿。

    通俗点说就是每次事件产生,浏览器都会去查询一下是否有preventDefault阻止该次事件的默认动作。我们加上passive就是为了告诉浏览器,不用查询了,我们没用preventDefault阻止默认动作。

    ​ 这里一般用在滚动监听,@scoll,@touchmove 。因为滚动监听过程中,移动每个像素都会产生一次事件,每次都使用内核线程查询prevent会使滑动卡顿。我们通过passive将内核线程查询跳过,可以大大提升滑动的流畅度。
    注:passive和prevent冲突,不能同时绑定在一个监听器上。

键盘事件
  • 基本语法

    @key(down/up).[对应的键(可选)]="函数名" 例: @keydown="Key" @keyup.ctrl="KeyCtrl"

    常用的按键修饰符:

    1
    2
    3
    4
    .enter  |  .tab  |  .delete  |  .esc
    .space | .up | .down | .left | .right
    .ctrl | .alt | .shift | .meta
    .键值
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    Ctrl<input @keydown.ctrl="KeyCtrl" type="text" />
    Submit <input @keydown.enter="SubmitEvent" type="text" />
    Space <input @keydown.space="SpaceEvent" type="text" />
    Delete <input @keydown.delete="DeleteEvent" type="text"/>

    methods: {
    KeyCtrl(){
    console.log("点击了Ctrl")
    },
    SubmitEvent(){
    console.log("进行提交")
    },
    SpaceEvent(){
    console.log("按了空格")
    },
    DeleteEvent(){
    console.log("点了删除")
    }
    }
示例
查看代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<template>
<div>
<h1>事件修饰符</h1>
<!-- .stop可以阻止冒泡事件 -->
<div @click="Father">
我是父DIV
<div @click.stop="Son">我是子DIV</div>
</div>

<!-- .prevent可以阻止默认事件、这里阻止了右键弹出的事件,right代表右键 -->
<div @click.right.prevent="Right">右键点击</div>
输入内容右键不会弹出<input type="text" @click.right.prevent="Right">

<div @click.middle="Log">鼠标中键</div>
<div @click.left="Log">鼠标左键</div>

<!-- .self修饰符只有在点击事件绑定的元素与当前被点击元素一致时才触发点击事件 -->
<div @click.self="Father">
我是父DIV
<div @click="Son">我是子DIV</div>
</div>

<!-- .once 只触发一次回调-->
<div @click.once="Father">我只会调用一次</div>

<!-- 键盘事件 keydown -->
Ctrl<input @keydown.ctrl="KeyCtrl" type="text" />
Submit <input @keydown.enter="SubmitEvent" type="text" />
Space <input @keydown.space="SpaceEvent" type="text" />
Delete <input @keydown.delete="DeleteEvent" type="text"/>
</div>
</template>

<script>
export default {
name: "Study05",
data() {
return {

}
},
methods: {
Father(){
console.log("Father被点击了");
},
Son(){
console.log("Son被点击了");
},
Right(){
console.log("点击了右键");
},
KeyCtrl(){
console.log("点击了Ctrl")
},
SubmitEvent(){
console.log("进行提交")
},
SpaceEvent(){
console.log("按了空格")
},
DeleteEvent(){
console.log("点了删除")
},
Log:function () {
console.log("-----------")
}
}
}
</script>

渲染结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div>
<h1>事件修饰符</h1>
<div>
我是父DIV
<div>我是子DIV</div>
</div>
<div>右键点击</div>
输入内容右键不会弹出<input type="text">
<div>
我是父DIV
<div>我是子DIV</div>
</div>
Ctrl<input type="text">
Submit <input type="text">
Space <input type="text">
Delete <input type="text">
</div>

计算属性与侦听属性

计算属性

计算属性(computed)是自动监听依赖值的变化,从而动态返回内容,监听是一个过程,在监听的值变化时,可以触发一个回调,并做一些事情。它有以下几个特点:

  • 数据可以进行逻辑处理,减少模板中计算逻辑。
  • 对计算属性中的数据进行监视
  • 依赖固定的数据类型(响应式数据)

计算属性由两部分组成:getset,分别用来获取计算属性和设置计算属性。默认只有get,如果需要set,要自己添加。另外set设置属性,并不是直接修改计算属性,而是修改它的依赖。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<div>{{ fullName }}</div>
<button @click="change">修改</button>
<button @click="changeFirstName('改了FirstName')">修改FirstName</button>
<button @click="changeLastName('改了LastName')">修改LastName</button>

var vue = new Vue({
data() {
return {
firstName: "卓越",
lastName: "科技"
}
},
methods: {
changeFirstName(val) {
this.fullName = val + " " + this.lastName
},
changeLastName(val) {
this.fullName = this.firstName + " " + val
}
},
computed: {
//fullName简写形式
//fullName(){
// return this.firstName + " " + this.lastName;
//},
fullName: {
//里面还有两个方法:set 当修改数据的时候调用。get 获取值的时候调用
set(newVal) {
console.log("newVal的新值:" + newVal)
let array = newVal.split(" ");
this.firstName = array[0]; //对它的依赖进行赋值
this.lastName = array[1];
},
get() {
return this.firstName + " " + this.lastName;
}
}
}
})

同个修改 fullName 时,setter 会被调用,firstName 和 lastName 也会相应地被更新。

  • 计算属性普通属性的区别:可以像绑定普通属性一样在模板中绑定计算属性,在定义上有区别:计算属性的属性值必须是一个函数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    data:{ 
    //普通属性
    msg:'哈哈哈',
    },
    computed:{
    //计算属性
    msg1:function(){
    //该函数必须有返回值,用来获取属性,称为get函数
    return '哈哈哈';
    },
    reverseMsg:function(){
    //可以包含逻辑处理操作,同时reverseMsg依赖于msg,一旦msg发生变化,reverseMsg也会跟着变化
    return this.msg.split(' ').reverse().join(' ');
    }
    }
  • 计算属性方法的区别:两者最主要的区别:computed 是可以缓存的,methods 不能缓存;只要相关依赖没有改变,多次访问计算属性得到的值是之前缓存的计算结果,不会多次执行。

    下面代码看方法和计算属性执行次数:结果: getFullName() 执行2次 fullName 执行1次

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    <div>{{ fullName }}</div>
    <div>{{ fullName }}</div>

    <div>{{ getFullName() }}</div>
    <div>{{ getFullName() }}</div>

    var vue = new Vue({
    data() {
    return {
    firstName: "卓越",
    lastName: "科技"
    }
    },
    methods: {
    getFullName(){
    console.log("------getFullName------")
    return this.firstName + " " + this.lastName;
    }
    },
    computed: {
    fullName: {
    get() {
    console.log("------fullName------")
    return this.firstName + " " + this.lastName;
    }
    }
    }
    })

侦听属性

有的时候,我们需要的派生数据是通过异步的方式处理的,这个时候,计算属性就不太好用了(不能处理异步)。我们可以使用另外一个选项:watch

  • watch : 侦听属性;监听的是data的属性,当属性发生改变以后,会做的一些事情

  • 里面传一个函数,第一个参数是最新的值,第二个参数是修改前的值

    1
    2
    3
    4
    5
    watch:{
    data中的属性名:function(newVal,oldVal){
    console.log(newVal,oldVal)
    }
    }
  • 深度监听: 如果监听了对象,当这个对象中的属性名对应的键值对发生改变以后,并不会触发监听的这个对象的函数;因为这个引用数据类型的地址没发生改变;

    这个时候需要把watch监听的方法改成对象的写法

    handler 相当于函数
    deep:true,对这个对象中的每一个属性进行监听
    immediate:true, 可以让函数立即执行一次;当其中一个属性发生改变,也会触发handler这个函数;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    watch:{
    data中的属性名: {
    handler(){

    },
    //immediate表示在watch中首次绑定的时候,是否执行handler,值为true则表示在watch中声明的时候,就立即执行handler方法,值为false,则和一般使用watch一样,在数据发生变化的时候才执行handler。
    immediate:true
    }
    }
  • 监听对象的时候写在handler方法的参数只写一个就可以,这个参数代表改变之后的值

  • 如果想监听对象里的一个属性值可以写成对象.属性名 ,这个时候写在handler方法的参数就得写两个,
    第一个参数是最新的值,第二个参是修改前的值

  • 另一种添加监视的方法: vm.$watch("XX",function(value){})

示例

查看代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
<template>
<div>
<h1>计算属性</h1>
<!--问题:如果表达式过于复杂会导致难以维护、所以我们将使用计算属性computed -->
<p>{{msg + " : " + type}}</p>

<!-- 作用: computed会进行缓存、函数会一直调用、性能低-->
<div>{{ msg_type }}</div>
<!-- 函数调用 -->
<div>{{ getFullName() }}</div>

<div>{{ fullName }}</div>
<button @click="change">修改</button>

<h1>监听属性</h1>
<div>content内容: {{ct}}</div>
<button @click="changeContent">改变content内容</button>
<!--
computed使用场景:某个数据受多个数据影响,或者需要对其他数据进行
js处理再显示;
watch使用场景:一个数据的变化会影响多个数据,或者一个数据变化的
时候需要执行异步操作
-->

<div>默认语言:{{ language }}</div>
<button @click="swit('chinese')">切换为中文</button>
<button @click="swit('english')">切换为English</button>
<div>{{ dl }}</div>

</div>
</template>

<script>
export default {
name: "Study05",
data() {
return {
msg: "这里是msg的内容",
type: "这里是type的内容",
firstName: "卓越",
lastName: "科技",
ct: "我是内容",
language: "chinese",
dl: ''
}
},
methods: {
getFullName() {
//每次刷新浏览器都会调用方法
return this.firstName + " " + this.lastName
},
change() {
this.fullName = "zy kj"
},
changeContent() {
this.ct = "改变了Content的内容"
},
swit(val){
if (val === 'chinese'){
this.dl = "中文"
}
else if(val === "english"){
this.dl = "english"
}
}
},
computed: {
msg_type() {
//只有当data(这里是 msg、type)的内容改变才会重新调用、缓存在内存中
return this.msg + " " + this.type
},
// FullName(){
// //每次刷新浏览器都会调用方法
// return this.firstName + " " + this.lastName
// }

fullName: {
//里面还有两个方法:set 当修改数据的时候调用。get 获取值的时候调用
set(newVal) {
console.log("newVal的新值:" + newVal)
let array = newVal.split(" ")
this.firstName = array[0]
this.lastName = array[1];
},
get() {
return this.firstName + " " + this.lastName
}
}
},
watch: {
//普通的watch监听
ct (oldValue, newValue) {
console.log("改变之前的值:" + oldValue + " " + "改变之前的值:" + newValue);
},
//深度监听,可监听到对象、数组的变化
language : {
//问题:当值第一次绑定的时候,不会执行监听函数,只有值发生改变才会执行。如果我们需要在最初绑定值的时候也执行函数,则就需要用到immediate属性。
handler(val){
if (val === 'chinese'){
this.dl = "中文"
}
else if(val === "english"){
this.dl = "english"
}
},
//immediate表示在watch中首次绑定的时候,是否执行handler,值为true则表示在watch中声明的时候,就立即执行handler方法,值为false,则和一般使用watch一样,在数据发生变化的时候才执行handler。
immediate:true
}
}
}
</script>

渲染结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div>
<h1>计算属性</h1>
<p>这里是msg的内容 : 这里是type的内容</p>
<div>这里是msg的内容 这里是type的内容</div>
<div>卓越 科技</div>
<div>卓越 科技</div>
<button>修改</button>
<h1>监听属性</h1>
<div>content内容: 我是内容</div>
<button>改变content内容</button>
<div>默认语言:chinese</div>
<button>切换为中文</button>
<button>切换为English</button>
<div>中文</div>
</div>

双向绑定 v-model

本质: 它负责监听用户的输入事件,从而更新数据,并对一些极端场景进行一些特殊处理。同时,v-model会忽略所有表单元素的value、checked、selected特性的初始值,它总是将vue实例中的数据作为数据来源。 然后当输入事件发生时,实时更新vue实例中的数据。

基本语法

v-model="data中的键名"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<input type="text" v-model="msg">
input中的内容:{{ msg }}

data:{
msg:""
}


<input type="text" :value="msg" @input="changeValue">
<input type="text" :value="msg" @input="msg = $event.target.value">

data:{
msg:""
},
methods:{
changValue(event){
this.msg = event.target.value;
}
}

v-model修饰符

  • .lazy 在输入框失去焦点或者按回车键时才会更新值。
  • .number 输入框输入的内容,即使是数字,默认也是 string 类型,使用 .number 修饰符让其转换为 number 类型
  • .trim 自动过滤掉输入框的首尾空格

示例

查看代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
<template>
<div>
<h1>v-model双向绑定</h1>
<input type="text" v-model="content">
<div>这显示输入框的内容:{{ content }}</div>

<textarea v-model="content" rows="4" cols="30"></textarea>
<div>这显示textarea的内容:{{ content }}</div>
<select v-model="languageCode">
<option value="">请选择</option>
<option v-for="program in programs" :value="program.code" :key="program.code">{{program.name}}</option>
</select>
<!--问题:option的中第一个数据(请选择)不在data中、我们想只显示data中的数据、通过计算属性来解决-->
<div>{{ language }}</div>
<br>
<!--radio-->
<input type="radio" name="sex" v-model="sex" value="male">
<input type="radio" name="sex" v-model="sex" value=female >
<div>{{sex}}</div>
<br>
<!--checkbox-->
<input type="checkbox" v-model="re">记住我
<div>{{re}}</div>
<!--true-value与false-value为真为假的值-->
<input type="checkbox" true-value="Y" false-value="N" v-model="re2">记住我
<div>{{re2}}</div>

<input type="checkbox" name="pro" value="c" v-model="pro">c
<input type="checkbox" name="pro" value="java" v-model="pro">java
<input type="checkbox" name="pro" value="python" v-model="pro">python
<h4>第一种写法</h4>
<div>{{ "["+pro.join("、")+"]" }}</div>
<h4>第二种写法</h4>
<div>{{ pro }}</div>

<!--v-model修饰符-->
<!--.lazy可以理解为失去焦点后数据才会更新、就是鼠标不在输入框内-->
<input type="text" v-model.lazy="contentlazy">
<div>数据显示:{{contentlazy}}</div>
<!--.number可以将输入文本转换为数字类型、不能转换时显示原文本-->
<input type="text" v-model.number="contentnumber">
<div>数据显示:{{contentnumber}}</div>
<!--.trim可以去除两边空格-->
<input type="text" v-model.trim="contenttrim">
<div>数据显示:{{contenttrim}}</div>
</div>
</template>

<script>
export default {
name: "Study05",
data() {
return {
content: "",
languageCode: "",
programs: [
{
code: "Java",
name: "JAVA"
},
{
code: "Html",
name: "HTML"
},
{
code: "Python",
name: "PYTHON"
}
],
sex:"",
re:"",
re2:"",
pro: [],
contentlazy: "",
contentnumber: "",
contenttrim: ""
}
},
computed: {
language() {
//find() 方法为数组中的每个元素都调用一次函数执行:
//当数组中的元素在测试条件时返回 true 时, find() 返回符合条件的元素,之后的值不会再调用执行函数。如果没有符合条件的元素返回 undefined
//array.find(function(curnettValue, index, arr),thisValue)

//通过find查找data中programs数组中(program.code与languageCode相同的)、返回这个对象
let _programCode = this.programs.find(program => program.code === this.languageCode)
//由于languageCode默认值不在programs数组,默认为空,我们需要进行判断
return _programCode ? _programCode.name : ""
}
}
}
</script>

渲染结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<div>
<h1>v-model双向绑定</h1><input type="text">
<div>这显示输入框的内容:哈哈</div>
<textarea rows="4" cols="30"></textarea>
<div>这显示textarea的内容:哈哈</div>
<select>
<option value="">请选择</option>
<option value="Java">JAVA</option>
<option value="Html">HTML</option>
<option value="Python">PYTHON</option>
</select>
<div></div>
<br>
<input type="radio" name="sex" value="male"><input type="radio" name="sex" value="female">
<div>male</div>
<br><input type="checkbox">记住我
<div>true</div>
<input type="checkbox" true-value="Y" false-value="N">记住我
<div>Y</div>
<input type="checkbox" name="pro" value="c">c <input type="checkbox" name="pro" value="java">java
<input type="checkbox" name="pro" value="python">python
<div>[c、java]</div>
<input type="text">
<div>数据显示:哈哈</div>
<input type="text">
<div>数据显示:123</div>
<input type="text">
<div>数据显示:00 00</div>
</div>

过滤器

过滤器,过滤就是一个数据经过了这个过滤之后出来另一样东西,可以是从中取得你想要的,或者给那个数据添加点什么装饰,那么过滤器则是过滤的工具。

过滤器分为两种:全局过滤器局部过滤器

  • 全局过滤器:全局过滤器必须写在vue实例创建之前

    1
    2
    3
    4
    5
    6
    //过滤器一:(使用时没有参数,即{{ msg | 过滤器名字}})
    Vue.filter('过滤器名字', function (value) {
    //可以理解为需要过滤的值
    console.log(value);
    return value + "-----";
    })
  • 局部过滤器:在组件实例对象里挂载

    1
    2
    3
    4
    5
    6
    //过滤器二:(使用时有参数,即{{ msg | filterA("1","2")}})
    filters: {
    filterA:(val,msg1,msg2)=>{
    return value + msg1 + msg2;
    }
    }
  • 参数说明

    1
    2
    3
    一:(使用时没有参数,即{{ msg | 过滤器名字}})

    二:(使用时有参数,即{{ msg | filterA("1","2")}})
  • 使用方法

    1. 在双花括号插值

      1
      {{ msg | filter }}
    2. 在v-bind表达式中使用

      1
      <div v-bind:data="'ok' | globalFilter" ></div>
    3. 通过逗号形式

      1
      2
      3
      4
      5
      6
      7
      {{ 'a','b' | filterB }} )

      filters: {
      filterB:(msg1,msg2)=>{
      return msg1 + msg2; //ab
      }
      }

后续补充更多知识。。。

参考资料: