• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

vue知识点

第一章、vue的指令

指令(Directives)是 vue 为开发者提供的模板语法,用于辅助开发者渲染页面的基本结构
① 内容渲染指令
② 属性绑定指令
③ 事件绑定指令
④ 双向绑定指令
⑤ 条件渲染指令
⑥ 列表渲染指令

1. 内容渲染指令

内容渲染指令用来辅助开发者渲染 DOM 元素的文本内容

1.1. v-text:缺点会覆盖元素内部原有的内容
1.2.{{ }}:插值表达式,只是内容的占位符不会覆盖原来的内容
1.3.v-html:可以带有标签的内容,渲染成真正的html内容

2. 属性渲染指令(又称单向数据绑定指令)

为元素的属性动态绑定属性值,则需要用到 v-bind 属性绑定指令
注意 : 插值表达式只能用在元素内容节点中,不能用在元素属性节点中

  • v-bind:为元素的属性动态的绑定值
  • 简写是英文 :
  • 在使用v-bind属性绑定期间,如果绑定内容需要进行动态的拼接,则字符串的外面应该包裹单引号,例如:
<div v-bind:title="'box'+index">这是一个div</div>

3. 事件绑定指令

vue 提供了 v-on 事件绑定指令,用来辅助程序员为 DOM 元素绑定事件监听
原生 DOM 对象有 onclick、oninput、onkeyup 等原生事件,替换为 vue 的事件绑定形式后,
分别为:v-on:click、v-on:input、v-on:keyup
v-on 绑定的事件处理函数,需要在 methods 节点中进行声明

3.1.v-on 指令绑定点击事件 后面是跟处理函数
3.2.可以简写为:@
3.3.语法格式为:

<button v-on:click="add"></button>

mmethods:{
  add(){
    //如果在方法中要修改数据,可以通过this访问到
    this.count+=1;
  }
}

3.4. $event 的应用场景:如果默认的事件对象e被覆盖了,则可以手动的传递一个 $event。例如:

<button v-on:click="add(n,$event)"></button>

mmethods:{
  add(e){
    //如果在方法中要修改数据,可以通过this访问到
    this.count+=n;
  }
}

3.5. 事件修饰符

  • prevent
<a @click.prevent="XXX">链接</a>
  • stop
<button @click.stop="XXX">按钮</button>

4. v-model:双向绑定指令(又称数据双向绑定指令)

vue 提供了 v-model 双向数据绑定指令,用来辅助开发者在不操作 DOM 的前提下,快速获取表单的数据

注意:只能用于一些表单的数据操作才有意义,其他没有意义
4.1. v-model的修饰符:

5. 条件渲染指令(根据条件显示与隐藏相应的dom元素)

条件渲染指令用来辅助开发者按需控制 DOM 的显示与隐藏

5.1.v-show 的原理是:动态的为元素添加或移除display:none样式,来实现元素的显示和隐藏
如果要频繁的切换元素的显示状态,用v-show性能会更好
5.2.v-if的原理:每次动态的创建或移除元素,实现元素的显示与隐藏
如果刚进入页面的时候,某些元素默认不需要显示,而且后期这个元素很可能不需要被展示出来,此时用v-if性能会更好
5.3.v-else-if:多条件判断指令,要和v-if来搭配只用 结束是:v-else,里面可以放Boolean值也可以放条件表达式的到Boolean值

<div v-if="type==='A'">优秀</div>
<div v-else-if="type==='B'">良好</div>
<div v-else-if="type==='C'">一般</div>
<div v-else="type==='D'">差</div>

6. v-for:列表渲染指令

6.1.作用:用来辅助开发基于一个数组来循环渲染一个列表结构。v-for指令需要使用item in items 形式的的特殊语法,

  • item :表示被循环的每一项
  • 在自身上也可以访问到item里面的值
  • items :表示被循环的数组,例如
  • ① key 的值只能是字符串或数字类型
    ② key 的值必须具有唯一性(即:key 的值不能重复)
    ③ 建议把数据项 id 属性的值作为 key 的值(因为 id 属性的值具有唯一性)
    ④ 使用 index 的值当作 key 的值没有任何意义(因为 index 的值不具有唯一性)
    ⑤ 建议使用 v-for 指令时一定要指定 :key 的值(既提升性能、又防止列表状态紊乱)
