VUE在项目中的使用

本文详细介绍了Vue.js项目从创建到组件交互的全过程,涵盖vuecli的使用、项目结构、单文件组件、组件通信、Vuex状态管理和事件总线。讲解了如何修改网站图标、使用props、自定义事件、全局事件总线以及Vuex的store、getters、mutations和actions。此外,还提及了Vue生命周期和第三方库Swiper的引入。
摘要由CSDN通过智能技术生成

目录

vue项目的创建

vue架构理解

index.html

修改vue网站的图标 

main.js 

单文件组件

组件的组织

props组件交互

父组件给子组件传值

子组件接收值

子组件向父组件传递数据

子组件内

父组件内

祖先组件给子孙组件传递数据

自定义事件的组件交互

子组件传递参数

父组件接收子组件参数

vue全局事件总线

父组件app内

子组件school内

子组件student内

组件的生命周期

生命周期时的状态

vue引入第三方

vuex状态管理

vuex简介

什么时候用vuex

vuex的工作原理

vuex的使用

创建store对象

引入vuex

vuex状态管理的核心

State

方式一

方式二

Getter

方式一

方式二

Mutation

方式一

方式二

Action

方式一

方式二

fragment-碎片

vue项目的创建

安装vue工具vue cli

vue cli是vue.js的开发标准工具,vue cli是一个基于vue.js进行快速开发的完整系统

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

验证安装是否成功:vue -V

创建一个项目

npx vue create vue-demo

注意:项目名无论如何都不能出现大写,必须全小写,但是可以用-来链接多个单词

 

注意:

  • 在控制台中可以用上下按键来调整选择项
  • 在控制台中,可以使用空格选择是否选中或取消
  • 我们选择第三个手动选择特性 

我们如图选中即可,注意关闭linter/formatter校检

我们选择版本3

询问配置文件的存放位置,我们选择第一个

是否保存预设,我选n

用什么包管理-npm因为使得熟

运行项目

  1. 进入项目根目录:cd vue-demo
  2. 运行npm run serve启动项目 

进入local:后面的地址(其实哪个都行)

vue架构理解

index.html

<!DOCTYPE html>
<html lang="">
  <!-- public内的index.html总页面内 -->
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <!-- 网站图标 -->
    <link rel="icon" href="./view.jpg">
    <!-- 网站标题,可直接修改 -->
    <title>vue实验</title>
  </head>
  <body>
    <!-- main.js全局vue挂载区(AppInner组件的地方) -->
    <div id="app"></div>
  </body>
</html>

修改vue网站的图标 

//vue.config.js文件内
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  // 修改vue网站的图标
  pwa:{
    iconPaths:{
      favicon32:"view.jpg",
      favicon16:"view.jpg",
      appleTouchicon:"view.jpg",
      maskicon:"view.jpg",
      msTileImage:"view.jpg"
    }
  }
})

main.js 

// src下的main.js(全局js文件内)
//导入vue
import { createApp } from 'vue'
//导入AppInner组件,使其成为全局vue挂载区(提供视图,用于翻页)
import AppInner from './AppInner.vue'
import './registerServiceWorker'
// 导入的路由——里面可以导入许多组件和实现路由跳转
import router from './router/index'
// vuex——实现vue的数据管理、过滤、修改、提交等
import store from './store'
// 导入elementplus组件
import ElementPlus from 'element-plus'
// 引入elementplus的样式css
import 'element-plus/dist/index.css'
//注册组件(对于app/AppInner的全局vue对象)
createApp(AppInner).use(store).use(router).use(ElementPlus,{size:"small"}).mount('#app')

单文件组件

Vue单文件组件(又名.vue文件,缩写为SFC)是一种特殊的文件格式,他允许将Vue组建的模板、逻辑与样式封装在单个文件中

