06-混入-自定义插件-插槽-本地存储-vuex组件通信-页面跳转

混入mixin

在Vue中,混入(mixin)是一种可以在多个组件中重复使用的对象。它允许您将组件中的一些选项提取出来,然后在多个组件中进行重复使用。混入可以包含组件中的任何选项,例如数据、计算属性、方法等。

使用步骤

  1. 在src文件夹下新建一个文件夹,比如mixin,然后再这个文件夹下面新建一个脚本,比如index.js
  2. 使用混入必须要导出,export default,在导出的对象内部写上需要的方法以及data属性等。
  3. 局部使用:
    1. 再自己的.vue中,导入
      1. import hunru from "@/mixin"
      2. 自己的组件中,写上mixin:[hunru]
  4. 全局使用:
    1. 在main.js中:
      1. import hunru from "@/mixin"
      2. Vue.mixnin(hunru)
      3. 就可以了,可以写多个:需要写多个,然后导入多个。
        1. import hunru2 from "@/mixin"
        2. Vue.mixin(hunru2)

案例

  1. 引用的组件一定要要有自定义混入的属性或者方法,如果没有则会报错。
  2. 如果组件有自己的属性以及方法,会优先使用自己的,没有再使用混入的。

image-20240430135352661

局部使用

image-20240430135408234

全局使用

image-20240430140223935

image-20240430140239853

// 1. 导入
import hunru from "@/mixin"

// 2. 使用
Vue.mixin(hunru)

// 这样局部就不用导入和引入了

img

自定义插件

使用别人写好的插件

  1. 在main.js中导入。
  2. Vue.use()
# 1 写plugins/index.js
import Vue from "vue";
import axios from "axios";
import hunru from "@/mixin";
export default {
    install(a,name) {
        console.log('----------',name)

        // 1 定义全局变量,放到原型中
        // prototype 原型链,一般定义在原型中的变量,都用 $ 开头,防止污染---》对象中可以定义同名属性,冲突
        Vue.prototype.$axios = axios
        // Vue.prototype.$BASE_URL='http://127.0.0.1:8000/'


        // 2  定义指令  自定义指令
        //定义全局指令:跟v-bind一样,获取焦点
        Vue.directive("fbind", {
            //指令与元素成功绑定时(一上来)
            bind(element, binding) {
                element.value = binding.value;
            },
            //指令所在元素被插入页面时
            inserted(element, binding) {
                element.focus();
            },
            //指令所在的模板被重新解析时
            update(element, binding) {
                element.value = binding.value;
            },
        });

        // 3 使用混入
        Vue.mixin(hunru)
        // 4 定义全局组件--》elementui
    }
}

// 3 在main.js中使用,可以传参数
// 1 使用自定义插件
import my from '@/plugins'
Vue.use(my,'小满') // 内部本质会执行install


// 咱们需要掌握的;
	-有些第三方插件,用了以后,增强了vue功能
    -this.$router
    -全局组件 :el-button
    -this.$message--->
    -this.$http.get

插件之赋值

使用步骤

  1. 在src下面新建一个文件夹,比如plugins

  2. 在这个文件夹下面新建一个脚本文件,比如index.js

  3. 必须导出,并且内部有一个install对应一个对象,所有代码写在install中。

    // 一个非常简单的插件
    // 这样项目运行, 都会在控制台打印
    export default {
    	install: function (xm){
            // 这个xm是什么 就是view的实例对象
    		console.log("小满最棒啦")
    		console.log(xm)
    	}
    }
    
  4. 在main.js中导入,import xx from "@/plugins",然后使用Vue.use(my) ,这句话内部本质就会执行install

image-20240430150104769

可以被赋值,根据这个属性,可以把一些第三方的包,比如axios提前写入到插件里面,然后所有视图都可以使用了。

image-20240430150642004

通过赋值axios,然后发送请求

image-20240430151400533

image-20240430151411468

image-20240430151423195

img

为什么名称前面有一个$

防止和视图内部的变量名起冲突,一般定义在原型中的变量都使用$开头。

插件之自定义指令(了解即可)

写上自定义指令之后全局都可以使用我们自定义的指令。

https://juejin.cn/post/7114267523415015455

自定义插件之混入

和之前一样,先定义一个混入。

导入的时候,不需要在main.js里面导入了,直接通过自定义插件去导入。

// 自定义插件
import Vue from 'vue'
import hunru from "@/mixin"