data:{
//list 表示数据
list:[
     {id:1,name:'zs'}
     {id:2,name:'ls'}
]
}
<ul>
<li v-for="item in list" :key="item.id">姓名:{{item.name}}</li>
</ul>

7. 总结:

① 能够知道vue的基本使用步骤
● 导入vue.js文件

● new Vue()构造函数,得到vm实例对象

● 声明el和data数据节点

● MVVM的对应关系

② 掌握vue中常见指令的基本用法

● 插值表达式、v-bind、v-on、v-if 和v-else

● v-for 和:key. v-model

③ 掌握vue中过滤器的基本用法

第二章、vue的过滤器

过滤器(Filters)是 vue 为开发者提供的功能,常用于文本的格式化。过滤器可以用在两个地方:插值表达式
和 v-bind 属性绑定

1. 过滤器的注意点:

1.1.要定义到filters节点下,本质是一个函数
1.2.在过滤器函数中一定要有return值
1.3.在过滤器的形参中,就可以获取到 管道符 |前面待处理的那个值
1.4.私有过滤器与全局过滤器

  • 私有过滤器:定义在vue 实列对象里面 filters的就是私有过滤器
  • 全局过滤器: Vue.filter
    参数1 ,表示全局过滤器的名字
    参数2,表示全局过滤器处理函数
Vue.filter('toMiniDate', function (val) {
  const y = val.getFullYear()
  const m = val.getMinutes() + 1
  const d = val.getDate()
  return [y, m, d].join('-')
})
//使用
<p>金额:{{ money | toRmb }}</p>
<p>生日:{{ bornDate | toMiniDate }}</p>

第三章、侦听器watch

watch 侦听器允许开发者监视数据的变化,从而针对数据的变化做特定的操作

1.方法格式的侦听器

  • 缺点1:无法在进入页面的时候,自动触发!
  • 缺点2:如果侦听的是一个对象,如果对象里面的属性发生了变化,不会触发侦听器!
 const vm = new Vue({
            el: "#app",
            data: {
                username: "张三",
            },
            // 所有的监听器都应该定义在watch 节点下
            watch: {
                // 侦听器本质上就是一个函数,要监听那个数据的变化,就把数据名作为方法名即可
                // 新增的数值在前,旧值在后
                username(newVal, oldValue) {
                    // console.log('监听到了username值的变换', newVal, oldValue);
                    $.get("https://www.escook.cn/api/finduser/" + newVal, function (req,res) {
                        console.log(req,res);
                    })
                }

            }
        })

2.对象格式的侦听器

  • 好处1:可以通过handler函数,immediate:true,让侦听器自动触发!
  • 好处2:可以通过deep:true选项,让侦听器深度监听对象中每个属性的变化!
 const vm = new Vue({
            el: "#app",
            data: {
                username: "张三",
            },
            // 所有的监听器都应该定义在watch 节点下
            watch: {
                // 定义对象格式的侦听器
                username: {
                    // 侦听器处理函数
                    handler(newVal, oldValue) {
                        console.log(newVal, oldValue);
                    },
                    // 默认是false 不会触发
                     // immediate作用:控制侦听器是否自动触发一次
                    immediate: true
                }
            },
        })
//使用
    <p>金额:{{ money | toRmb }}</p>
    <p>生日:{{ bornDate | toMiniDate }}</p>

第四章、计算属性 (computed)

计算属性是通过一些列运算之后,最终得到的一个值,这个动态计算出来的属性可以被模板结构或者methods方法使用

注意点:

  1. 所有的计算属性都要定义到computed中
  2. 在定义计算属性的时候要定义成方法
  3. 在使用计算属性的时候,当普通的属性使用即可
    优点
  4. 实现了代码的复用
  5. 只要计算属性中依赖的数据源变化了,则计算属性会自动重新求值
var vm = new Vue({
      el: '#app',
      data: {
        // 红色
        r: 0,
        // 绿色
        g: 0,
        // 蓝色
        b: 0
      },
      methods: {
        // 点击按钮,在终端显示最新的颜色
        show() {
          console.log(this.rgb)
        }
      },
      // 所有的计算属性都要被定义到computed中
      // rgb作为一个计算属性,被定义成 方法格式
      // 最终这个方法中,要返回一个生成到的rgb(x,x,x)的字符串
      computed: {
        rgb() {
          return `rgb(${this.r}, ${this.g}, ${this.b})`
        }
      }
    });