<template>
<h3>我是单文件组件</h3>
</template>
<script>
export default{
    name:"MyConponent"/* 组件名称 */
}
</script>
<!-- scoped属性表示css标签样式只在本组件内有效 -->
<style scoped>
h3{
    background: red;
}
</style>

scoped属性:该属性表示css标签样式只在当前组件内有效,对于本组件内引入的其他组件、以及其他组件无效(不然每个被“全局”导入的组件内的css样式都会全局生效)

全局导入:在main.js文件内导入或者被导入的文件可以连接到main.js文件全局

组件内部元素

  • template:视图结构部分
  • script:逻辑部分
  • style:样式部分

加载组件

  • 第一步:引入组件:import HelloWorld from './components/HelloWorld.vue'
  • 第二步:挂载组件:components: {HelloWorld}
  • 第三步:显示组件:<HelloWorld></HelloWorld>

组件的组织

通常一个应用会以一棵嵌套的组件树的形式来组织

props组件交互

props是可以在组件之上进行传递数据的

父组件给子组件传值

<template>
  <my-component :message="message" :age="age" :names="names"></my-component><!-- 这样写也可以 -->
</template>
<script>
import MyComponent from './components/MyComponent.vue'
export default {
  name: 'App',
  data() {
        return {
            message:"你好,世界",
            age:20,
            names:["lili","makabaka","tangbulibou"]
        }
  },
  components: {
  MyComponent
  }
}
</script>

子组件接收值

<template>
<h3>props传递数据</h3>
<p>{{message}}</p>
<p>{{age}}</p>
<ul>
    <li v-for="(item,index) in names" :key="index">{{item}}</li>
</ul>
</template>
<script>
export default{
    name:"MyConponent",/* 组件名称 */
    props:{
        message:{
            type:String,/* 组件接受的值为string类型 */
            default:""/* 如果不传值则组件默认值为空串 */
        },
        age:{
            type:Number,
            default:0
        },
        names:{
            type:Array,
            /* 数组和对象必须使用函数进行返回 */
            default:function(){
                return []
            }
        }
    }
    }
</script>

子组件向父组件传递数据

子组件内

<template>
    <div class="school">
        <button @click="sendSchoolName(name)">把学校名给App</button>
    </div>
</template>
<script>
    export default {
        name:"School",
        props:['getSchoolName'],
        data(){
            return{
                name:"bilibili",
                address:"北京"
            }
        },
        methods:{
            sendSchoolName(name){
                this.getSchoolName(name)
            }
        }
    }
</script>

父组件内

<template>
  <div class="app">
    <!-- 通过父组件给子组件传递函数类型的prop参数实现了子传父 -->
    <School :getSchoolName="getSchoolName"></School>
  </div>
</template>
<script>
import School from "./components/School.vue";
export default {
  name: "App",
  components: {
    School
  },
  methods: {
    getSchoolName(name) {
      console.log("app收到了学校名:" + name);
    }
  }
}
</script>

理解:两个组件通过v-bind:进行连接,子组件通过props属性对床过来的数据进行接收 

祖先组件给子孙组件传递数据

使用方法:父组件有一个provide选项用来提供数据,子组件有一个inject选项用来接收这个数据

结果:无论组件嵌套有多深,子孙组件均可接收祖先组件传来的数据

需求:second组件要接收app组件的msg,name

<template>
  <div>
    <!-- app组件内 -->
    <First></First>
    <h1>父组件的{{obj.msg}}</h1>
    <h1>父组件的{{name}}</h1>
    <button @click="obj.msg='hiworld'">父组件改变msg</button>
    <button @click="name='lala'">父组件改变name</button>
  </div>
</template>
<script>
import First from './components/First.vue';
export default {
  data(){
    return{
      name:"lili",
      //msg:"helloworld",//不能实现父子响应式
      //传递响应式对象,以使改变父组件属性的同时改变父组件传给子组件的属性
      obj:{
        msg:"helloworld",
      }
    }
  },
  //祖先组件向子孙组件传递数据
  //provide:{msg:"helloworld"},//此种传递方式不能直接传变量(只能传具体的值)
  provide(){
    //若想要传递具体的变量则需要provide返回一个对象
    return{
      obj:this.obj,//将响应式对象传递过去
      name:()=>this.name//通过函数返回响应式
    }
  },
  components:{
    First
}
}
</script>
<template>
    <div id="first">
        <Second></Second>
    </div>
