Vue2笔记

一、Vue简介

vue是什么
  • vue.js是一套构建用户界面的框架
vue的两个特性
  • 数据驱动视图:数据的变化会驱动视图的自动更新
  • 双向数据绑定:js数据的变化,会被自动渲染到页面上;页面上表单采集的数据发生变化时,会被vue自动获取到,并更新到js数据中
MVVM

Model数据源,View视图,ViewModel是vue的实例

vue的基本使用
  • 导入vue.js的script脚本文件
  • 在页面中声明一个将要被vue控制的DOM区域
  • 创建vue实例对象
<div id="app">{{ username }}</div>
<script src="./lib/vue-2.6.12.js"></script>
<script>
    const vm = new Vue({
        el: '#app', // el属性,接收的值是一个选择器
        data: {
            username: 'zs'
        } // data对象是要渲染到页面上的数据
        methods: {
            // ...
        } // methods用于定义事件的处理函数
    })
</script>

二、Vue指令

内容渲染指令
  • v-text,会覆盖元素内部原有的内容
  • {{ }},插值表达式,不能用在属性节点
  • v-html,可以把带标签的字符串渲染成html
属性绑定指令
  • v-bind,为元素的属性动态绑定值,简写为:
<img :src="photo" alt="">

注意:插值表达式和属性绑定指令中可以写js表达式

事件绑定指令
  • v-on,简写为@,用于给元素绑定事件
  • 如果在方法中要修改data中的数据,可以通过this访问到
  • $event事件对象,防止事件传参覆盖事件对象e
<div id="app">
    <button @click="add(2,$event)"></buttton>
</div>
<script>
const vm = new Vue({
    el: '#app',
    methods:{
        add(step,e){ // e:事件对象
            const bgc = e.target.style.backgroundColor
            this.count += step
        }
    }
})
</script>
  • 事件修饰符.prevent阻止默认行为.stop阻止事件冒泡
<button @click.stop = "add(2,$event)"></button>
  • 按键修饰符.esc .enter
<input @keyup.esc = "clearInput">
双向数据绑定指令
  • v-model,只能用在表单元素上,页面上的改动同步到数据源
  • 修饰符
    • .number自动将用户输入值转换为数字型
    • .trim自动过滤用户输入的首尾空格
    • .lazychange时而非input时更新
条件渲染指令
  • 将根据表达式值(truefalse)决定是否显示元素
  • v-if,动态创建/移除元素
  • v-show,添加/移除display:none
  • v-else-if
  • v-else
<div v-if="type === 'A'">优秀</div>
<div v-else-if="type === 'B'">良好</div>
<div v-else-if="type === 'C'">一般</div>
<div v-else>差</div>
循环渲染指令
  • v-for
<li v-for="(item, index) in list" :key="item.id">姓名是:{{ item.name }}</li>
    ...
    data: {
        list[
            { id:1, name: 'zs'},
            { id:2, name: 'ls'},
            { id:3, name: 'ww'}
        ]
    }

注意:用索引当key没有意义


三、Vue过滤器,侦听器,计算属性

过滤器
  • 要定义到 filters 节点下,本质是一个函数
  • 在过滤器函数中,一定要有 return
  • 在过滤器的形参中,可以获取到管道符 | 前面待处理的那个值
<p>message的值是:{{ message | capi }}</p>
    ...
    filters: {
        capi(val){
            ...
        }
    }
  • 全局过滤器写法:
Vue.filter('函数名',funciton(过滤器前面的值){})

如果全局过滤器和私有过滤器名字一致,此时按照就近原则,调用的是私有过滤器

侦听器
  • 方法格式的侦听器
watch: { // username:要监听的data节点中的数据名
    username(newVal, oldVal){
        ...
    }
}
  • 对象格式的侦听器
watch: {
    username: {
        handler(newVal,oldVal) {
            ...
        },
        immediate: true, // 加载页面自动触发 
        deep: true // 深度监听对象中每个属性的变化
    }
}
  • 监听对象单个属性的变化
data: {
    info: {
        username: 'admin'
    }
},
watch:{
    'info.username': {
        handler(newVal,oldVal){
            ...
        }
    }
}
计算属性
  • 要定义到computed节点下,要被定义为方法
  • 在使用计算属性的时候,当普通的属性使用即可
  • return一个计算结果
  • 优点:实现了代码复用,只要计算属性中依赖的数据源变化了,则计算属性会自动重新求值

