vue项目开发(二)

六 Vue指令(Directive)

条件渲染指令

  • v-if
  • v-else (必须紧跟v-if其后)
  • v-show
    1
    2
    3
    区别:
    1.v-show通过改变元素的css属性display,v-if通过适当的销毁和重建元素,是真正的条件渲染
    2.v-if适合条件不经常改变的场景,v-show适合频繁切换

列表渲染指令v-for

  • 遍历数组

    1
    2
    3
    4
    <div v-for="(item,index) in items"></div>
    // item为每次遍历的元素
    // index为下标索引
    // item表示数组或对象
  • 遍历对象

    1
    2
    3
    4
    5
    <div v-for="(value,key,index) in personObj" :key="index"></div>

    // index 索引
    // key
    // value
  • key属性

    1
    2
    为了方便Vue实例跟踪每个节点的身份,从而重用或重新排列现有的元素
    key需要通过v-bind来绑定动态值,尽可能在使用v-for时提供key属性

方法和事件

v-on:事件名=”fn()” 函数定义在vue的选项methods中,没有参数时候后面的参数可以省略

  • v-on可以简写成@符号
  • 事件修饰符
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
//event的事件可以使用vue事件的修饰符来实现.在@绑定的事件后面加上小圆点,在跟一个后缀来是使用修饰符
1.stop
2.prevent
3.capture
4.self
5.once

<!-- 组织单击事件冒泡-->
<a href="" @click.stop='handle'>阻止单击事件冒泡</a>

<!-- 提交事件不再重载页面 -->
<form action="" @submit.prevent=''handle></form>

<!-- 修饰符可以串联 -->
<a href="" @click.stop.prevent='handle'></a>

<!-- 只有修饰符 -->
<form action="" @submit.prevent></form>

<!-- 添加事件侦听器时使用时间捕获模式 -->
<div @click.capture='handle'>..</div>

<!-- 只当事件在该元素本身(而不是子元素)触发时触发回调 -->
<div @click.self='handle'>..</div>

<!-- 只触发一次,组件同样适用 -->
<div @click.once='handle'>..</div>

<!-- 在表单元素上监听键盘事件时。还可以使用按键修饰符,比如按下具体的某个键时才调用方法 -->
<!-- 只有在keyCode是13时调用vm.submit() -->
<input type="text" @keyup.13='submit'>
<!--
也可以自己配置具体的按键
Vue.config.keyCodes.f1=112;
全局定义后,就可以使用@keyup.f1

除了某个具体的keyCode外,vue还提供了一些快捷名称,以下是全部的别名
.enter
.tab
.delete
.esc
.space
.up
.down
.left
.right
这些按键修饰符还可以组合使用,或和鼠标一起配合使用
.ctrl
.alt
.shift
.meta (mac下Command键 WIndows是窗口键)
-->

表单双向绑定v-model

  • v-model只能用在input,select,textarea等表单元素上
  • 修饰符
    1
    2
    1. lazy将改变默认的同步状态,在change事件中同步
    2. trim将自动过滤输入的首尾空格

七 组件详解

组件概念和复用

使用props传递数据

1
2
3
4
5
/*
组件的内容不仅仅是对模板的复用,更重要的是组件之间的通讯.
父组件向子组件传递数据和参数,子组件接收到参数后再根据参数的
不同来渲染不同的内容或执行操作,这个正向传递的过程就是通过props来实现的
*/

props来声明需要从父组件接受的数据,值类型为数组和对象,对象中可以自定义数据类型

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 class="page">
<h3>这是列表页</h3>
<button @click="skip()">跳转到详情页</button>
<!--使用组件-->
<list-item message="来自列表页的数据"></list-item>
</div>
</template>

<script>
//引入组件
import ListItem from "@/components/ticketlist/listitem"
export defalt{
components:{
ListItem //注册组件
}
}
</script>


//子组件
<template>
<div class="list">
<p>{{message}}</p>
</div>
</template>
<script>
export default{
props:['message']
}
</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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/*
业务中经常遇到两种需要改变props传递过来数据的情况
*/

//1.父组件传递初始值,子组件将其作为初始值保存起来
<template>
<div class="page">
<!--使用组件-->
<list-item :message="normalVariable"></list-item>
</div>
</template>

<script>
//引入组件
import ListItem from "@/components/ticketlist/listitem"
export defalt{
data(){
return{
mormalVariable:"初始值"
}
},
components:{
ListItem //注册组件
}
}
</script>

//子组件
<template>
<div class="page-child">
<p>{{receive}}</p>
</div>
</templte>
export dafault{
data(){
return{
receive:this.message //只需要维护receive不需要操作message
}
},
props:["message"]
}

//2.另一种情况是props作为需要被转变的原始值传入,这种情况用计算属性就可以了