</template>
<script>
import Second from './Second.vue';
export default {
    components: {
        Second
    }
}
</script>
<template>
    <div id="second">
        <h1>子组件的{{obj.msg}}</h1>
        <!-- 通过函数接收 -->
        <h1>子组件的{{name()}}</h1>
    </div>
</template>
<script>
    export default {
        //子孙组件接收祖先组件传过来的值
        inject:['obj','name']
    }
</script>

自定义事件的组件交互

自定义事件可以在组件中反向传递,props可以将数据从父组件传递到子组件,那么反向如何操作呢,就可以利用自定义事件实现$emit

子组件传递参数

<template>
<h3>自定义事件的组件交互</h3>
<button @click="sendClickHandle()">点击传递事件</button>
</template>
<script>
export default{
    name:"MyConponent",/* 组件名称 */
    data() {
        return {
            message:"我变大神,那是必然"
        }
    },
    methods: {
        sendClickHandle(){
            /* 参数1:字符串-事件名称
               参数2:传递的数据-事件参数 */
            //触发my-component组件的实例对象绑定的onevent事件并传递参数
            this.$emit("onevent",this.message)
        }
    },
    }
</script>

父组件接收子组件参数

<template>
  <!-- 给my-component组件的实例对象绑定onevent事件 -->
  <!--里面的.once标识只能触发一次(若没有该参数可触发无数次)-->
  <my-component @onevent.once="getDataHandle"></my-component><!-- 这样写也可以 -->
</template>
<script>
import MyComponent from './components/MyComponent.vue'
export default {
  name: 'App',
  components: {
  MyComponent
  },
  methods: {
    /* 里面的参数为自定义事件传递数据的参数 */
    getDataHandle(data){
        console.log(data);
    }
  },
}
</script>

理解:点击事件触发sendClickHandle函数,此函数触发自定义事件onevent并将参数带入父组件,父组件事件已被触发调用带参数的getDataHandle方法来获得数据

vue全局事件总线

前言:全局事件总线常用于兄弟组件的传值

vue项目内安装mitt:npm install -S mitt

//main.js内引入并使用
import mitt from "mitt"
//紧接着定义全局属性
const app = createApp(App);
app.config.globalProperties.$bus = new mitt();

父组件app内

<template>
  <div class="app">
    <Student />
    <School />
  </div>
</template>
<script>
import Student from "./components/Student.vue";
import School from "./components/School.vue";
export default {
  name: "App",
  components: {
    Student,
    School,
  },
}
</script>

需求:子组件school向student组件发送数据

子组件school内

<template>
    <div class="school">
        <button @click="sendSchoolName(name)">把学校名给student</button>
    </div>
</template>
<script>
    export default {
        name:"School",
        data(){
            return{
                name:"bilibili",
                address:"北京"
            }
        },
        methods:{
            sendSchoolName(name){
                //触发公共能找到的全局事件总线事件
                this.$bus.emit("onevent",name)
            }
        }
    }
</script>

子组件student内

<template>
    <div class="student">
        <button @click="over">取消事件总线事件绑定</button>
    </div>
</template>
<script>
    export default {
        name:"student",
        methods:{
            over(){
                //取消事件总线的事件绑定
                this.$bus.off("onevent")
            }
        },
        mounted(){
            // 监听公共全局事件总线的onevent事件,并接受参数(参数可以为多个)
            this.$bus.on("onevent",(data)=>{
                console.log("学生得到了学校信息"+data);
            })
        }
    }
</script>

组件的生命周期