第五章、axios

axios是一个专注于网络请求的一个库

1. 私有axios

axios的基本使用
1.1 发起post请求:

 axios({
            // 请求方式
            method: "GET",
            // 请求地址 
            url: "http://www.liulongbin.top:3006/api/getbooks",
            // get传参  url中的查询参数
            params: {
                id: 1
            }
        }).then((res) => {
            console.log(res.data);
        })

1.2. 发起post请求:

 <button id="btn1">发起post请求</button>
    <script>
        document.querySelector("#btn1").addEventListener('click', async function () {
            //  如果调用某个方法的返回值是promise实列 ,则前面可以调价 await
            // await 只能用在被 async '修饰'的方法中 
            const { data } = await axios({
                // 请求方式
                method: "POST",
                // 请求地址 
                url: "http://www.liulongbin.top:3006/api/post",
                // post 传参
                data: {
                    name: "zs",
                    age: 20
                }
            })
            console.log(data);
        })

2. 全局axios

2.1.在main.js中 配置

// 导入axios模块
import axios from 'axios'
//全局配置axios的请求地址
axios.defaults.baseURL='http://www.liulongbin.top:3006'
// 今后,在每个.vue每个组件中发起请求,直接调用 this.$http
Vue.prototype.$http=axios

2.2. 使用

 methods: {
    async getAss() {
      const {data:res } = await this.$http.get('/api/get')
      console.log(res);
    }

第六章、vue-cli(称脚手架)

vue-cli 是 Vue.js 开发的标准工具。它简化了程序员基于 webpack 创建工程化的 Vue 项目的过程

1.安装

1.1.安装vue-cli 指令

// -g 表示全局安装
npm install -g @vue/cli

1.2. 检测是否安装成功

vue -V

2. 创建vue项目

  1. 步骤指令 点击enter
vue create 项目名称

2.步骤 点击enter

3.步骤 点击enter

4.步骤 点击enter

5.步骤 点击enter

6.步骤 点击enter

7.步骤 点击enter

8.步骤

3. vue项目中src目录的构成

3.1. assets文件名:存放项目中用到的静态资源,例如:css样式表,图片资源
3.2.components文件名:存放程序员封装的,可复用的组件,到要放到此目录
3.3.main.js是项目的入口文件,整个项目的运行,要先执行main.js
3.4.App.vue 是项目的跟组件

第七章、组件(components)

1. vue在项目中运行的过程

  1. 在工程化的项目中,vue 要做的事情很单纯:通过 main.js 把 App.vue 渲染到 index.html 的指定区域中。
    其中:
    ① App.vue 用来编写待渲染的模板结构
    ② index.html 中需要预留一个 el 区域
    ③ main.js 把 App.vue 渲染到了 index.html 所预留的区域中

2.组件的格式语法

组件化开发指的是:根据封装的思想,把页面上可重用的 UI 结构封装为组件

  • 每个 .vue 组件都由 3 部分构成,分别是:
  • template -> 组件的模板结构
  • script -> 组件的 JavaScript 行为
  • style -> 组件的样
  1. 组件中template 定义ui结构的:
    注意点1:template 中只能包含唯一的根节点
<template>
    <h1 class="box">这是测试text.vue的结构---{{ username }}</h1>
</template>
  1. 组件中script 处理交互行为

注意:组件中的data数据,不能指向对象
注意:组件中的data数据必须是一个函数{},在return出去的{}中,可以定义数据

  1. style是样式:
<template>
    <h1 class="box">这是测试text.vue的结构---{{ username }}</h1>
</template>

<script>
// 默认到处的语法
export default {
    // data数据源
    //注意:.vue组件中的data 不能像之前一样,不能指向对象
    //注意:组件中的data必须是一个函数
    data() {
        //这个return出去的{}中,可以定义数据
        return {
            username: 'zs'
        }
    }
}
</script>

<style>
.box {
    background-color: red;
}
</style>

3.组件之间的父子关系

4. 使用组件三个步骤


4.4.1. 注册私有组件

通过 components 注册的是私有子组件
例如:
在组件 A 的 components 节点下,注册了组件 F。
则组件 F 只能用在组件 A 中;不能被用在组件 C 中

4.4.2. 注册全局组件
在 vue 项目的 main.js 入口文件中,通过 Vue.component() 方法,可以注册全局组件

// 导入 Count组件
import Count from '@/components/Count.vue'
// 把Count注册为全局组件
Vue.component('MyCount', Count)

4.4.3.组件中的props属性

props 是自定义属性,允许使用者通过自定义属性,为当前的组件指定初始值

export default{
//组件的自定义属性
props:['自定义属性A','自定义属性B'....]

//组件的私有数据
data(){
      return{}
   }
}

第八章、组件的生命周期函数

表示组件从创建到运行到销毁的时间阶段:叫生命周期

1.总结

第九章、动态组件

动态组件:表示动态的按需展示或者隐藏所需要的组件

  1. vue内置得到组件 component 占位符
<component is='组件得到名字'></component>
  1. 缓存(keep-alive),include:表示要缓存的组件
<keep-alive include='要缓存的组件'>
      <component is='组件的名字'><component>
</keep-alive>
  1. keep-alive对应的生命周期
    1.当组件被缓存了,自动触发deactivated生命周期函数
    2.当组件被激活了,自动触发activated生命周期函数
deactivated (){
console.log('组件被缓存了')
},
activated(){
console.log('组件被激活了')
}

第十章、插槽(slot)

把不确定,希望用户自定的部分定义为插槽

1. 默认插槽

1.1. 插槽的name属性,表示给每一个插槽指定一个插槽名称

// 子组件
<slot name='插槽的名称'></slot>

1.2. 在使用组件中,把内容填充到指定的插槽中(v-slot 简写:#)

// 父组件
<templat v-solt:default>
// v-solt 只能用在组件或者template身上
<p>把这个内容渲染到指定的插槽中</p>
</templat>

2. 具名插槽

为每一个插槽指定一个名字

//父组件
<template>
  <div>
    <TestChild>
      <template v-slot:title>
        <div>哈哈</div>
      </template>

      <template #contain>
        <div>你好</div>
      </template>
      
     <template #author>
        <div>李白</div>
      </template>
    </TestChild>
  </div>
</template>

<script>
import TestChild from '@/components/TestChild'
export default {
  components: {
    TestChild
  },
// 子组件
<template>
  <div class="article-contain">
    <!-- 文章的标题 -->
    <div class="header-box">
      <slot name="title"></slot>
    </div>

    <!-- 文章的内容 -->
    <div class="contain-box">
      <!-- 在封装组件时,为预留的<slot>提供属性对应的值,这种用法,叫做 "作用域插槽" -->
      <slot name="contain" msg="hello world" :user="userInfo"></slot>
    </div>

    <!-- 文章的作者 -->
    <div class="footer-box">
      <slot name="author"></slot>
    </div>
  </div>
</template>

3. 作用域插槽

为预留插槽提供属性的对应值,叫做作用域插槽

<template>
// 父组件
  <div>
    <TestChild v-slot="{ item }">
      <div>{{ item }}</div>
    </TestChild>
  </div>
</template>

<script>
import TestChild from '@/components/TestChild'
export default {
  components: {
    TestChild
  }
}
</script>

//子组件
<template>
  <div>
    <slot v-for="item in list" :item="item"></slot>
  </div>
</template>

<script>
export default {
  data() {
    return {
      list: [1, 2, 3]
    }
  }
}
</script>

第十一章、自定义指令

2.私有自定义指令

1.两个函数:bind当指令绑定到元素上才触发,只触发一次
2.update:实时更新DOM元素内容

在每个vue组件中,可以在directives节点下声明私有自定义指令

 // 第一种 对象形式的写法
 // 定义私有自定义指令
  directives: {
    // 定义一个color指令 指向一个配置对象
    color: {
      // 当指令绑定到元素上的时候,会立即触发bind函数
      // 形参中的el表示当前所绑定到的那个DOM对象
      bind(el,bind) {
        el.style.color = bind.value
      },
      // 数据发生改变是就是触发这个update函数
      update(el,bind){
        el.style.color=bind.value
     }
    }
  }

//第二种 函数形式的写法,当对象形式的写法的bind和update函数的逻辑一样的时候可以改成函数形式的写法
color(el,bind){
  el.style.color=bind.value
}

2.全局自定义指令

在main.js中定义全局自定义属性

// 全局自定义指令
Vue.directive('color', function (el, binding) {
  el.style.color = binding.value
})

第十二章、路由(router)

表示hash地址和组件之间的对应关系

1.安装路由

npm install vue-router@4

2.配置路由在src下新建一个router->index.js文件

import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from '../views/HomeView.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'home',
    component: HomeView
  },
  {
    path: '/about',
    name: 'about',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
  }
]

const router = new VueRouter({
  routes
})

export default router

2.1.<router-view>表示存放定义的hash地址的组件

<router-view></touter-view>

2.2.routes:定义路由链接

routes: [
// 表示路由规则
{path: '/home',component: HomeView},
]

2.3.router-link:可以替换a链接

<router-link to='路由的hash地址'>首页<router-link>

2.4. 路由的重定向redirect

routes: [
// 路由重定向
{path:'/', redirect:'/home'}
// 表示路由规则
{path: '/home',component: HomeView},
]

第十三章、路由的嵌套(router children)

  1. 默认子路由相当于是路由重定向

默认子路由:如果children数组中,某个路由规则的path值为空字符,则这条路由规则,叫做‘默认子路由’

  • 路由参数对象:route 路由导航对象:router
<div id="app">
    <router-link to="/home">首页</router-link>
    <!-- 注意1:再hash地址中,/后面的参数项,叫做路径参数 -->
    <!-- 再路由参数对象中,需要使用this.$route.params 来访问路径参数 -->
    <router-link to="/mui/i">篮球火</router-link>
     <!-- 注意2:在hash地址中, ?好后面的参数项,叫做 查询参数 -->
    <!-- 在路由参数对象中,需要使用 this.$route.query来访问 查询参数 -->
    <!-- 注意3:在this.$route中,path只是路径部分,fullpath是完整的路径地址 -->
    <router-link to="/mui/w?name=zs age=20">熊出没</router-link>
    <router-link to="/mui/f">大鱼</router-link>
    <router-link to="/music">歌曲</router-link>
    <hr>
    <!-- 只要再项目中安装了vue-router 就提供了一个组件router-view这个组件起到占位符 -->
    <router-view></router-view>
  </div>

第十四章、vue-router中的编程式导航API

vue-router提供了许多编程式导航的API,其中最常用的导航API分别是

  1. thi.$router.push('hash地址'),跳转到指定的地址,并增加一条历史记录
  2. this.$router.replace('hash地址'),跳转到指定的地址,并替换掉原来的历史记录
  3. this.$router.go('数字'),表示前进或者后退
    3.1. $router.go的简写
  • $router.back():在历史记录中,后退到上一个页面
  • $router-forward():在历史记录中,前进到下一个页面

第十五章、vue-$router导航守卫

导航守卫可以控制路由的访问权限

  1. 全局前置守卫
// 创建路由实例对象
const router =new VueRouter({})
// 全局前置守卫
router.beforeEach((to,from,next)=>{
// to表示要访问的 路由信息对象
// from 表示将要离开路由信息对象
//next是一个函数 调用next()表示放行,允许这次路由导航
next()
})
  1. next函数的三种调用方式

    3.全局前置导航守卫
// from表示当前所在的hash地址,to表示的是路由连接跳转到组件的hash地址
router.beforeEach((to, from, next) => {
  //    1.要拿到用户将要访问的hash地址
  //  2.判断hash 地址是否等于/main。
  //  2.1 如果等于/main, 证明需要登录之后,才能访问成功
  //  2.2如果不等于/main, 则不需要登录,直接放行next()
  //  3.如果访问的地址是/main。 则需要读取localStorage 中的token值
  //  3.1 如果有token, 则放行
  //  3.2如果没有token, 则强制跳转到/login 登录页

  if (to.path === '/main') {
    const token = localStorage.getItem('keyToken')
    if (token) {
      next()
    } else {
      next('/login')
    }
  } else {
    next()
  }
})

第十六章、 组件之间的通信方法

第一种 自定义属性,父向子传递数据

//父组件中的数据传递给Left 组件 yongv-bind绑定自定义属性
<div class="box">
      <Left :msg="message" :userInfo="userInfo"></Left>
      <Right @changVal="countValue"></Right>
    </div>
 data() {
    return {
      message: 'hello word',
      userInfo: { name: '你好', age: 12 },
      countAdd: 0
    }
 // 子组件中用props来声明接收,可以直接在模板中使用
 props: ['msg', 'userInfo'],

第二种 自定义事件,子向父传递数据

//父组件
<template>
  <div id="app">
      // 父组件中定义自定义事件处理函数
      <Right @changVal="countValue"></Right>
  </div>
</template>

<script>
import Left from "@/components/Left.vue"
import Right from "@/components/Right.vue"
export default {
  name: 'App',
  components: {
    Right
  },
  data() {
    return {
      userInfo: { name: '你好', age: 12 },
    }
  },
  methods: {
    countValue(e) {
      this.countAdd = e
    }
  }
}
</script>

// 子组件
<template>
  <button @click="addCount">count++</button>
</template>

<script>
import bus from '@/components/eventBus'
export default {
  name: 'Left_Info',
  data() {
    return {
      // 子组件,将来将count子组件里面的值传递给父组件
      count: 10,
      songMessage:''
    }
  },
  methods: {
    addCount() {
      this.count++ 
      // $emit 触发自定义事件,将值传递给父组件
      this.$emit('changVal',this.count)
    }

  }
}


第三种 eventBus 兄弟组件通信


第四种 全局事件总线

  1. 在main.js中vue实列上挂载一个属性
import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false
new Vue({
  render: h => h(App),
  beforeCreate() {
    // 安装全局事件总线,借助的是同一个vue实列
    Vue.prototype.$bus = this
  }
  
}).$mount('#app')
  1. 在任意组件中绑定一个点击事件 调用$emit将数据发送过去
 methods: {
    nameDaas() {
    // 发送数据
      this.$bus.$emit('hell', 9999)
    }
  }

3.在任意组件中的生命钩子接收数据 调用 $on

 mounted() {
  //接收数据
    this.$bus.$on('hell', (data) => {
      console.log('我是Left组件', +data);
    })

  },

第五种方式、消息订阅与发布

1.安装包来完成消息订阅与发布

npm i pubsub-js

2.在任意组件种导入包,发送数据方调用pubsub.publish

 methods: {
    nameDaas() {
      // 发送数据
      pupsub.publish('hello', 666)
    }
  }

3.在任意组件中导入包并在组件中调用一个生命周期钩子函数,接收数据方调用pupsub.unsubscribe

  mounted() {
    // 接收数据,两个参数,第一个是订阅的名称,第二个参数是发送方发过来的数据
    this.pubId = pupsub.subscribe('hello', (item, msg)=> {
      console.log('有人发布消息了', item, msg);
    })
  },
  // 在组件销毁之前把所有的订阅数据个他解绑
  beforeDestroy() {
    pupsub.unsubscribe(this.pubId)
  }

第六种方式、provide与inject

1.父组件种定义数据

<template>
  <div class="home">
    <h2>父组件</h2>
    <p>姓名:{{ name }}</p>
    <p>年龄:{{ age }}</p>
    <p>汽车名称:{{ carName }}</p>
    <p>汽车颜色:{{ carColor }}</p>
    <!-- 父组件通过props向子组件传递数据 -->
    <One :name="name" :age="age" @setname="name = $event" @setage="updateAge"></One>
    <Two></Two>
  </div>
</template>

<script>
import One from '@/components/One.vue'
import Two from '@/components/Two.vue'
export default {
  name: 'My_Home',
  // 数据
  data() {
    return {
      name: '张三',
      age: 20,
      carName: '特斯拉',
      carColor: '白色'
    }
  },
  // 依赖数据,这里定义数据,所有的后代组件都可以获取
  provide() {
    return {
      carName: this.carName,
      carColor: this.carColor,
      setCarName: this.setCarName,
      setCarColor: this.setCarColor
    }
  },
  methods: {
    updateAge(e) {
      this.age = e
    },
    // 修改汽车名称的方法 
    setCarName(val) {
      this.carName = val
    },
    // 修改汽车颜色的方法
    setCarColor(val) {
      this.carColor = val
    }
  },
  components: {
    One,
    Two
  }
}

</script>
  1. 在子组件种接收数据
<template>
  <div class="three">
    <h3>子组件</h3>
    <p>汽车名称:{{ MyCarName }}</p>
    <p>汽车颜色:{{ MyCarColor }}</p>
    <p>
      <button @click="setName">修改汽车名称</button>
      <button @click="setCarColor1">修改汽车颜色</button>
    </p>
  </div>
</template>

<script>
export default {
  name: 'My_three',
  // 后代组件,通过inject选项注入父组件中依赖鹅数据
  inject: ['carName', 'carColor', 'setCarName', 'setCarColor'],
  data() {
    return {
      // 中转接收过来的父组件数据
      MyCarName: this.carName,
      MyCarColor: this.carColor,
    }
  },

  methods: {
    setName() {
      // 修改自己的值
      this.MyCarName = '宝马'
      // 修改父组件中的值
      this.setCarName('宝马')
    },
    setCarColor1() {
      this.MyCarColor = '红色'
      this.setCarColor('红色')
    },
  },
}
</script>

第十七章、vuex

vuex是专门在vue中实现集中式数据管理的一个vue插件,读vue应用中的多个组件的共享状态进行集中式的管理(读/写)也是组件间通信的方式

  1. 安装vuex
//安装版本三
npm i vuex@3
  1. 搭建vuex环境

  2. 创建文件:src/store/index.js

//引入Vue核心库
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)

//准备actions对象——响应组件中用户的动作
const actions = {}
//准备mutations对象——修改state中的数据
const mutations = {}
//准备state对象——保存具体的数据
const state = {}

//创建并暴露store
export default new Vuex.Store({
	actions,
	mutations,
	state
})
  1. 在main.js中创建vm时传入store配置项
......
//引入store
import store from './store'
......

//创建vm
new Vue({
	el:'#app',
	render: h => h(App),
	store
})

基本使用

  1. 初始化数据、配置actions、配置mutations,操作文件store.js
//引入Vue核心库
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//引用Vuex
Vue.use(Vuex)

const actions = {
    //响应组件中加的动作
	jia(context,value){
		// console.log('actions中的jia被调用了',miniStore,value)
		context.commit('JIA',value)
	},
}

const mutations = {
    //执行加
	JIA(state,value){
		// console.log('mutations中的JIA被调用了',state,value)
		state.sum += value
	}
}

//初始化数据
const state = {
   sum:0
}

//创建并暴露store
export default new Vuex.Store({
	actions,
	mutations,
	state,
})
  1. 组件中读取vuex中的数据:$store.state.sum

  2. 组件中修改vuex中的数据:$store.dispatch('action中的方法名',数据) 或 $store.commit('mutations中的方法名',数据)

备注:若没有网络请求或其他业务逻辑,组件中也可以越过actions,即不写dispatch,直接编写commit

getters的使用

  1. 概念:当state中的数据需要经过加工后再使用时,可以使用getters加工。

  2. 在store.js中追加getters配置

......

const getters = {
	bigSum(state){
		return state.sum * 10
	}
}

//创建并暴露store
export default new Vuex.Store({
	......
	getters
})
  1. 组件中读取数据:$store.getters.bigSum

四个map方法的使用

  1. mapState方法:用于帮助我们映射state中的数据为计算属性
computed: {
    //借助mapState生成计算属性:sum、school、subject(对象写法)
     ...mapState({sum:'sum',school:'school',subject:'subject'}),
         
    //借助mapState生成计算属性:sum、school、subject(数组写法)
    ...mapState(['sum','school','subject']),
},
  1. mapGetters方法:用于帮助我们映射getters中的数据为计算属性
computed: {
    //借助mapGetters生成计算属性:bigSum(对象写法)
    ...mapGetters({bigSum:'bigSum'}),

    //借助mapGetters生成计算属性:bigSum(数组写法)
    ...mapGetters(['bigSum'])
},
  1. mapActions方法:用于帮助我们生成与actions对话的方法,即:包含$store.dispatch(xxx)的函数
methods:{
    //靠mapActions生成:incrementOdd、incrementWait(对象形式)
    ...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})

    //靠mapActions生成:incrementOdd、incrementWait(数组形式)
    ...mapActions(['jiaOdd','jiaWait'])
}
  1. mapMutations方法:用于帮助我们生成与mutations对话的方法,即:包含$store.commit(xxx)的函数