export default {
	install: function (xm){
		Vue.mixin(hunru)
	}
}

插槽

<!--  
	子组件
	src/components/MySlot.vue 
-->
<template class="my-slot">
	<div>
		<h3>小满三岁啦</h3>
		<slot></slot>
		<p>{{message}}</p>
	</div>
</template>

<!--
	父组件
	src/views/HomeView.vue
-->
<template>
  <div class="home">
	<MySlot>
        <!-- @代表的就是src路径 -->
		<img src="@/assets/logo.png" alt="">
	</MySlot>
</template>
<script>
	import MySlot from "@/components/MySlot.vue"
    export default {
      name: "HomeView",
      components: {
          MySlot
      }
    }
</script>

image-20240430161707329

本地存储 cookie/sessionStorage/localStorage

image-20240430163208995

前提是登录成功。

存储类型 说明 其他
cookie 登录信息放这里,有过期时间,一旦过期就没有了 需要下载第三方模块vue-cookies,cnpm install vue-cookies -S,记得main.js注册
sessionStorage 当前浏览器生效,浏览器一旦关闭,数据就没有了
localStorage 永久生效,除非删除代码或者清空浏览器缓存 案例:未登录,加入购物车
// localStorage
// 存 setItem 取 getItem 删 removeItem clear()

// sessionStorage
// 存 setItem 取 getItem 删 removeItem clear()

// cookies
// 需要下载第三方模块 npm install vue-cookies -S 
this.$cookies.set("name", "小满", "1d") // 存 -->1d 1天 2h 2小时
this.$cookies.get("name") //取
this.$cookies.remove("name")// 删

vue-cookies的第三个参数

vue-cookies 插件中设置 Cookie 的第三个参数是过期时间,可以使用以下单位:

  • '1s': 1 秒
  • '1m': 1 分钟
  • '1h': 1 小时
  • '1d': 1 天
  • '1y': 1 年

你可以根据需要选择合适的单位,例如:

this.$cookies.set("name", "xm", "1h"); // 表示1小时过期

这样就会在 1 小时后过期。

如何使用

<!--视图层-->
   
<template>
  <div class="home">
    <h3>localStorage 案例演示</h3>
    <button class="btn btn-outline-primary" @click="handleSaveLocalStorage">存储到localStorage</button>
    <button class="btn btn-outline-primary" @click="handleGetLocalStorage">从localStorage取出</button>
    <button class="btn btn-outline-primary" @click="handleDeleteLocalStorage">从localStorage删除/清空</button>

    <hr>

    <h3>sessionStorage 案例演示</h3>
    <button class="btn btn-outline-primary" @click="handleSaveSessionStorage">存储到sessionStorage</button>
    <button class="btn btn-outline-primary" @click="handleGetSessionStorage">从sessionStorage取出</button>
    <button class="btn btn-outline-primary" @click="handleDeleteSessionStorage">从sessionStorage删除/清空</button>

    <hr>

    <h3>cookieStorage 案例演示</h3>
    <button class="btn btn-outline-primary" @click="handleSaveCookieStorage">存储到cookieStorage</button>
    <button class="btn btn-outline-primary" @click="handleGetCookieStorage">从cookieStorage取出</button>
    <button class="btn btn-outline-primary" @click="handleDeleteCookieStorage">从cookieStorage删除</button>
  </div>
</template>
<script>


export default {
  name: "HomeView",
  methods: {
    // 本地存
    handleSaveLocalStorage() {
      // 方式1
      // 因为是在window对象里面的,所以可以直接使用 localStorage
      localStorage.setItem("name", "小满")
      // 方式2
      let user = {
        hobby: "摸鱼",
        age: 3
      }
      localStorage.setItem("user", JSON.stringify(user)) // 这里要放字符串,不要放对象

    },
    // 本地取
    handleGetLocalStorage() {
      // 取出
      let name = localStorage.getItem("name")
      let user = localStorage.getItem("user")
      console.log(name);
      console.log(user);

    },
    // 本地删
    handleDeleteLocalStorage() {
      // 删除指定的
      localStorage.removeItem("name")
      // 删除全部
      localStorage.clear()
    },

    // session存
    handleSaveSessionStorage() {
      // 方式1
      sessionStorage.setItem("name", "大乔")
      // 方式2
      let user = {name:"大乔", hobby: "欺负小满"}
      sessionStorage.setItem("user", JSON.stringify(user)) // 不要放对象进去
    },

    // session取
    handleGetSessionStorage() {
      let name = sessionStorage.getItem("name")
      let user = sessionStorage.getItem("user")
      console.log(name);
      console.log(user);
    },

    // session删
    handleDeleteSessionStorage() {
      // 按指定删
      sessionStorage.removeItem("name")
      // 清空 删全部
      sessionStorage.clear()
    },

    // 存cookie
    handleSaveCookieStorage(){
      this.$cookies.set("name", "小满", "1h") // 这里的1h 表示1小时  1d 表示1天 类推
    },
    // 取cookie
    handleGetCookieStorage(){
      let name = this.$cookies.get("name")
      console.log(name);
    },  
    // 清空全部cookie
    handleDeleteCookieStorage(){
      this.$cookies.remove("name") // 只能一个一个的删
    },    
  },
}
</script>