每个组件在被创建时都要经过一系列的初始化过程--例如,需要设置数据监听、编译模板、将实例挂载到dom并在数据变化时更新dom等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己代码的机会

生命周期时的状态

  1. 创建时:beforeCreate、created
  2. 渲染时:beforeMount、mounted
  3. 更新时:beforeUpdate、updated
  4. 卸载时:beforeUnmount、unmounted
<template>
<h3>生命周期函数</h3>
<input type="text" v-model.lazy="msg">
<p>{{msg}}</p>
</template>
<script>
export default{
    name:"mycomponent",
    data() {
        return {
            msg:""
        }
    },
    beforeCreate() {
        console.log("组件创建之前");
    },
    created() {
        console.log("组件创建之后");
    },
    beforeMount() {
        console.log("组件挂载前");
    },
    mounted() {
        console.log("组件挂载后");
    },
    beforeUpdate() {
        console.log("组件更新前");
    },
    updated() {
        console.log("组件更新后");
    },
    beforeUnmount() {
        console.log("组件卸载前");
    },
    unmounted() {
        console.log("组件卸载后");
    },
}
</script>

vue引入第三方

以swiper为例

  • swiper开源、免费、强大的触摸滑动插件
  • swiper是纯javascript打造的滑动特效插件,面向手机、平板电脑等移动终端
  • swiper能实现触摸焦点图、触屏tab切换、触屏轮播图切换等常用效果

安装swiper:npm i --save swiper

<template>
<div id="a">
<!-- 使用轮播图-->
    <swiper>
        <swiper-slide class="mySwiper">
            <img src="../assets/test.jpg" alt="图片没了">
        </swiper-slide>
        <swiper-slide>
            <img src="../assets/test.jpg" alt="图片没了">
        </swiper-slide>
        <swiper-slide>
            <img src="../assets/test.jpg" alt="图片没了">
        </swiper-slide>
    </swiper>
</div>
</template>
<script>
// 引入轮播图组件
import {Swiper,SwiperSlide} from "swiper/vue"
import "swiper/css"
export default{
    name:"mycomponent",
    // 注册组件
    components:{
        Swiper,
        SwiperSlide,
    }
}
</script>

vuex状态管理

vuex简介

概念:专门在vue中实现集中式状态(数据)管理的一个vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间的通信

注意:vuex不属于任意一个组件里

什么时候用vuex

  • 多个组件依赖于同一个状态
  • 来自不同组件的行为需要变更同一个状态

vuex的工作原理

注意:

  • 将数据交给vuex管理其是就是把数据交给State对象进行管理
  • 整个过程为vue组件通过dispatch函数做出某种行为,actions对其行为进行提交,mutations对行为进行执行并加工到state中然后就会渲染到该vue组件
  • 整个过程的actions、mutations、state都是经过store管理,store为他们提供对应的函数

vuex的使用

安装vuex:npm install --save vuex

创建store对象

在src目录中新建一个store文件夹存放index.js文件

//index.js文件内
import { createStore } from 'vuex'
// vuex的核心作用就是帮我们管理组件之间的状态
export default createStore({
  state: {
    count:10
  },
  getters: {  
    getCount(state){
      /* count数据深层的管理 */
      return state.count>0?state.count:"count数据异常"
    }
  },
  mutations: {
    //用于修改参数(第一个传state信息,第二个传修改参数的变量)
    //注意:在mutations里面不可以执行异步的代码
    addCount(state,num){
      state.count+=num
    }
  },
  actions: {
    //在actions里面可以执行异步的代码,num为携带的参数
    addAsync(context,num){
      //commit内的参数为mutations内的函数
      setTimeout(()=>{
        //异步内触发mutations函数
        context.commit("addCount",num)
      },1000)
    }
  },
})

引入vuex

//main.js内
import { createApp } from 'vue'
import App from './App.vue'
import './registerServiceWorker'
//全局引入vuex
import store from './store'
//注册vuex
createApp(App).use(store).mount('#app')

