Vue总结笔记

116 阅读9分钟

Vue开发

[1]Vue是什么?

Vue是前端优秀框架, 是一套用于构建用户界面的渐进式框架

[2]Vue开发步骤?

(1)安装Vue工具 Vue CLI

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

 npm install -g @vue/cli

安装之后,你就可以在命令行中访问 vue 命令。你可以通过简单运行 vue,看看是否展示出了一份所有可用命令的帮助信息,来验证它是否安装成功。

 vue --version

(2)创建一个项目

运行以下命令来创建一个新项目

 vue create vue-demo

温馨提示

在控制台中,可以用上下按键调整选择项

在控制台中,可以用空格(spacebar)选择是否选中和取消选中

可以选择默认项目模板,或者选“手动选择特性”来选取需要的特性。

image-20220527164650454.png 我们选择BabelProgressive Web App (PWA) Support 两个选项即可

温馨提示

在学习期间,不要选中 Linter / Formatter 以避免不必要的错误提示

image-20220527164940432.png

Vue目前有两个主流大版本vue2vue3,我们本套课程选择vue3最新版本

image-20220527165107021.png

配置放在哪里? In dedicated config files 专用配置文件或者 In package.json在package.json文件

image-20220527165155721.png

将其保存为未来项目的预置? y代表保存,并添加名字,n不保存

image-20220527165356418.png

项目创建成功如下提示信息

image-20220527165529413.png

(3)运行项目

第一步:进入项目根目录cd vue-demo

第二步:运行npm run serve 启动项目

(4)安装Vue高亮插件

VSCode中安装vetur或者volar都可,前者针对Vue2版本,后者针对Vue3版本

1. 模板语法

 <template>
   <div class="hello">
     <h3>学习Vue:模板语法</h3>
     <p>{{ message }}</p>
     <div>{{ rawHtml }}</div>
     <div v-html="rawHtml"></div>
     <div :id="dynamicId"></div>
     <p>{{ num+10 }}</p>
     <p>{{ flag ? "孙猴子" : "傻猴子" }}</p>
   </div>
 </template>
 ​
 <script>
 export default {
   // innerHTML  innerText
   name: 'HelloWorld',
   data() {
     return {
       message: "学习Vue",
       rawHtml:"<a href='http://www.itbaizhan.com'>百战</a>",
       dynamicId:10001,
       num:10,
       flag:false
     }
   }
 }
 </script>

[1]v-text

文本

文本-->{{}}

若使用JS表达式:

 {{ number + 1 }}
 ​
 {{ ok ? 'YES' : 'NO' }}
 ​
 {{ message.split('').reverse().join('') }}

这些表达式会在当前活动实例的数据作用域下作为 JavaScript 被解析。有个限制就是,每个绑定都只能包含单个表达式.

 <!--  这是语句,不是表达式:-->
 {{ var a = 1 }}
 ​
 <!-- 流程控制也不会生效,请使用三元表达式 -->
 {{ if (ok) { return message } }}

[2]v-html

原始HTML-->v-html

双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用v-html 指令

[4]v-bind

属性 Attribute

温馨提示

v-bind: 可以简写成 :

其中:

加冒号的,说明后面的是一个变量或者表达式; 没加冒号的后面就是对应的字符串常量(String)

2. 条件渲染

功能都为:控制显示

[1]v-if

v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 true 值的时候被渲染。

 <p v-if="flag">我是孙猴子</p>
 data() {
     return {
         flag: true
     }
 }

v-else

你可以使用 v-else 指令来表示 v-if 的“else 块”

 <p v-if="flag">我是孙猴子</p>
 <p v-else>你是傻猴子</p>
 data() {
     return {
         flag: false
     }
 }

[2]v-show

另一个用于条件性展示元素的选项是 v-show 指令

 <h1 v-show="ok">Hello!</h1>

[3]区别

v-if 是“真正”的条件渲染,因为它会确保在切换过程中,条件块内的事件监听器和子组件适当地被销毁和重建。

v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。

相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。

一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好

3.列表渲染

[1]v-for

功能:把一个数组映射为一组元素

其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名

 <ul>
     <li v-for="item in items">{{ item.message }}</li>
 </ul>
 data() {
     return {
         items: [{ message: 'Foo' }, { message: 'Bar' }]
     }
 }

[2]维护状态

当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。

为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一的 key attribute:

 <div v-for="(item,index) in items" :key="item.id|index">
   <!-- 内容 -->
 </div>