组件通信

  • 自定义事件以及$emit方法
    1
    2
    3
    4
    5
    6
    this.$emit('event',val)
    /*
    vue实例方法$emit
    参数event为自定义事件名
    参数val代表通过自定义事件传递的值(可选)
    */

子组件传值给父组件的时候,事件触发及接受原则是: 谁触发的监听谁接受

  • 兄弟组件通信的处理方式
    1
    利用props和$emit的综合使用

slot插槽分发内容

  • 匿名插槽

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    //假设现在有一个弹出提示框,头部,中间,底部,只有中间区域改变
    // 子组件
    <div class="child>
    <slot>如果没有分内容则显示此段话</slot>
    </div>


    //父组件
    <child>
    <h1>显示弹出的内容</h1>
    </child>
  • 具名插槽

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // 子组件
    <div class="child>
    <slot name="CPU">CPU插槽</slot>
    <slot name="GPU">显卡插槽</slot>
    <slot name="Memory">内存插槽</slot>
    <slot name="Hard-drive">硬盘插槽</slot>
    </div>


    //父组件
    <child>
    <div slot="CPU"></div>
    <div slot="GPU"></div>
    <div slot="Memory"></div>
    <div slot="Hard-drive"></div>
    </child>

八计算属性和侦听器

计算属性
1
2
3
1、计算属性是基于他依赖缓存的,一个计算属性所依赖的数据发生变化的时候它才会重新计算取值
2、methods不同,只要重新渲染,方法就会被调,函数就会执行
3、究竟使用什么取决于是否需要缓存,当遍历大数组和计算量很大时,应使用计算属性,除非不希望得到缓存

九插件的使用

状态管理和vuex

  • 安装 cnpm installl vuex –save
  • 使用

    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
    //@/store/index.js
    import Vue from 'vue'
    import Vuex from 'vuex'
    Vue.use(Vuex)

    export default new Vuex.Store({
    state:{
    //state存放数据
    count:0
    },
    mutations:{
    //状态的变化
    increment:state=>state.count++,
    decrement:state=>state.count--
    }
    })

    // main.js中映入store

    import store from "@/store"
    //在实例中挂载
    new Vue({
    el:"#app",
    store,
    ....
    ...
    ..
    })


    // 新建组件page
    <template>
    <div class="page">
    <Button type="success" @click="increment">+</Button>
    <Button type="success" @click="decrement">-</Button>
    </div>
    </template>

    <script>
    export default {
    data(){
    return{

    }
    },
    methods:{
    increment(){
    this.$store.commit("increment")
    },
    decrement(){
    this.$store.commit("decrement")
    }
    },
    computed:{
    count(){
    return this.$store.state.count
    }
    }
    }
    </script>
  • 总结:引入Vuex后统一的对数据进行管理存放,在各个页面组件中使用commit方法提交mutation对共享数据进行修改

    案例:项目中统一管理登录状态的数据,如购票业务中,未登录的情况下如果点击购票肯定是会提示用户先登录,整个页面都会共享登录信息,也就是token标识,通过vuex很容易就拿到token值,方便后面的操作

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22

    const state={
    sLoginInfo:loginInfo //登录信息
    }
    const mutations={
    //登录
    mLogin:(state,loginInfo)=>{
    loginInfo.extTime-=0
    loginInfo.genTime-=0
    state.sLoginInfo=loginInfo
    window.localStorage.setItem(storageKey,JSON.stringify(loginInfo))
    }
    //退出
    mLogout:(state)=>{
    state.sLoginInfo={}
    window.localStorage.removeItem(storageKey)
    }
    }

    export default new Vuex.Store({
    state,mutations
    })

二维码插件 QRCode

微信支付流程

  • 1.确定微信支付时把当前订单号发送给后台
  • 2.后台利用订单号去数据库查询订单信息并整合微信官方等信息后发送给微信官方,微信官方会生成一个携带支付必要信息的链接给后台开发人员
  • 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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// cnpm install qrcode --save

<template>
<div class="page">
<div id="canvasArea">
<canvas id="canvas"></canvas>
</div>
</div>
</template>

<script>

import Vue from 'vue'
import QRCode from "qrcode"
Vue.use(QRCode)

export default {
data(){
return{}
},
methods:{
useqrcode(){
//放二维码的容器
var canvas=document.getElementById("canvas")
//调用函数生成二维码,参数依次为 容器,生成的内容,回调函数
QRCode.toCanvas(canvas,"http://www.baidu.com",function(err){
if(err){
console.error(err)
}else{
//成功之后可回调的函数
alert("success")
}
})
}
},
mounted () {
this.useqrcode() //组件挂载的时候调用二维码生成函数
}
}
</script>

<style>

</style>