vuex状态管理的核心

常用的核心概念包括:State、Getter、Mulation、Action

app.vue内

<template>
  <HelloWorld></HelloWorld>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
  name: 'App',
  components: {
    HelloWorld,
  }
}
</script>

State

作用:在组件中读取状态

方式一

<template>
  <div class="hello">
    <!-- 从vuex中读取属性 -->
    {{$store.state.count}}
  </div>
</template>

方式二

<template>
  <div class="hello">
    <!-- 直接读取count -->
    {{count}}
  </div>
</template>
<script>
//引入mapState从vuex
import { mapState } from 'vuex'
export default {
  name: 'HelloWorld',
  //计算属性
  computed:{
    ...mapState(["count"])
  }
}
</script>

Getter

作用:对vuex中的数据进行过滤(对读取的方式提供一种更合理的方式)

方式一

<template>
  <div class="hello">
    {{$store.getters.getCount}}
  </div>
</template>

方式二

<template>
  <div class="hello">
    <!-- 直接获取 -->
    {{getCount}}
  </div>
</template>
<script>
/* 引入mapgetters */
import { mapGetters } from "vuex";
export default {
  name: 'HelloWorld',
  //计算属性
  computed:{
    ...mapGetters(["getCount"])
  }
}
</script>

Mutation

理解:更改vuex的store中状态的唯一方法是提交mutation。vuex中的mutation非常类似于事件:每个mutation都有一个字符串的事件类型(type)和一个回调函数(handler),这个回调函数就是我们实际进行状态更改的地方,并且他会接收state作为第一个参数 

方式一

<template>
  <div class="hello">
    <!-- 获取属性对比 -->
    <p>count={{$store.getters.getCount}}</p>
    <!-- mutaion的事件类型 -->
    <button @click="addClickHandler">增加</button>
  </div>
</template>
<script>
export default {
  name: 'HelloWorld',
  methods: {
    /* mutation调用函数 */
    addClickHandler(){
      //固定调用方式 
      //第一个参数为函数,第二个参数为修改参数的变量num
      this.$store.commit("addCount",15)
    }
  },
}
</script>

方式二

<template>
  <div class="hello">
    <p>count={{$store.getters.getCount}}</p>
    <!-- mutaion的事件类型 -->
    <button @click="addClickHandler">增加</button>
  </div>
</template>
<script>
/* 引入mapMutations */
import { mapMutations } from "vuex";
export default {
  name: 'HelloWorld',
  methods: {
    /* mutation调用函数 */
    ...mapMutations(["addCount"]),
    addClickHandler(){
      //里面的参数为修改参数的变量(num)
      this.addCount(20)
    }
  },
}
</script>

Action

理解:Action用于处理异步任务,若通过异步操作变更数据,而不能用Mutation,但是在Action中还要通过触发Mutation的方式间接变更数据

方式一

<template>
  <div class="hello">
    <p>count={{$store.getters.getCount}}</p>
    <button @click="addAsyncClickHandler">异步增加</button>
  </div>
</template>
<script>
export default {
  name: 'HelloWorld',
  methods: {
    addAsyncClickHandler(){
      /* 固定写法,第一种方式 */
      this.$store.dispatch("addAsync",20)
    }
  },
}
</script>

方式二

<template>
  <div class="hello">
    <p>count={{$store.getters.getCount}}</p>
    <button @click="addAsyncClickHandler">异步增加</button>
  </div>
</template>
<script>
import { mapActions } from "vuex";
export default {
  name: 'HelloWorld',
  methods: {
    ...mapActions(["addAsync"]),
    addAsyncClickHandler(){
      /* 第二种方式 */
      //里面传num
      this.addAsync(15);
    }
  },
}
</script>

fragment-碎片

vue3的新特性,不再限于模板中只有一个根节点

<template>
  <div>道生一</div>
  <div>一生二</div>
</template>

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值