methods:{
    //靠mapActions生成:increment、decrement(对象形式)
    ...mapMutations({increment:'JIA',decrement:'JIAN'}),
    
    //靠mapMutations生成:JIA、JIAN(对象形式)
    ...mapMutations(['JIA','JIAN']),
}

备注:mapActions与mapMutations使用时,若需要传递参数需要:在模板中绑定事件时传递好参数,否则参数是事件对象。

模块化+命名空间

  1. 目的:让代码更好维护,让多种数据分类更加明确。

  2. 修改store.js

const countAbout = {
  namespaced:true,//开启命名空间
  state:{x:1},
  mutations: { ... },
  actions: { ... },
  getters: {
    bigSum(state){
       return state.sum * 10
    }
  }
}

const personAbout = {
  namespaced:true,//开启命名空间
  state:{ ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    countAbout,
    personAbout
  }
})
  1. 开启命名空间后,组件中读取state数据:
//方式一:自己直接读取
this.$store.state.personAbout.list
//方式二:借助mapState读取:
...mapState('countAbout',['sum','school','subject']),
  1. 开启命名空间后,组件中读取getters数据:
//方式一:自己直接读取
this.$store.getters['personAbout/firstPersonName']
//方式二:借助mapGetters读取:
...mapGetters('countAbout',['bigSum'])
  1. 开启命名空间后,组件中调用dispatch
