0%

一、Vue环境搭建及基础用法

详情请点阅读全文

一、项目初始化及安装

官网:https://cn.vuejs.org/

1.1安装及运行项目步骤

1.安装vue-cli(-g=-global)
    npm install -g vue-cli
    cnpm install -g vue-cli
2.初始化项目
    vue init webpack my-project
3.进入项目
    cd my-project
4.安装依赖
    npm install
5.启动项目
    npm run dev

1.1.2 小项目安装方式(推荐)

安装的目录简单,少很多杂东西,适合小项目

1
2
3
4
5
6
7
8
9
另一种创建项目的方式   (推荐)  ***

vue init webpack-simple vuedemo02

cd vuedemo02

cnpm install / npm install

npm run dev

1.1.3 vue-cli3安装

#### 官方文档:
https://cli.vuejs.org/zh/guide/installation.html
最新工具已经升级到cli3,可以更新一下,它的编译速度要快一些,命令稍有不同,其它都一样
如果装有vue-cli2需先卸载一下,再安装cli3

卸载cli2/1

1
2
3
npm uninstall vue-cli -g 

yarn global remove vue-cli 卸载

cli3创建项目命令

1
2
3
4
5
npm install -g @vue/cli
或者:
cnpm install -g @vue/cli
或者:
yarn global add @vue/cli

cli3运行项目命令

1
2
3
vue create hello-world
运行:npm run serve
编译:npm run build

1.2实际安装过程记录

注:到第3步后(作者)有个一串提示,直接回车即可,就会进入install vue-router

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
D:\a\vue-app>vue init webpack my-project #my-project即项目名字,可随便写
D:\a\vue-app>"node" "C:\Users\Administrator\AppData\Roaming\npm\\node_modules\v
ue-cli\bin\vue" init webpack my-project

? Project name hello_vue #即运行时标题显示的名字
? Project description hello_demo
? Author pasaulis
? Vue build (Use arrow keys)
? Vue build standalone
? Install vue-router? No #是否安装路由,没学,先不用
? Use ESLint to lint your code? No #代码检查,安装后会对代码格式严格检查,多个空格都报错
? Set up unit tests No #是否安装测试,不用
? Setup e2e tests with Nightwatch? No #也是测试相关
#是否自动帮我们安装npm依赖,用箭头按键【直接回车用npm即可】
? Should we run `npm install` for you after the project has been created? (recom
mended) (Use arrow keys)
> Yes, use NPM
Yes, use Yarn
No, I will handle that myself
......
# Project initialization finished!
# ==========至此即安装成功!目录下就有对应的项目了==============
To get started:
cd my-project
npm run dev
Documentation can be found at https://vuejs-templates.github.io/webpack
#进入目录,并运行项目
D:\a\vue-app>cd my-project
D:\a\vue-app\my-project>npm run dev

#显示如下即运行成功,在浏览器打开对应地址即可:
DONE Compiled successfully in 3953ms
I Your application is running here: http://localhost:8080

【效果】:
在这里插入图片描述

1.3项目目录结构

index.html:项目根视图
.postcssrc.js:postcss配置文件
static:静态文件目录

运行项目时自动打开浏览器配置

/config/index.js里的

1
autoOpenBrowser: false, #改成ture即可

上一步配置的信息可在package.json里看到,及修改

1
2
3
4
5
6
7
8
9
10
11
12
{
"name": "hello_vue",
"version": "1.0.0",
"description": "hello_demo",
"author": "pasaulis",
"private": true,
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev", #运行命令
"build": "node build/build.js" #打包命令
},
......

二、Vue基础

2.1Vue组件(src/components/Helloworld.vue):

包含三个部分:
    template:视图
    script:逻辑
    style:样式

2.2Mustache:模板(见2.3第4个)

表现形式:{{ 语法 }}
{{ hello }}
{{ 1+1 }}
{{ "哈哈" }}
{{ 0<10 ? '对的' : '错的' }}
{{ '注意:只能存在单行语句,并且不能作用在HTML属性' }}

2.3第一个实例Hello Vue

1. 根目录下:index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<!--【0】固定写法:入口点,页面宽度=设备宽度,缩放比例=原比例-->
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>hello_vue</title>
</head>
<body>
<div id="app"></div> <!--【1】main.js里定义的组件模板内容,将写到此处-->
<!-- built files will be auto injected -->
</body>
</html>

2.入口文件:/src/mian.js