四、vue组件

组件的三个组成部分
<template>
    // 不能出现两个根元素
    ...
</template>

<style lang="less"> //启用less语法
    ...
<style>

<script>
export default {
  data() { //组件中的data必须是函数
    return {
      username: 'admin'
    }
  },
  methods: {
    changeName() {
      this.username = '哇哈哈'
    }
  },
  watch: {},
  computed: {},
  filters: {},
  components: {}
}
</script>
使用组件的三个步骤
  • 使用import语法导入需要的组件
  • 使用components节点注册节点
  • 以标签形式使用组件
<template>
    <div class="box">
        <Left></Left>
    </div>
</template>

<script>
import Left from '@/components/Left.vue'
export default {
    components: {
        'Left': Left
    }
}
</script>
...
注册全局组件

main.js中通过import导入组件

import Count from '@/components/Count.vue'

Vue.component('MyCount', Count)
组件间样式冲突
  • 默认情况下写在.vue中的样式全局生效,易造成样式冲突
  • 解决方法:给<style>标签添加scoped属性
  • /deep/样式穿透
    • 在父组件中改子组件样式,在子组件中加/deep/
    • 修改第三方组件默认样式
组件的生命周期
  • 生命周期:每个组件从创建->运行->销毁的一个过程
  • 生命周期函数:在生命周期的不同阶段,会按次序,自动执行的函数
  • beforeCreate
  • created
    • 可以调用 methods 中的方法,请求服务器的数据
    • 可以把请求到的数据,转存到 data 中,供 template 模板渲染的时候使用
  • beforeMount
  • mounted
    • 如果要操作当前组件的 DOM,最早,只能在 mounted 阶段执行
  • beforeUpdate
  • updated
    • 当数据变化之后,操作最新的 DOM 结构
  • beforeDestroy
  • destroyed

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rXONjjSS-1661245247524)(9886AC03753F4F70A231881FF3B8FD5C)]


五、组件间的数据共享

父向子传值:自定义属性
  • 子组件中,通过props来自定义属性
  • 父组件中,负责把数据,通过v-bind:绑定给子组件
  • props自定义属性:
    • 在封装通用组件时,可以利用props提高组件的复用性
    • props是只读的,若想修改可以把props的值转存到data
<MyCount :init="9"></MyCount>
    ...
    props: {
        init: {
            default: 0, // 默认值
            type: Number, // 值类型
            required: true // 必填项
        }
    }
子向父传值:自定义事件
  • 在子组件中调用this.$emit()来触发自定义事件
    • 参数1:字符串,表示自定义事件的名称
    • 参数2:值,要发送给父组件的数据
  • 在父组件中,通过v-on:来绑定自定义事件,并提供一个事件处理函数。通过事件处理函数的形参,接收到子组件传递过来的数据
// 子组件:
<button @click="onBtnClick"></button>
<scripts>
export default {
    // 触发自定义事件
    methods:{
        onBtnClick(){
           this.$emit('change',this.count)// 第二个参数用来传参
        }
    }
}
</scripts>
// 父组件
// 监听自定义事件
<mycounter @change="getCount"></mycounter>
<scripts>
export default {
    methods:{
        getCount(val){ // 接收this.count
            // ...
        }
    }
}
兄弟组件共享数据:EventBus
  • 数据发送方:导入eventBus.js,调用bus.$emit触发自定义事件
import bus from './eventBus.js'

export default {
    data() {
        return {
            msg: 'hello vue.js'
        }
    },
    methods: {
        sendMsg() {
            bus.$emit('share', this.msg)
        }
    }
}
  • EventBus模块:创建并向外导出Vue的实例对象
import Vue from 'vue'

export default new Vue()
  • 数据接收方:
    导入eventBus.js,调用bus.$on注册一个自定义事件
import bus from './eventBus.js'

export default {
    data() {
        return {
            msgFromLeft: ''
        }
    },
    created() {
        bus.$on('share', val=>{
            this.msgFromLeft = val
        })
    }
}

六、路由

路由简介
  • 概念:Hash地址path与组件component的对应关系
  • 工作方式
    • 用户点击了页面上的路由链接
    • 导致了URL地址栏中Hash值发生了变化
    • 前端路由监听到了Hash地址的变化
    • 前端路由把当前Hash地址对应的组件渲染到浏览器中