//方式一:自己直接dispatch
this.$store.dispatch('personAbout/addPersonWang',person)
//方式二:借助mapActions:
...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
  1. 开启命名空间后,组件中调用commit
//方式一:自己直接commit
this.$store.commit('personAbout/ADD_PERSON',person)
//方式二:借助mapMutations:
...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),
  1. 总结

第十七章、 自定义插件

import axios from 'axios'
// 自定义插件就是一个对象
export default {
  // 对象中的必须是一个install方法
  install(Vue, options) {
    // install方法第第一个参数必须是Vue, 第二个参数是可选的配置对象
    // 在options方法中,对Vue进行扩展

    // 在vue原型上添加一个属性
    Vue.prototype.$bus = new Vue()

    // 扩张过滤器
    Vue.filter('toRmb', function (val) {
      return '¥' + val.toFixed(2)
    })

    Vue.filter('toMiniDate', function (val) {
      const y = val.getFullYear()
      const m = val.getMinutes() + 1
      const d = val.getDate()
      return [y, m, d].join('-')
    })

    // 全局混入
    // 混入代码,这里面定义的选项或跟所有的vue实列及组件进行合并
    Vue.mixin({
      data() {
        return {
          message: '欢迎使用vue开发'
        }
      },
      methods: {
        setMessage(e) {
          this.message = e
        },
        async $get(url, params) {
          const { data } = await axios.get(url, { params })
          return data
        },

        // 定义post请求方法
        async $post(url, params) {
          const { data } = await axios.post(url, params)
          return data
        }
      }
    })

    // 全局自定义指令
    // 自定义指令,就是对dom结构的封装
    Vue.directive('red', function (el, bind) {
      // el: 当前所在的元素
      // bind:是绑定的一份数据
      el.style.color = 'red'
    })

    Vue.directive('green', function (el, bind) {
      el.style.color = 'green'
    })

    Vue.directive('myShow', function (el, bind) {
      if (bind.value) {
        el.style.display = 'block'
      } else {
        el.style.display = 'none'
      }
    })

    Vue.directive('role', function (el, bind) {
      // 判断当前登录的用户权限
      const roeId = sessionStorage.getItem('roeId')
      if (['1', '3', '5'].includes(roeId)) {
        el.style.display = 'block'
      } else {
        el.style.display = 'none'
      }
    })

    // 全局组件
    Vue.component('my_box', (h) => {
      return h('div', {}, '哈哈')
    })
  }
}

posted on 2022-12-18 16:06  青&&风  阅读(91)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3