1
2
3
4
5
6
7
8
9
10
11
12
13
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
el: '#app', //【1】:在index.html里id为#app标签里写入组件内容
components: { App },//【2】:写入的组件
template: '<App/>' //【3】:写入的模板名(也可看成一个完整组件)
})

3.主组件 /src/App.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
27
28
<template>
<div id="app">
<!-- <img src="./assets/logo.png"> -->
<HelloWorld/> <!-- 【2】第二步,调用子组件 -->
</div>
</template>

<script>
import HelloWorld from './components/HelloWorld' #【1】第1步,引入子组件省略了.vue 原 HelloWorld.vue

export default {
name: 'App',
components: {
HelloWorld #【3】第3步,把组件写到此处,目的是把它暴露出去
}
}
</script>

<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>

4. 子组件(主要内容):/src/components/HelloWorld.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
27
28
29
30
31
32
33
34
35
36
<template>
<div class="hello">
<h1>{{msg}}</h1>
{{1+1}}<br/>
{{4>8?'是的':'错的'}}
</div>
</template>

<script>
export default {
name: 'HelloWorld', //【1】当前组件名,在其它地方引入此组件时所用的名字
data () {
return {
msg: 'Hello Vue'
}
}
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

显示:
在这里插入图片描述

三、VUE基本指令:

3.0

v-html:渲染文本
v-text:渲染文本
v-bind:绑定动态的属性
v-bind的简写:(:)

3.1vue指令代码实例/src/components/HelloWorld.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
27
28
29
30
31
32
33
34
35
36
37
38
<template>
<div class="hello">
<p v-html="htm"></p> <!--【2】关键点:v-html="" 如果引号的对应data值含html代码,可解析-->
<p v-text="htm"></p> <!--【3】关键点:v-text="" 只能解析文本-->
<p v-bind:class="ha">v-bind示例:用于动态的属性绑定</p> <!--【4】关键点:v-bind=""-->
<p v-bind:id="wa">v-bind示例2:</p> <!--【5】关键点:v-bind=""-->
<p :id="wa">v-bind示例:简写</p> <!--【5】关键点:v-bind=""-->
</div>
</template>

<script>
export default {
name: 'HelloWorld',
data () {
return {
msg: 'Hello Vue',
htm:'<h2>v-html渲染示例!</h2>',//【2和3】的数据
ha:'ha', //【4】的数据
wa:'wa' //【5】的数据
}
}
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
#模板出现的class,id对应的样式
#wa{
color: green;
}
.ha{
color: red;
}

h1, h2 {
font-weight: normal;
}
</style>

在这里插入图片描述

3.2条件渲染:

v-if
v-else
v-else-if
v-show

v-if,v-else示例:

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
<template>
<div class="hello">
<p v-if="s">【v-if和v-else实例】v-if:据条件显示/隐藏此处,为true时看到此处</p> <!-- 【1】 -->
<p v-else>v-else:为false看到此处</p> <!--【2】-->
</div>
</template>

<script>
export default {
name: 'HelloWorld',
data () {
return {
msg: 'Hello Vue',
s:false //【0】如果值为true则显示对应的模板
}
}
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1{
font-weight: normal;
}
</style>

结果:【0】处为ture时显示【1】处;false显示【2处】;

v-if,v-else,v-show,内部多层嵌套标签示例:

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
<template>
<div class="hello">
<!-- v-if v-else的隐藏是直接不渲染标签来实现的,注意和v-show的区分 -->
<div v-if="s"> <!-- 【1】如果v-if else内部有多层嵌套,则首层标签要用div;或<template></template>(渲染时不显示会第一层template) -->
<h1>v-if:为true时看到此处</h1>
<h2>v-if:h2内容</h2>
<p>v-if:p1内容</p> <!-- 且模板内其它标签除div之外,最好都不要嵌套,即使套了,也会渲染成同级标签 -->
<p>v-if:p2内容</p>
</div>
<div v-else><!-- 【2】如果v-if else内部有多层嵌套,则首层标签要用div;或<template></template>(渲染时不显示会不显示第一层template) -->
<h1>v-else:为false看到此处</h1>
<h2>v-else:h2内容</h2>
<p>v-else:p1内容</p>
<p>v-else:p1内容</p>
</div>

<!-- 【3】v-show的显示隐藏:此处不显示是利用css样式display:none;实现,标签还是会渲染进去的 -->
<div v-show="s">v-show:对应的data值为true就显示,false不显示</div>
</div>

</template>

<script>
export default {
name: 'HelloWorld',
data () {
return {
msg: 'Hello Vue',
s:false //【0】如果值为true则显示对应的模板
}
}
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1{
font-weight: normal;
}
</style>

结果:注意看箭头处,v-if的不显示是直接不渲染标签,v-show渲染后用css样式display:none实现隐藏
在这里插入图片描述

template的示例:不加v-if的顶层标签

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
<template>
<div class="hello">
<!-- v-if v-else的隐藏是直接不渲染标签来实现的,注意和v-show的区分 -->
<template v-if="s"> <!-- 【1】如果v-if else内部有多层嵌套,则首层标签要用div;或<template></template>(渲染时不显示会第一层template) -->
<h1>v-if:为true时看到此处</h1>
<h2>v-if:h2内容</h2>
<p>v-if:p1内容</p> <!-- 且模板内其它标签除div之外,最好都不要嵌套,即使套了,也会渲染成同级标签 -->
<p>v-if:p2内容</p>
</template>
<template v-else><!-- 【2】如果v-if else内部有多层嵌套,则首层标签要用div;或<template></template>(渲染时不显示会不显示第一层template) -->
<h1>v-else:为false看到此处</h1>
<h2>v-else:h2内容</h2>
<p>v-else:p1内容</p>
<p>v-else:p1内容</p>
</template>

<!-- 【3】v-show的显示隐藏:此处不显示是利用css样式display:none;实现,标签还是会渲染进去的 -->
<div v-show="s">v-show:对应的data值为true就显示,false不显示</div>
</div>
</template>

<script>
export default {
name: 'HelloWorld',
data () {
return {
msg: 'Hello Vue',
s:false //【0】如果值为true则显示对应的模板
}
}
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1{
font-weight: normal;
}
</style>

注意:看此处上级没有渲染template标签,如果不想要顶层标签时就可用这个template
在这里插入图片描述

3.2.1问题:v-if与v-show有什么区别?

  • v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
  • v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
  • 相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
  • 一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。

3.3列表渲染:v-for

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
<template>
<div class="hello">
<!-- v-for列表循环示例 -->
<ul>
<li v-for="n in news">{{n}}</li> <!-- 【循环】 注意v-for="引号里实际是js代码,因此不能用js的关键字如:此处要用new就报错" -->
</ul>

<!-- v-for循环字典 并用上第2个参数索引(value,index) 一般用于v-bind绑定key值-->
<ul>
<li v-for="(v,k) in info" v-bind:key="k">{{v.name}},{{v.age}},{{v.sex}}--{{k}}</li>
<!-- 注:v-bind:key='k' 可简写成 :key='k'-->
</ul>
</div>
</template>

<script>
export default {
name: 'HelloWorld',
data () {
return {
msg: 'Hello Vue',
s:false ,
news:['新闻标题1','新闻标题2','新闻标题3'],//【0】要循环的数据
info:[
{name:'小明',age:20,sex:'男'},
{name:'小红',age:21,sex:'女'},
{name:'小刚',age:22,sex:'男'}
]
}
}
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1{
font-weight: normal;
}
</style>

在这里插入图片描述

四、事件监听:

v-on:监听鼠标点击等事件
v-on简写方法(注意后面没冒号):@click
methods: 自写函数都写在此处
    事件参数:从事件中向函数传递参数
    事件修饰符:阻止事件默认的操作等等,详细见https://cn.vuejs.org/v2/guide/events.html

1.事件监听v-on代码实例:监听到点击则调用函数

主组件 /src/App.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
27
28
<template>
<div id="app">
<!-- <img src="./assets/logo.png"> -->
<JianTing/> <!-- 【2】第二步,调用子组件 -->
</div>
</template>

<script>
import JianTing from './components/JianTing' //【1】第1步,引入子组件

export default {
name: 'App',
components: {
JianTing //【3】第3步,把组件写到此处,目的是把它暴露出去
}
}
</script>

<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>

子组件(主要):/src/components/JianTing.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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<template>
<div>
<!-- 【1】v-on监听事件实例,直接写要执行的动作 -->
{{num}}<br/>
<button v-on:click='num+=1'>点此数数</button><br/>

<!-- 【2】用v-on监听事件,调用自写函数,并对data内的数据进行操作 -->
<h1 v-show="s">哈哈我显示了!</h1>
<button v-on:click='show_hidden'>点我显示/隐藏文本</button><br/>

<!-- 【3】监听事件v-on的简写:@ -->
<button @click='num+=1'>点此数数2</button><br/>

</div>
</template>

<script>
export default {
name: 'Jianting',//当前组件名字,其它组件调用时用到
data () {
return {
msg: 'jianTing',
num:1,
s:false ,
}
},
//[2]要调用的自写函数都写在此处
methods:{
show_hidden(){//【2】要调用此函数,对data里的s值取反,原来是false就改成true,反之亦然
this.s=!this.s;
}
}
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1{
font-weight: normal;
}
</style>

效果:
在这里插入图片描述

2.事件监听v-on代码实例:监听到点击则调用函数,向函数传递参数,传Event对象本身

JianTing.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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<template>
<div>
<!-- 【1】向函数传递参数 【2】$event:把event对象传给函数-->
<ul><!-- (value,name,index)分别为:值,键名,索引 -->
<li v-for="(value,name,index) in userInfo" v-bind:key='index' v-on:click="send(value,name,$event)" >{{value.name}}:{{value.age}}--{{value.sex}}--{{name}}</li>
</ul>

</div>
</template>

<script>
export default {
name: 'Jianting',//当前组件名字,其它组件调用时用到
data () {
return {
msg: 'jianTing',
num:1,
s:false,
userInfo:[
{name:'小明',age:20,sex:'男'},
{name:'小红',age:21,sex:'女'},
{name:'小刚',age:22,sex:'男'}
]
}
},
//要调用的自写函数都写在此处
methods:{//【2】读取模板里传过来的参数
send(value,name,event){
console.log(value.name,value.age,value.sex,name)
console.log(event) //【3】输出event对象,此处不用再加$符号
},
show_hidden(){//对data里的s值取反,原来是false就改成true,反之亦然
this.s=!this.s;
}
}
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1{
font-weight: normal;
}
</style>

效果:点对应的行,获取到其值,及传过来的event对象
在这里插入图片描述

3事件修饰符:阻止事件的默认动作

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

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

<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>

<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>

<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>

<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>

<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>

<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 -->
<!-- 而不会等待 `onScroll` 完成 -->
<!-- 这其中包含 `event.preventDefault()` 的情况 -->
<div v-on:scroll.passive="onScroll">...</div>

4按键修饰符

在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符:

1
2
3
<!-- 只有在 `key``Enter` 时调用 `vm.submit()` -->
<input v-on:keyup.enter="submit">
<input v-on:keyup.page-down="onPageDown">

5按键码

keyCode 的事件用法已经被废弃了并可能不会被最新的浏览器支持。
常用按键码别名:

1
2
3
4
5
6
7
8
9
.enter
.tab
.delete (捕获“删除”和“退格”键)
.esc
.space
.up
.down
.left
.right
1
<input v-on:keyup.13="submit">

6系统修饰键

1
2
3
4
5
6
7
8
9
10
.ctrl
.alt
.shift
.meta

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

<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>

7 .exact 修饰符

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

1
2
3
4
5
6
7
8
<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button @click.ctrl="onClick">A</button>

<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button @click.ctrl.exact="onCtrlClick">A</button>

<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button @click.exact="onClick">A</button>

四、数组更新检测:

变异方法:引起视图更新
替换数组:不会引起视图更新

1.更新data内数据,视图自动检测,并更新代码示例:

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>
<!--【3】点击2的按钮后,此处会自动检测到data里数据更新,重新渲染列表加入data里新加入的信息-->
<ul>
<li v-for="(value,index) in userInfo" v-bind:key='value.id'>{{value.name}}:{{value.age}}--{{value.sex}}--{{index}}</li>
</ul>
<!--【2】通过自写的p函数向userInfo里新加一条数据-->
<button v-on:click="p">点击传入新数据到userInfo里去,上面列表将被更新</button>
</div>
</template>

<script>
export default {
name: 'Jianting',//当前组件名字,其它组件调用时用到
data () {
return {
msg: 'jianTing',
num:1,
s:false,
userInfo:[//【0】要用到的数据
{name:'小明',age:20,sex:'男'},
{name:'小红',age:21,sex:'女'},
{name:'小刚',age:22,sex:'男'}
]
}
},

methods:{
p(){//【1】重点:利用push()向data的userInfo里新加入一条数据
this.userInfo.push({name:'小花',age:25})
},
show_hidden(){//对data里的s值取反,原来是false就改成true,反之亦然
this.s=!this.s;
}
}
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1{
font-weight: normal;
}
</style>

效果:点击按钮,数据增加,列表更新
在这里插入图片描述

2.显示过滤/排序结果:

filter()、concat() 和 slice()
它们不会改变原始数组,而总是返回一个新数组。当使用非变异方法时,可以用新数组替换旧数组

替换数组代码示例

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
<template>
<div>
<ul> <!-- 此处渲染data里的nums数组每个数字,一般对data内数据操作会影响视图,但此用.filter()处理就不会 -->
<li v-for="(v,i) in nums" :key="i">{{v}}</li>
</ul>
<!--【3】调用filter写的处理函数-->
<button v-on:click='getOdd'>点此获取奇数</button>
</div>
</template>

<script>
export default {
name: 'Jianting',
data () {
return {
msg: 'filter',
nums:[1,2,3,4,5,6,7,8,9],//【0】要用到的数据
}
},

methods:{
getOdd(){//【1】用.filter把原数组复制一份进行取奇数处理,此操作不会改变原始数据,因此不会改变视图
this.nums.filter((num)=>{//这里进行函数回调,处理nums内每一个数字,此处用箭头函数写法,官方用.filter(function(num){操作})
if(num%2==!0){
console.log(num)
}
})
},
p(){
this.userInfo.push({name:'小花',age:25})
}
}
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1{
font-weight: normal;
}
</style>

效果:
在这里插入图片描述

五、计算属性和观察者:computed

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

0.计算属性代码示例

1
2
3
4
5
<div id="example">
{{ message.split('').reverse().join('') }}
</div>
在这个地方,模板不再是简单的声明式逻辑。你必须看一段时间才能意识到,这里是想要显示变量 message 的翻转字符串。
当你想要在模板中多次引用此处的翻转字符串时,就会更加难以处理。

所以,对于任何复杂逻辑,都应当使用计算属性解决这个问题:

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
<template>
<div>
<p>此处是直接用语句处理单词反转:{{msg.split('').reverse().join('')}}</p>
<div>此处是用computed里写函数处理单词反转:{{reversedWord}}【2】</div>
<div>多次调用代码会少很多:{{reversedWord}}【3】</div>
</div>
</template>

<script>
export default {
name: 'Jianting',
data () {
return {
msg: 'hello',
nums:[1,2,3,4,5,6,7,8,9],
}
},

//所有自写函数都放在此处
methods:{
r(){
return console.log(this.msg.reversedWord)
}
},

//所有要有复杂处理逻辑的都放这里
computed:{//【1】单词反转
reversedWord:function(){ //此处也可写成 reversedWord(){
return this.msg.split('').reverse().join('')
}
},

}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1{
font-weight: normal;
}
</style>

效果:
在这里插入图片描述

1.计算属性和Methods区别

我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的依赖进行缓存的(即:computed里的方法只有数据变化时才会再次运算,而methods里每次都会运算)。计算属性只有在它的相关依赖发生改变时才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。

2.双向绑定:表单输入绑定 v-model,及监听watch:{}

v-model 双向数据绑定
watch:{} 对v-model监听

官方文档:https://cn.vuejs.org/v2/guide/forms.html

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
<template>
<div>
<p>【1】双向数据绑定:表单变<==>数据变</p>
<input v-model="msg" />
{{msg}}
</div>
</template>

<script>
export default {
name: 'Jianting',
data () {
return {
msg: 'hello',
nums:[1,2,3,4,5,6,7,8,9],
}
},

//所有自写函数都放在此处
methods:{
r(){
return console.log(this.msg.reversedWord)
}
},

// 监听文本框输入数据的改变
watch:{
//【2】msg必须和前面data里的对应,文本框里的文本如果变化,就接收它,并在控制台输出
msg:function(data){
console.log(data)
}
},

//所有要有复杂处理逻辑的都放这里
computed:{//单词反转
reversedWord:function(){ //此处也可写成 reversedWord(){
return this.msg.split('').reverse().join('')
}
},

}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1{
font-weight: normal;
}
</style>

效果:
在这里插入图片描述

3.双向绑定v-model的修饰符:lazy、trim、number

  1. v-model.lazy 当表单失去焦点时才进行监听
  2. v-model.trim 如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符
  3. v-model.number 如果想自动将用户的输入值转为数值类型,可以给 v-model 添加 number 修饰符
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
<template>
<div>
<p>【1】v-model.lazy在表单失去焦点点才进行监听</p>
<input v-model.lazy="msg" />
{{msg}}

</div>
</template>

<script>
export default {
name: 'Jianting',
data () {
return {
msg: 'hello',
nums:[1,2,3,4,5,6,7,8,9],
}
},

//所有自写函数都放在此处
methods:{
r(){
return console.log(this.msg.reversedWord)
}
},
// 监听文本框输入数据的改变
watch:{
//【2】v-model.lazy加上后此处也是表单失去焦点后才监听;
msg:function(data){//msg必须和前面data里的对应,文本框里的文本如果变化,就接收它,并在控制台输出
console.log(data)
}
},

//所有要有复杂处理逻辑的都放这里
computed:{//单词反转
reversedWord:function(){ //此处也可写成 reversedWord(){
return this.msg.split('').reverse().join('')
}
},

}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1{
font-weight: normal;
}
</style>

六、Class 与 Style 绑定

1.绑定 HTML Class
2.数组语法

1.动态绑定样式代码:根据data里数据决定是否加载样式

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>
<!-- 【1】用法:{样式名:bool} 为ture则加载样式,否则不加载 -->
<p v-bind:class="{red_color:is_no}">【1】样式动态绑定:根据data值确定是否加载样式</p>
<p v-bind:class="{red_color:is_no,s5:yes_no}">【2】样式动态绑定:动态绑定多个加载样式</p>
</div>
</template>

<script>
export default {
name: 'Jianting',
data () {
return {
msg: 'hello',
is_no:false ,//【2】此处值用于控制样式是否加载
yes_no:true
}
},

//所有自写函数都放在此处
methods:{},

// 监听文本框输入数据的改变
watch:{},

//所有要有复杂处理逻辑的都放这里
computed:{},

}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.red_color{color:red;} /* [1]要用到的样式 */
.s5{font-size: 25px;} /*[2]要用到的样式*/
</style>

效果:因为第【1】个样式的bool值设定成false,所以它没有加载;第【2】个是动态加载多个样式
在这里插入图片描述

2.动态绑定样式:把class=’xxx’里内容写到data字典里

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>
<!-- 【1】 -->
<p v-bind:class="styles1">【1】样式动态绑定:把多个动态样式控制放到data的字典里</p>
</div>
</template>

<script>
export default {
name: 'Jianting',
data () {
return {
msg: 'hello',
styles1:[//最终放到[1]里的内容即此处的styles1
{red_color:true,s25:false},//[1]用到的字典,解释:{样式名:bool} 为ture则加载样式,否则不加载
]
}
},

//所有自写函数都放在此处
methods:{},

// 监听文本框输入数据的改变
watch:{},

//所有要有复杂处理逻辑的都放这里
computed:{},

}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.red_color{color:red;} /* [1]要用到的样式 */
.s25{font-size: 25px;} /*[1]要用到的样式*/
</style>

效果:把样式控制写到data的字典里,(因为此样式设为ture所以加载了它,s25为false所以示加载)
在这里插入图片描述

3.用计算属性computed:{}写样式,麻烦

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
<template>
<div>
<!-- 【1】 -->
<p v-bind:class="styleObj">【1】样式动态绑定:用computed进行控制</p>
</div>
</template>

<script>
export default {
name: 'Jianting',
data () {
return {
msg: 'hello',
styles1:[//用到的字典控制样式名
{red_color:true,s25:false},//用到的字典控制样式
],
red_color:true,//用computed计算属性进行动态绑定样式的控制要用到的数据
s25:false,
}
},

//所有自写函数都放在此处
methods:{},

// 监听文本框输入数据的改变
watch:{},

//所有要有复杂处理逻辑的都放这里
computed:{
styleObj(){//样式用此处进行控制,样式最终用此名
return{
red_color:this.red_color,
s25:this.s25
}
}
},

}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.red_color{color:red;} /* [1]要用到的样式 */
.s25{font-size: 25px;} /*[1]要用到的样式*/
</style>

效果:
在这里插入图片描述

4.数组写法绑定样式

1
2
3
4
5
6
<div v-bind:class="[activeClass, errorClass]"></div>

data: {
activeClass: 'active',
errorClass: 'text-danger'
}

5.三目运算确定样式是否显示

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

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

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

6.绑定样式用在组件上

官网:https://cn.vuejs.org/v2/guide/class-and-style.html#用在组件上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Vue.component('my-component', {
template: '<p class="foo bar">Hi</p>'
})

然后在使用它的时候添加一些 class
<my-component class="baz boo"></my-component>

HTML 将被渲染为:
<p class="foo bar baz boo">Hi</p>

对于带数据绑定 class 也同样适用:
<my-component v-bind:class="{ active: isActive }"></my-component>

当 isActive 为 truthy[1] 时,HTML 将被渲染成为:
<p class="foo bar active">Hi</p>