4.事件处理

[1]v-on

v-on作用:监听DOM事件

我们可以使用 v-on 指令 (通常缩写为 @ 符号) 来监听 DOM 事件,并在触发事件时执行一些 JavaScript。用法为 v-on:click="methodName" 或使用快捷方式 @click="methodName"

 <button @click="counter += 1">Add 1</button>
 data() {
     return {
         counter: 0
     }
 }

5.表单输入绑定

[1]v-model

v-model:双向数据绑定

双向:既可以获取, 又可以设置

适用元素: <input><textarea><select>

作用:会根据控件类型自动选取正确的方法来更新元素。但 v-model 本质上不过是语法糖。它负责监听用户的输入事件来更新数据,并在某种极端场景下进行一些特殊处理。

以下为修饰符

[2].lazy

在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步 。你可以添加 lazy 修饰符,从而转为在 change 事件之后进行同步

比如:失去焦点时进入同步

[3].trim

去输入首尾空格

6.组件基础

[1]单文件组件

单文件组件:.vue格式

vue文件组成:模版,逻辑,样式

App.vue:根组件

[2]加载组件

第一步:引入组件 import MyComponentVue from './components/MyComponent.vue'

第二步:挂载组件 components: { MyComponentVue }

第三步:显示组件 <my-componentVue />

引入,挂载,显示首字母都可以大写,其中显示组件可用‘-’形式

[3]组件的组织

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

image-20220527181326746.png

7.父传子

Prop类型

Prop传递参数其实是没有类型限制的

 props: {
   title: String,
   likes: Number,
   isPublished: Boolean,
   commentIds: Array,
   author: Object,
   callback: Function
 }

温馨提示

数据类型为数组或者对象的时候,默认值是需要返回工厂模式(使用函数进行返回)

 anArray:{
   type:Array,
   default:function(){
       return[]
   }
 }

8.子传父

自定义事件组件交互

this.$emit(‘事件’,数据)

9.组件生命周期

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

image-20220527183622323.png

为了方便记忆,我们可以将他们分类:

创建时:beforeCreatecreated

渲染时:beforeMountmounted

更新时:beforeUpdateupdated

卸载时:beforeUnmountunmounted

10.Vue引入第三方

寻找第三方

vue2的资源列表里的Awesome Vue

注意:检查第三方支持vue2还是vue3

image-20220904170614017.png

Swiper:

Swiper 开源、免费、强大的触摸滑动插件

Swiper 是纯javascript打造的滑动特效插件,面向手机、平板电脑等移动终端

Swiper 能实现触屏焦点图、触屏Tab切换、触屏轮播图切换等常用效果

温馨提示

官方文档:swiperjs.com/vue

安装指定版本: npm instal --save swiper@8.1.6

11.Axios网络请求

[1]介绍与安装

Axios 是一个基于 promise 的网络请求库

官方文档地址: www.axios-http.cn/docs/intro

以下,具体看文档

安装

 npm install axios

温馨提示

post请求参数是需要额外处理的

  1. 安装依赖: npm install --save querystring
  2. 转换参数格式: qs.stringify({})

[2]使用

1.内容包括:

1.局部引入和全局引入

2.post参数格式转换

3.普通写法与快捷方案

2.代码包括:’HelloWorld.vue’ 与 ‘main.js’

[1]HelloWorld.vue

 <template>
   <div class="hello">
     <p>{{ chengpin.title }}</p>
   </div>
 </template>
 ​
 <script>
 ​
 import axios from "axios"
 import qs from "querystring"
 ​
 export default {
   name: 'HelloWorld',
   data() {
     return {
       chengpin: {}
     }
   },
   mounted() {
     // //1.局部axios用-->axios
     // // 1.1 get请求方式
     // axios({
     //   method: "get",
     //   url: "http://iwenwiki.com/api/blueberrypai/getChengpinDetails.php"
     // }).then(res => {
     //   console.log(res.data);
     //   this.chengpin = res.data.chengpinDetails[0]
     // })
 ​
     // // 1.2 post请求方式
     // axios({
     //   method: "post",
     //   url: "http://iwenwiki.com/api/blueberrypai/login.php",
     //   data: qs.stringify({
     //     user_id: "iwen@qq.com",
     //     password: "iwen123",
     //     verification_code: "crfvw"
     //   })
     // }).then(res =>{
     //   console.log(res.data);
     // })
 ​
     // 2.全局axios用-->this.$axios
     this.$axios.get("http://iwenwiki.com/api/blueberrypai/getChengpinDetails.php")
       .then(res => {
         console.log(res.data);
       })
 ​
     this.$axios.post("http://iwenwiki.com/api/blueberrypai/login.php", qs.stringify({
       user_id: "iwen@qq.com",
       password: "iwen123",
       verification_code: "crfvw"
     })).then(res => {
       console.log(res.data);
     })
   }
 }
 </script>