<style>
.home {
  margin: 20px;
}

.home button {
  margin: 10px
}
</style>
// main.js
// 导入vue-cookies
import VueCookies from "vue-cookies"
Vue.use(VueCookies)

img

vuex状态管理器

  1. vuex在vue2中,大量使用
  2. vue3中,Pinia 或 vuex
  3. 作用:主要用来跨组件通信。

集中式状态管理-->组件有自己的数据-->放在组件中-->有了状态管理器,多个组件可以共同操作这个管理器-->实现了组件间通信-->跨组件。

如何使用

// 1. 安装 cnpm install vuex -S
// 2. 新建 store/index.js 写入代码
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
      // 应用数据存储在这里面
  },
  getters: {
      // 从state中获取数据
  },
  mutations: {
      // 修改state中的数据
  },
  actions: {
      // 提交muations
      // 异步操作也放在这里面
  },
  modules: {
      // modules 是 Vuex 中用于将 store 分割成模块的功能。它允许你将 store 分割成模块,每个模块拥有自己的 state、getters、mutations 和 actions。
  }
})
// 3. 在main.js 导入
import store from './store'
new Vue({
  store,
})

// 上面三步 默认创建好项目就已经自动弄好了,如果项目中没有再去操作上面的步骤,如果有,就直接跳过上面步骤按下面继续。
//------------------- 关注下面 -------------------- //
// 4. 在store/index.js 中写代码

// 5 在组件中使用 (拿变量)
    js:this.$store.state.count
    html:$store.state.count
    
// 6 修改变量
    js中:
    	1 this.$store.dispatch('actions定义的函数名',参数)
    	2 this.$store.commit('mutations定义的函数名',参数)
    	3 this.$store.state.count++
   	所有组件中使用到的位置,都会变量
// 7 为什么经过 actions和mutations 
    -可以跟后端交互,可以做数据验证

// 8 getters:
    	可以通过getters获取数据--》对state中的数据,再做处理
    
// 9 modules:
    	分到不同模块中,不同模块有自己的state,actions

[this.]$store.state.变量名 视图中显示数据