vue-router的安装配置
  • 安装vue-router
  • 创建路由模块:在src源码目录下,新建router/index.js路由模块
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const router = new VueRouter()
export default router
  • 导入并挂载路由模块,在main.js
import router from '@/router/index.js'
    ...
    new Vue({
        router: router
    })
  • 声明路由链接和占位符
    • 路由链接<router-link>可代替<a>
    • 占位符<router-view></router-view>
<a href="#/home">首页</a>
<router-link to="/home">首页</router-link>
  • 声明路由规则,在路由模块index.js
const router = new VueRouter({
    routes: [
        { path: '/', redirect: '/home' }, //重定向
        { path: '/home', component: Home },
        { path: '/movie', component: Movie }
    ]
})
嵌套路由
const router = new VueRouter({
    routes: [
        { path: '/about', component: About, children:[ // 子路由规则
            // 默认子路由:在children数组在,path值为空,展示父组件时默认展示
            { path: '', component: Tab1 },
            { path: 'tab2', component: Tab2 }
        ] },
    ]
动态路由
  • 概念:把Hash地址中可变的部分定义为参数项,从而提高路由规则的复用性
  • $route
    • 用冒号声明,:参数名
    • 路径参数,this.$route.params.参数名
    • 查询参数,this.$route.query
    • 完整路径,this.$route.fullPath
// 对应vue组件
<h3>{{ this.$route.params.mid }}</h3>
// index.js
{ path: '/movie/:mid', component: Movie }
  • 为路由规则开启props传参
// 对应vue组件
    props:['mid']
// index.js
{ path: '/movie/:mid', component: Movie, props: true }
编程式导航API
  • 概念:
    • 声明式导航:点击链接实现导航
    • 编程式导航:调用API方法实现导航
  • this.$router.push('hash地址')跳转到指定的hash地址,并增加一条历史记录
  • this.$router.replace('hash地址')跳转到指定的hash地址,并替换掉当前的历史记录
  • this.$router.go(数字n)可以在浏览历史中前进或后退
  • this.$router.forward()
  • this.$router.back()
导航守卫
  • 功能:控制路由的访问权限
  • 全局前置守卫
const router = new VueRouter({ ... })
// 只要发生了路由的跳转,必然触发beforeEach的回调函数
router.beforeEach((to, from, next) => {
    //to表示将要访问的路由对象
    //from表示将要离开的路由对象
    //next()函数表示放行
    //next函数的三种调用方式:
    //next(),next('/login'),next(false)
    if(to.path === '/main'){
        const token = localStroage.getItem('token')
        if(token){
            next()
        }else{
            next('/login')
        }else{
            next()
        }
    }
})

七、ref引用、动态组件、插槽、自定义指令

ref引用
  • ref不仅可以用来引用DOM元素,也可以用来引用组件实例
  • 在标签内或者组件内添加一个ref属性即可
    <h1 ref="helloRef">hello</h1>
  • 使用:this.$refs.helloRef.//+组件内的数据或者是方法

this.nextTick(cb)把cb回调函数推迟到下一个更新DOM周期之后执行

动态组件
  • 通过:is改变实现动态切换组件
    <component :is='动态组件的名称'></component>
  • <keep-alive>可以把内部组件进行缓存,而不是销毁组件
<keep-alive>
    <component :is='动态组件的名称'></component>
</keep-alive>
  • <keep-alive>的生命周期函数:activated,组件被激活;deactivated,组件被缓存
  • 可通过include/exclude之一指定哪些组件需要/不需要被缓存
插槽
  • 作用:插槽就是在自定义组件中预留一个位置,这个位置的内容可以由使用组件的人来定义,具有高度的灵活性
  • 默认插槽
//在my-com组件中
<slot>后备内容</slot>
//使用组件
<my-com>插槽内容</my-com>
  • 具名插槽
<slot name="left"></slot> //默认name为default
<template v-slot:left></template> //v-slot只能用在template标签上
<template #left></template>
  • 作用域插槽
<slot name="left" msg="hello"></slot>
<template #left="obj">{{ obj.msg }}</template>
<template #left="{ msg }">{{ msg }}</template>
自定义指令
  • 私有自定义指令
directives:{
    color:{
        //binding:用户通过=传的值
        bind(el,binding) {
            el.style.color = binding.value
        }
        //在DOM更新的时候,会触发update函数
        update(el,binding) {
            el.style.color = binding.value
        }
    }
}
directives:{
        //简写
        color(el,binding) {
            el.style.color = binding.value
        }
    }
}
  • 全局自定义指令
Vue.directive('color',function(el,binding){
    el.style.color = binding.value
})

八、Vuex

简介
  • Vuex是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间数据的共享
  • 核心概念
    • State
    • Mutation
    • Action
    • Getter
Vuex的使用
  • 安装vuex依赖包
  • 导入vuex
import Vuex from 'vuex'
Vue.use(Vuex)
  • 创建store对象
const store = new Vuex.Store({
    // state 中存放的是全局共享的数据
    state: {
        count: 0
    },
    mutations: {
 
    },
    actions: {
 
    }
})
  • store对象挂载到vue实例中
new Vue({
    el: '#app',
    render: h => h(app), 
    router,
    // 将创建的共享数据对象,挂载到 Vue 实例中
    // 所有的组件,就可以直接从 store 中获取全局的数据了
    store
})
State
  • State 提供唯一的公共数据源,所有共享的数据要统一放到 StoreState 中进行存储
// 创建 store 数据源,提供唯一的公共数据
const store = new Vuex.Store({
    state: { count: 0 }
})
  • 组件访问 State 中数据的第一种方式:
this.$store.state.全局数据名称
  • 组件访问 State 中数据的第二种方式:
// 1. 从 vuex 中按需导入 mapState 函数
import { mapState } from 'vuex'

// 2. 将全局数据,映射为当前组件的 computed 计算属性
computed: {
    ... mapState(['count'])
}
Mutation
  • Mutation 用于变更 Store 中的数据
  • 只能通过 mutation 变更 Store 数据,不可以直接操作 Store 中的数据,这种方式可以集中监控所有数据的变化
  • 可以在触发 mutations 时传递参数
  • 不要再 mutations 函数中,执行异步操作
// 定义 Mutation
const store = new Vuex.Store({
    state: {
        count: 0
    },
    mutation: {
        addN(state, step) {
            // 变更状态
            state.count += step
        }
    }
})
// 触发 mutation
methods: {
    handle(){
    // 调用 commit 函数
    // 触发 mutations 时可以携带参数
    this.$store.commit('addN', 3)
    }
}
  • 触发 mutations 的第一种方式
this.$store.commit()
  • 触发 mutations 的第二种方式:
// 1. 从 vuex 中按需导入 mapMutations 函数
import { mapMutations } from 'vuex'

// 2. 将需要的 mutations 函数,映射为当前组件的 methods 方法
methods: {
    ... mapMutations(['add', 'addN'])
}
Action
  • Action 用于处理异步任务
  • 如果通过异步操作变更数据,必须通过 Action,而不能用 Mutation,但是在 Action 中还是要通过触发 Mutation 的方式间接变更数据
  • 触发 actions 异步任务时可以携带参数
// 定义 Action
const store = new Vuex.Store({
    state: {
        count: 0
    },
    mutations: {
        addN(state, step) {
            state.count += step
        }
    },
    actions: {
        addNAsync(context, step) {
            setTimeout(() => {
                context.commit('addN', step)
            }, 1000)
        }
    }
})
// 触发 Action
methods: {
    handle() {
        // 触发 actions 的第一种方法
        this.$store.dispatch('addAsync', 5)
    }
}
  • 触发 actions 的第一种方式
this.$store.dispatch()
  • 触发 actions 的第二种方式:
// 1. 从 vuex 中按需导入 mapActions 函数
import { mapActions } from 'vuex'

// 2. 将需要的 actions 函数,映射为当前组件的 methods 函数
methods: {
    ... mapActions(['addASync', 'addNASync'])
}
Getter
  • Getter 用于对 Store 中的数据进行加工处理形成新的数据,类似 Vue 中的计算属性。
  • Store 中数据发生变化,Getter 的数据也会跟着变化
// 定义 Getter
const store = new Vuex.Store({
    state: {
        count: 0
    },
    getters: {
        showNum: state => {
            return '当前最新的数量为[' + state.count + ']'
        }
    }
})
  • 使用 getters 的第一种方式:
this.$store.getters.名称
  • 使用 getters 的第二种方式:
import { mapGetters } from 'vuex'

computed: {
    ...mapGetters(['showNum'])
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值