[2]main.js设置

 import { createApp } from 'vue'
 import App from './App.vue'
 import './registerServiceWorker'
 import axios from "axios"
 ​
 // 将Axios挂载到全局
 const app = createApp(App)
 app.config.globalProperties.$axios = axios
 app.mount('#app')
 ​

12.Axios网络请求封装

看云文档: www.kancloud.cn/yunye/axios…

封装步骤

安装: npm install axios querystring

  1. 创建文件:src/utils/request.js:在用来存储网络请求对象 axios
  2. 在src/api创index.js:存放网络请求方法,创path.js:存放请求路径
  3. import引入后直接使用

1.在src/utils/request.js

 import axios from "axios"
 import qs from "querystring"
 ​
 // 参考文档:https://www.kancloud.cn/yunye/axios/234845
 ​
 const errorHandle = (status,info) => {
     switch(status){
         case 400:
             console.log("语义有误");
             break;
         case 401:
             console.log("服务器认证失败");
             break;
         case 403:
             console.log("服务器拒绝访问");
             break;
         case 404:
             console.log("地址错误");
             break;
         case 500:
             console.log("服务器遇到意外");
             break;
         case 502:
             console.log("服务器无响应");
             break;
         default:
             console.log(info);
             break;
     }
 }
 ​
 ​
 const instance = axios.create({
     // 网络请求的公共配置
     timeout:5000
 })
 ​
 // 拦截器最常用的
 ​
 // 发送数据之前
 instance.interceptors.request.use(
     config =>{
         if(config.methods === "post"){
             config.data = qs.stringify(config.data)
         }
         // config:包含着网络请求的所有信息
         return config;
     },
     error =>{
         return Promise.reject(error)
     }
 )
 ​
 // 获取数据之前
 instance.interceptors.response.use(
     response =>{
         return response.status === 200 ? Promise.resolve(response) : Promise.reject(response)
     },
     error =>{
         const { response } = error;
         // 错误的处理才是我们需要最关注的
         errorHandle(response.status,response.info)
     }
 )
 ​
 export default instance;

2.src/api/path.js

 const base = {
     baseUrl:"http://iwenwiki.com",
     chengpin:"/api/blueberrypai/getChengpinDetails.php"
 }
 ​
 export default base;

3.src/api/index.js

 import axios from "../utils/request"
 import path from "./path"
 ​
 const api = {
     // 诚品详情地址
     getChengpin(){
         return axios.get(path.baseUrl + path.chengpin)
     }
 }
 ​
 export default api

4.组件中直接调用网络请求

 import api from "../api/index"
 ​
 export default {
   mounted(){
     api.getChengpin().then(res =>{
       console.log(res.data);
     })
   }
 }

13.网络请求跨域解决方案

JS采取的是同源策略

同源策略是浏览器的一项安全策略,浏览器只允许js 代码请求和当前所在服务器域名,端口,协议相同的数据接口上的数据,这就是同源策略.

也就是说,当协议、域名、端口任意一个不相同时,都会产生跨域问题,所以又应该如何解决跨域问题呢

解释

  • 域名:http
  • 端口:默认8080
  • 协议:baidu.com

[1]跨域错误提示信息

image-20220530200726999.png

[2]目前主流的跨域解决方案有两种:

  1. 后台解决:cors
  2. 前台解决:proxy
 devServer: {
     proxy: {
       '/api': {
         target: '<url>',
         changeOrigin: true
       }
     }
 }

温馨提示

解决完跨域配置之后,要记得重启服务器才行哦!