// store/index.js
export default new Vuex.Store({
  state: {
    count: 0
  },
    
// 视图
{{ this.$store.state.count }}
// 等同于
{{ $store.state.count }}

和后端交互 actions

所以可以在这里发送Ajax请求给后端

actions: {
    this.$store.commit("addOne", num) // 报错
}

根据您提供的代码和错误信息,问题出在您在actions中的addCount方法中尝试直接访问this.$store.commit。在actions中,您不能直接访问this.$store,因为actions中的方法会接收一个与store实例具有相同方法的上下文对象。因此,您应该将commit方法作为第二个参数传递给addCount方法,而不是直接访问this.$store.commit。这应该可以解决您遇到的错误。

下面是您可以尝试的修改:

actions: {
    addCount({ commit }, num) {
      console.log(commit); // 可以直接访问commit方法
      console.log(num); // 1 是dispatch传递的参数

      // 通过commit方法来触发mutations中的函数
      commit("addOne", num);
    }
}

通过这种方式,您应该能够正确调用commit方法而不会再出现TypeError: Cannot read properties of undefined (reading 'commit')的错误。希望这能帮助您解决问题!

全部代码

两个子组件

<!-- 购物车 -->
<template>
    <div class="shopping-car">
        <div>
            <p>商品数量: {{this.$store.state.count}}</p>
        </div>
    </div>
</template>

<style scoped>
    .shopping-car p {
        text-align: right;
        margin-right: 20px;
    }
</style>

<!-- 商品列表 -->
<template>
    <div class="good-list">
        <!-- 
				点击按钮 触发handleClick 
							↓
        				触发this.$store.dispatch("addCount", 1)
							↓
						是否要与后端交互,发送Ajax请求
						触发mutations内部的函数
							↓
						触发state
							↓
						完成修改
		-->
        <p>商品名称:摸鱼套餐,价格$100<button class="btn btn-outline-primary" @click="handleClick">加入购物车</button></p>
        <p>商品名称:逃课套餐,价格$200<button class="btn btn-outline-danger" @click="handleClick">加入购物车</button></p>
    </div>
</template>

<script>
    export default {
        methods: {
            handleClick(){
                // 1. 直接操作变量
                // this.$store.state.count++

                // 2. 间接操作变量 借助 actions 
                // dispatch会触发actions中某个方法的执行,这个方法在dispatch中要用括号括起来。
                this.$store.dispatch("addCount", 1)
            }
        },
    }
</script>

<style scoped>
    button {
        margin: 10px;
    }
</style>

主视图

<template>
    <div class="state-view">
        <ShoppingCar></ShoppingCar>
        <hr>
        <GoodList></GoodList>
    </div>
</template>

<script>

import GoodList from '@/components/GoodList.vue';
import ShoppingCar from '@/components/ShoppingCar.vue';

export default {
    name: "StateView",

    components: {
        GoodList,
        ShoppingCar
    }

}
</script>


<style scoped>
    .state-view {
        margin: 20px;
        padding: 10px;
        border: 1px solid black;
    }
</style>

store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 100
  },
  getters: {
  },
  mutations: {
    // 这里的函数名可以和actions的函数名一样 不影响的
    // 这里的state 就是state的对象
    addOne(state, num) {
      console.log(state);
      console.log(num);

      state.count += num

    }
  },
  actions: {
    // 在这里发送Ajax请求,数据库数量增加成功,然后本地(页面)数量再加1 ,这样保证了数据的安全。


    // 这个函数会传递一个东西进来,与store实例具有相同方法的上下文对象, 就是mutations 简写成m
    // 这个m其实就是state的对象,所以可以用来传参数
    // addCount(m, num) ==>  this.$store.dispatch("addCount", 1)
    addCount(m, num) {
      console.log(m);
      console.log(m.state.count); // 100
      console.log(num); // 1 就是dispatch传过来的数

      // 这句化会触发 mutations内部函数 addOne()的执行
      // 它一样可以传递参数 
      // this.commit("addOne", num)


      // 3. 间接操作,不通过actions校验,直接请求mutations
      // m.commit("addOne", num)

      // 4. 通过第一个对象操作
      // m.state.count++
    }
  },
  modules: {
  }
})

img

页面跳转

前提,路径已经在app.vue中写好了

<!-- App.vue 就这么多代码就可以了 -->
<template>
    <div id="app">
        <router-view/>
    </div>
</template>

img

方式1:router.push('path')

这个path里面写router.js里面的path地址,不是name地址!

  1. HTML属性中跳转,直接写 $router.push("path地址")
  2. JavaScript内部函数跳转,写this.$router.push("path地址")
<p><button @click="$router.push('/pe')" class="btn btn-outline-success">回到体育馆</button></p>
<p><button @click="$router.push('/sale')" class="btn btn-outline-primary">回到小卖部</button></p>

to表示要跳转的地址,这个地址就是指的是router.js中path的地址

<router-link to="/pe">
    <p><button class="btn btn-outline-success">回到体育馆</button></p>
</router-link>

<router-link to="/sale">
    <p><button class="btn btn-outline-primary">回到小卖部</button></p>
</router-link>

方式3:通过router.push指定方式

<!-- html代码 -->
<p><button class="btn btn-outline-success" @click="toPE">回到体育馆</button></p>
<p><button class="btn btn-outline-primary" @click="toSale">回到小卖部</button></p>

<!-- js methods函数内部代码 -->
this.$router.push({
	path: "/pe"
})

this.$router.push({
	name: "sale"
})

方式4:通过:to绑定对象跳转

<router-link :to="{path:'/pe'}">
    <p><button class="btn btn-outline-success">回到体育馆</button></p>
</router-link>

<router-link :to="{name:'sale'}">  <!-- 通过name指定找不到控制台会报错 -->
    <p><button class="btn btn-outline-primary">回到小卖部</button></p>
</router-link>
posted @ 2024-04-30 21:24  小满三岁啦  阅读(12)  评论(0编辑  收藏  举报