(1)组件使用

   import axios from "axios"
   export default{
     mounted(){
       // http://iwenwiki.com/api/FingerUnion/list.php跨域
       axios.get("/api/FingerUnion/list.php")
       .then(res =>{
         console.log(res.data);
       })
     }

(2)vue.config.js

 const { defineConfig } = require('@vue/cli-service')
 module.exports = defineConfig({
   transpileDependencies: true,
   devServer: {
     proxy: {
       '/api': {
         target: 'http://iwenwiki.com',
         changeOrigin: true
       }
     }
   }
 })

(3)重启服务器

14.Vue引入路由配置

Vue是单页面应用

在Vue中,我们可以通过vue-router路由管理页面之间的关系

Vue Router 是 Vue.js 的官方路由。它与 Vue.js 核心深度集成,让用 Vue.js 构建单页应用变得轻而易举

步骤:

第一步:安装路由 npm install --save vue-router

第二步:配置独立的路由文件

 // index.js
 import { createRouter, createWebHashHistory } from 'vue-router'
 import HomeView from '../views/HomeView.vue'
 ​
 const routes = [
   {
     path: '/',
     name: 'home',
     component: HomeView
   },
   {
     path: '/about',
     name: 'about',
     component: () => import('../views/AboutView.vue')
   }
 ]
 ​
 const router = createRouter({
   history: createWebHashHistory(),
   routes
 })
 ​
 export default router

第三步:引入路由到项目

 // main.js
 import router from './router'
 app.use(router)

第四步:指定路由显示入口 <router-view/>

第五步:指定路由跳转

 <router-link to="/">Home</router-link> |
 <router-link to="/about">About</router-link>

15.路由传递参数

页面跳转过程中,是可以携带参数的

步骤:

第一步:在路由配置中指定参数的key

 {
     path:"/list/:name",
     name:"list",
     //这是异步加载方式:如果页面没有显示出来,代码不会执行,节省空间,让首页加载速度更快一些
     component:() => import("../views/ListView.vue")
 }

第二步:在跳转过程中携带参数

 <li><router-link to="/list/内蒙">内蒙旅游十大景区</router-link></li>
 <li><router-link to="/list/北京">北京旅游十大景区</router-link></li>
 <li><router-link to="/list/四川">四川旅游十大景区</router-link></li>

第三步:在详情页面读取路由携带的参数

 <p>{{ $route.params.name }}城市旅游景区详情</p>

16.嵌套路由配置

(1)二级路由代码:

   {
     path: '/about',
     name: 'about',
     // 重定向配置:默认打开哪个二级导航
     redirect:"/about/us",
     component: () => import('../views/AboutView.vue'),
     children:[
       {
         // 二级导航的路径不要加 /
         path:"us",
         component:() => import("../views/AboutSub/AboutUS.vue")
       },
       {
         path:"info",
         component:() => import("../views/AboutSub/AboutInfo.vue")
       }
     ]
   }

(2)路由使用

  1. 指定子路由显示位置<router-view></router-view>
  2. 添加子路由跳转链接
 <!-- to后地址是完整地址 -->
 <router-link to="/news/baidu">百度新闻</router-link> | 
 <router-link to="/news/wangyi">网易新闻</router-link>

17.Vue状态管理(Vuex)

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

Vuex的核心作用:帮我们管理组件之间的状态.

image-20220530160524287.png

引入Vuex的步骤:

第一步:安装Vuex npm install --save vuex

第二步:配置Vuex文件 |路径:src/store/index.js

 import { createStore } from "vuex"
 ​
 // Vuex的核心作用就是帮我们管理组件之间的状态的
 export default createStore({
     // 所有的状态都放在这里(数据)
     state:{
         counter:0
     }
 })

第三步:在主文件中引入Vuex |路径:main.js

 import store from "./store"
 ​
 createApp(App).use(store).mount('#app')

第四步:在组件中读取状态

 ​
 //方法1
 <p>counter:{{ $store.state.counter }}</p>
 ​
 // 方法2
 // 1.vuex提供的state快捷读取方式
 import { mapState } from "vuex"
 ​
 // 2.专门来读取vuex的数据
 computed:{
   ...mapState(["counter"])
 }

18.Vue状态管理核心(Vuex)(未完成)

最常用的核心概念包含: StateGetterMutationAction

1.Getter

对Vuex中的数据进行过滤

 import { createStore } from 'vuex'
 ​
 export default createStore({
   state: {
     counter: 0
   },
   getters: {
     getCount(state){
       return state.counter > 0 ? state.counter : "counter小于0,不符合要求"
     }
   }
 })
 //方法1,多次引用用这个
 import { mapGetters } from 'vuex';
 computed:{
     ...mapGetters(["getCount"])
 }
 ​
 //方法2
 {{ $store.getters.getCounter }}

2.Mutation

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

mutation同时修改数据

同步操作

 import { createStore } from 'vuex'
 ​
 export default createStore({
   state: {
     counter: 0
   },
   getters: {
   },
   mutations: {
     setCounter(state, num) {
       state.counter += num
     }
   }
 })
 import { mapMutations } from 'vuex';
 ​
 methods:{
     ...mapMutations(["setCounter"]),
     clickHandler(){
       // this.$store.commit("setCounter",20)
     // 或者
       // this.setCounter(10)
     }
 }

3.Action

Action 类似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态
  • Action 可以包含任意异步操作

异步操作:网络请求

 import { createStore } from 'vuex'
 import axios from "axios"
 ​
 export default createStore({
   state: {
     counter: 0
   },
   getters: {
     getCount(state){
       return state.counter > 0 ? state.counter : "counter小于0,不符合要求"
     }
   },
   mutations: {
     setCounter(state, num) {
       state.counter += num
     }
   },
   actions: {
     asyncSetCount({ commit }){
       axios.get("http://iwenwiki.com/api/generator/list.php")
       .then(res =>{
         commit("setCounter",res.data[0])
       })
     }
   }
 })
 ​
 import { mapState,mapMutations,mapGetters,mapActions } from 'vuex';
 ​
 methods:{
     ...mapActions(["asyncSetCount"]),
     clickAsyncHandler(){
         // this.$store.dispatch("asyncSetCount")
         // 或者
         // this.asyncSetCount()
     }
 }

19.Vue3新特性1

(1)六大亮点

  • Performance:性能更比Vue 2.0强。
  • Tree shaking support:可以将无用模块“剪辑”,仅打包需要的。
  • Composition API:组合API
  • Fragment, Teleport, Suspense:“碎片”,Teleport即Protal传送门,“悬念”
  • Better TypeScript support:更优秀的Ts支持
  • Custom Renderer API:暴露了自定义渲染API

(2)ref或者reactive

在2.x中通过组件data的方法来定义一些当前组件的数据

 data() {
   return {
     name: 'iwen',
     list: [],
   }
 }

在3.x中通过ref或者reactive创建响应式对象

 import { ref,reactive } from "vue"
 export default {
   name: 'HelloWorld',
   setup(){
       const name = ref("iwen")
       const state = reactive({
           list:[]
       })
 ​
     return{
         name,
         state
     }
   }
 }

(3)methods中定义的方法写在setup()

在2.x中methods来定义一些当前组件内部方法

 methods:{
     http(){}
 }

在3.x中直接在setup方法中定义并return

 setup() {
     const http = ()=>{
         // do something
     }
     return {
       http
     };
 }

(4)setup()中使用props和context

在2.x中,组件的方法中可以通过this获取到当前组件的实例,并执行data变量的修改,方法的调用,组件的通信等等,但是在3.x中,setup()在beforeCreate和created时机就已调用,无法使用和2.x一样的this,但是可以通过接收setup(props,ctx)的方法,获取到当前组件的实例和props

 export default {
   props: {
     name: String,
   },
   setup(props,ctx) {
     console.log(props.name)
     ctx.emit('event')
   },
 }

20.Vue3新特性2

(1)在setup中使生命周期函数

你可以通过在生命周期钩子前面加上 “on” 来访问组件的生命周期钩子。

下表包含如何在 setup () 内部调用生命周期钩子

Options APIHook inside setup
beforeCreateNot needed*
createdNot needed*
beforeMountonBeforeMount
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeUnmountonBeforeUnmount
unmountedonUnmounted
 export default {
   setup() {
     // mounted
     onMounted(() => {
       console.log('Component is mounted!')
     })
   }
 }

(2)Provide / Inject

  • provide() 和 inject() 可以实现嵌套组件之间的数据传递。
  • 这两个函数只能在 setup() 函数中使用。
  • 父级组件中使用 provide() 函数向下传递数据。
  • 子级组件中使用 inject() 获取上层传递过来的数据。
  • 不限层级
 // 父组件
 import { provide } from "vue"
 ​
 setup() {
     provide("customVal", "我是父组件向子组件传递的值");
 }
 // 子组件
 import { inject } from "vue"
 ​
 setup() {
     const customVal = inject("customVal");
     return {
       customVal
     }
 }

(3)Fragment

Fragment翻译为:“碎片”

  • 不再限于模板中的单个根节点
 <template>
   <img alt="Vue logo" src="./assets/logo.png">
   <HelloWorld msg="Welcome to Your Vue.js App" />
 </template>

\