DaZeng:Vue的基础使用及基于vue/cli的开发

21 篇文章 1 订阅
8 篇文章 0 订阅

安装vue/cli

安装:

npm i -g @vue/cli

查看版本号:

vue --version
在这里插入图片描述

卸载:

npm uninstall -g @vue/cli; // 4.x
npm uninstall -g vue-cli // 3.x

创建vue项目

vue create 项目名

在这里插入图片描述

目录介绍

public/ 静态资源目录,不需要编译的文件资源 ,都放里面。

src/ 项目开发源目录

babel.config.js E6 =>es5的配置文件;

.gitignore GIT管理配置文件,设置要忽略的目录。

src–assets/ 放需要webpack编译东西;

components 各类子组件的目录或直接放子组件文件;

router Vue中,前端路由配置文件

store VueX状态管理目录

views 存储页面级别的vue组件;

App.vue 项目的默认的根组件;

main.js 项目的入口配置文件;

Vue生命周期

在这里插入图片描述
生命周期钩子函数:是每个 Vue 实例在被创建时都要经过一系列的初始化过程,例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。
VUE提供一个让用户运行代码的机会的一个API,而这些API,就是生命周期钩子函数。

beforeCreate: 就是Vue实例初始化时,完成创建实例之前;
created: Vue实例初始化结束,实例创建成功之后。

beforeMount: Vue模板编译成功后,在挂载到el指定的DOM之前;
mounted: 挂载到el指定的DOM成功之后。

beforeUpdate: 在更新数据时,完成页面渲染之前;
updated: 重新渲染页面成功之后;

beforeDestroy: 在切换组件或离开组件时,触发这个钩子函数,即销毁组件之前。
destroyed: 销毁组件之后

Vue-router

Vue-router:是通过地址栏的变化,来处理要切换的组件的渲染,并且可以指定渲染的窗口。仅仅是前端单页的一个地址管理,不是后台的接口;

<router-view>

<router-view>组件是一个 functional 组件,渲染路径匹配到的视图组件。<router-view> 渲染的组件还可以内嵌自己的 <router-view>,根据嵌套路径,渲染嵌套组件。

<router-view name="First">
    <About />
</router-view>

<router-link>

<router-link>组件支持用户在具有路由功能的应用中 (点击) 导航。 通过 to 属性指定目标地址,默认渲染成带有正确链接的 <a>标签,可以通过配置 tag 属性生成别的标签.。另外,当目标路由成功激活时,链接元素自动设置一个表示激活的 CSS 类名。

属性:

to: 表示目标地址
to="/home"
:to="{name:'', params:{id:1}}"    this.$route.params.id
:to="{path:'', query:{id: 1}}"   this.$route.query.id;

路由的使用

根路由、重定向、异步导入路由、子路由、默认路由、404页面

//router index.js
import Vue from 'vue'  // 导入Vue
import VueRouter from 'vue-router'  // 导入Vue路由模块
// import Home from '../views/Home.vue' //同步导入常用的组件;

Vue.use(VueRouter)  //让Vue使用Vue-router模块;
const routes = [
// 每一个对象,就是配置的一条路由信息。
  {
    path: '/', //表示访问根路由,渲染首页
    name: 'IndexPage', //路由名,在使用<router-link to="{name: 'Home'}">
    // component: Home //使用哪一个组件来渲染,组件名称。通过import 导入的;
    redirect: "/home"  //重定向路径 
  },
  // 数组的一级成员,对应是一级路由,一级路由的组件,就显示在最外面的<router-view>
  {
    path: "/about",
    name: "about",
    component: () => import("../components/about/About.vue"),//异步导入常用的组件;
    // 一级下面的children:里面的路由,对应的就是二级路由;如果不添加子<router-view>,则不能显示二级路由对应的组件。对应的地址:/about/xxx
    // 只要在childrend添加了子路由,就必须再嵌套一个<router-view>。
    children: [
      {
        path: '',// 设置一个默认的二级路由的页面
        component: () => import("../components/about/AboutQyjs.vue")
      },
      {
        path: "qyjs",//子路由不要以“/”开头,
        name: "qyjs",
        component: () => import("../components/about/AboutQyjs.vue"),
        // 二级路由里面的children, 对应的就是三级路由:/about/qyjs/xx
        // 当前三级路由是在qyjs组件页中添加三级,所以 <router-view />就必须 要写在AboutQyjs.vue中。
        children: [
          {
            path: "a",
            name: "qyjsA",
            component: () => import("../components/about/AboutQyjsA.vue")
          },
          {
            path: "b",
            name: "qyjsB",
            component: () => import("../components/about/AboutQyjsB.vue")
          }
        ]
      },
    {
    path: "*",
    name: "page404",
    component: () => import("../components/404/Page404.vue")
  }
]
// 实例化一个VueRouter路由对象,并把路由配置做参数对象;
const router = new VueRouter({
  routes
})
// 公开 router路由配置模块。
export default router

动态路由

参考博文传送门

params 传参方式:name和params

1、声明式传参

  • 直接传参(单参&多参): <router-link to="/getdata/data1/data"></router-link>
  • 对象传参(单参&多参):<router-link :to=’{name:“GetData”,params:{key1:“data1”,key2:“data2”}}’></router-link>

2、编程式传参

  • 直接传参(单参&多参):this.$router.push("/getdata/data1/data2")
  • 对象传参(单参&多参):this.$router.push({name:“GetData”,params:{key1:“data1”,key2:“data2”}})

3、接收参数

  • 模板页面中:$route.params.key 或 this.$route.params.key
  • this实例中:this.$route.params.key

params路由设置 /:key

{
	path:"/getdata/:key1/:key2",
	name:"getData",
	component:()=>import("@/views/getData.vue")
}

query 传参方式:name/path和query

1、声明式传参

  • 直接传参(单参&多参): <router-link :to="/getdata?key1=data1&key2=data2"></router-link>
  • name 对象传参(单参&多参): <router-link :to=’{name:“GetData”,query:{key1:“data1”,key2:“data2”}}’></router-link>
  • path对象传参(单参&多参): <router-link:to=’{path:"/getdata",query:{key1:“data1”,key2:“data2”}}’></router-link>

2、编程式传参

  • 直接传参(单参&多参): this.$router.push("/getdata?key1=data1&key2=data2")
  • name 对象传参(单参&多参): this.$router.push({name:"",query:{key1:“data1”,key2:“data2”}})
  • path对象传参(单参&多参): this.$router.push({path:"",query:{key1:“data1”,key2:“data2”}})

3、接收参数

  • 模板页面中:$route.query.key 或 this.$route.query.key
  • this实例中:this.$route.query.key

query路由设置

{
	path:"/getdata",
	name:"getData",
	component:()=>import("@/views/getData.vue")
}

Element UI

安装

npm i element-ui -S

引入

main.js 导入element-ui模块

import ElementUI from ‘element-ui’

导入CSS

import ‘element-ui/lib/theme-chalk/index.css’;

Vue.use(模块对象)

Vue.use(ElementUI);

基础使用

布局

用于布局的容器组件,方便快速搭建页面的基本结构:

<el-container>外层容器。当子元素中包含 <el-header> 或 <el-footer> 时,全部子元素会垂直上下排列,否则会水平左右排列。

注:以上组件采用了 flex 布局,使用前请确定目标浏览器是否兼容。此外,<el-container>的子元素只能是后四者,后四者的父元素也只能是 <el-container>。

<el-header>:顶栏容器。

<el-aside>:侧边栏容器。

<el-main>:主要区域容器。

<el-footer>:底栏容器。

通过基础的 24 分栏,迅速简便地创建布局。
通过 row 和 col 组件,并通过 col 组件的 span 属性我们就可以自由地组合布局。

Row 组件 提供 gutter 属性来指定每一栏之间的间隔,默认间隔为 0。

通过制定 col 组件的 offset 属性可以指定分栏偏移的栏数。

排版

将 type 属性赋值为 ‘flex’,可以启用 flex 布局,并可通过 justify 属性来指定 start(左对齐), center(水平居中), end(右对齐), space-between(两端对象), space-around (每个成员两边都有间隔)其中的值来定义子元素的排版方式。

响应式布局

参照了 Bootstrap 的 响应式设计,预设了五个响应尺寸:xs 超小屏幕、sm 小屏幕、md 中等、lg大屏幕和 xl超大

<el-col :xs="8" :sm="6" :md="4" :lg="3" :xl="1">
<div class="grid-content bg-purple"></div>
</el-col>

基于断点的隐藏类

Element 额外提供了一系列类名,用于在某些条件下隐藏元素。这些类名可以添加在任何 DOM 元素或自定义组件上。如果需要,请自行引入以下文件:

import ‘element-ui/lib/theme-chalk/display.css’;

包含的类名及其含义为:

hidden-xs-only - 当视口在 xs 尺寸时隐藏
hidden-sm-only - 当视口在 sm 尺寸时隐藏
hidden-sm-and-down - 当视口在 sm 及以下尺寸时隐藏
hidden-sm-and-up - 当视口在 sm 及以上尺寸时隐藏
hidden-md-only - 当视口在 md 尺寸时隐藏
hidden-md-and-down - 当视口在 md 及以下尺寸时隐藏
hidden-md-and-up - 当视口在 md 及以上尺寸时隐藏
hidden-lg-only - 当视口在 lg 尺寸时隐藏
hidden-lg-and-down - 当视口在 lg 及以下尺寸时隐藏
hidden-lg-and-up - 当视口在 lg 及以上尺寸时隐藏
hidden-xl-only - 当视口在 xl 尺寸时隐藏

button

使用type、plain、round和circle属性来定义 Button 的样式。

type: default(不写),primary,success,info, danger, warning
plain: 无背景色显示
round: 圆角
circle: 圆

侧边栏

 <el-menu
  default-active="/fyfs"
  class="el-menu-vertical-demo"
  @open="handleOpen"
  @close="handleClose"
  background-color="#545c64"
  text-color="#fff"
  active-text-color="#ffd04b"
  :default-openeds="openeds"
  ref="menus"
  :router="true"
>

使用侧边栏不折叠

methods: {
   handleSelect(key, keyPath) {
     console.log(key, keyPath);
   },
   handleOpen(key, keyPath) {
     console.log(key, keyPath);
   },
   handleClose(key, keyPath) {
     console.log(key, keyPath);
     //1.2 设置侧边栏默认不折叠
     this.$refs.menus.open(keyPath);
   }
 }

官方文档

更多详情参考Element

keep-alive和transition

include - 字符串或正则表达式。只有名称匹配的组件会被缓存。
exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。
max - 数字。最多可以缓存多少组件实例。 最小值是2。

当组件在 <keep-alive> 内被切换,它的 activated 和 deactivated 这两个生命周期钩子函数将会被对应执行。

注意嵌套的顺序,过渡组件在最外面

<transition>   
  <keep-alive include="About">  
    <!-- 缓存组件,默认缓存所有组件: -->
    <router-view />
  </keep-alive>
</transition>

书写生命周期:

beforeCreate() {
    console.log('beforeCreate')
},
created() {
    console.log('created');
},
beforeMount() {
    console.log('beforeMount');
},
mounted() {
    console.log('Mounted');
},
beforeUpdate() {
    console.log('beforeUpdate');
},
updated() {
    console.log('updated');
},
beforeDestroy() {
    console.log('beforeDestory');
},
destroyed() {
    console.log('destoryed');
},
deactivated() {
    console.log('deactived');
},
activated() {
    console.log('actived'); 
},

三个框框依次是首次进入组件,切换组件,再次进入组件
在这里插入图片描述
如果没有缓存则这三种情况下依次打印:
首次进入组件:
在这里插入图片描述
切换组件:
在这里插入图片描述
再次进入组件:
在这里插入图片描述

Router编程式导航的方法

router.push()
router.replace(): 跟 router.push 很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录。

router.go(n)
这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)。

router.back()
router.forward()

Route路由信息对象

$route.path:字符串,对应当前路由的路径,总是解析为绝对路径,如 “/foo/bar”。

$route.params :一个 key/value 对象,包含了动态片段和全匹配片段 /user/:id

$route.query: 一个 key/value 对象,表示 URL 查询参数。例如,对于路径 /foo?user=1,则有 $route.query.user == 1,如果没有查询参数,则是个空对象。

$route.matched:类型: Array,一个数组,包含当前路由的所有嵌套路径片段的路由记录 。路由记录就是 routes 配置数组中的对象副本 (还有在 children 数组)。

导航守卫

全局守卫

beforeEach全局前置守卫(router内)

router.beforeEach((to,from,next)=>{
    //可以做导航时的验证;如登录,访问权限等;
    next()
  })

beforeEach和meta的使用(<eg.访问权限>)

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
	  // a meta field
      meta: { requiresAuth: true }
    }
  ]
})

router.beforeEach((to, from, next) => {
//to.matched包括了一级路径和二级路径,是一个数组
  if (to.matched.some(record => record.meta.requiresAuth)) {
    if (!auth.loggedIn()) {
      next({
        path: '/login',
        query: { redirect: to.fullPath }
      })
    } else {
      next()
    }
  } else {
    next() // 确保一定要调用 next()
  }
})

Array.some((item)=>{
return 条件表达式
})
some() 方法用于检测数组中的元素是否满足指定条件(函数提供)。
some() 方法会依次执行数组的每个元素:
如果有一个元素满足条件,则表达式返回true , 剩余的元素不会再执行检测。
如果没有满足条件的元素,则返回false。
注意: some() 不会对空数组进行检测。不会改变原始数组。

before

Resolve全局解析守卫
router.beforeResolve 注册一个全局守卫。这和router.beforeEach 类似,区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。

afterEach全局后置钩子

你也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身。

router.afterEach((to, from) => {
  // ...
})

更改导航标题meta和afterEach

const routes = [
  {
    path: '/',
    redirect:'/home',
    meta:{requiresAuth:true,title:'首页'}
  }
]
router.afterEach((to, from) => {
  // console.log(to)
  document.title = to.meta.title;
})

beforeEnter路由独享守卫

只在配置了的路由上,才会触发该钩子函数;

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        next()
      }
    }
  ]
})

组件内的守卫

const Foo = {
  template: `...`,
  beforeRouteEnter (to, from, next) {
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不!能!获取组件实例 `this`
    // 因为当守卫执行前,组件实例还没被创建
    next(vm => {
    // 通过 `vm` 访问组件实例
  	})
  },
  beforeRouteUpdate (to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 可以访问组件实例 `this`
  },
  beforeRouteLeave (to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以访问组件实例 `this`
  }
}

路由导航的流程理解

导航被触发。(点击超链接时)
在失活的组件里调用 beforeRouteLeave 守卫。
调用全局的 beforeEach 守卫。
在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
在路由配置里调用独享守卫 beforeEnter。
解析异步路由组件。
在被激活的组件里调用 beforeRouteEnter。
调用全局的 beforeResolve 守卫 (2.5+)。
导航被确认。
调用全局的 afterEach 钩子。
触发 DOM 更新。
调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入

Axios

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。

安装

npm i axios --save

使用

main.js引入axios

import axios from ‘axios’

配置基路由

axios.defaults.baseURL = “http://127.0.0.1:8000/api”

全局挂载axios

Vue.prototype.$axios = axios;

发送请求:

// 发送 POST 请求
axios({
  method: 'post',
  url: '/user/12345',
  data: {
    firstName: 'Fred',
    lastName: 'Flintstone'
  }
});

// 发送 GET 请求
axios({
  method: 'get',
  url: '/user/12345',
  params: {
    firstName: 'Fred',
    lastName: 'Flintstone'
  }
});

实际开发使用

在实际的项目开发中,要根据JAVA后台接受的参数做调整。

GET

GET /gxa/post1?uname=aaa&uage=12

let data =  {
        uname: "aaa",
        uage: 12,
    };
this.$axios({
    method: "get",
    url: "/post1",
    headers: { "content-type": "application/x-www-form-urlencoded" },
    params:data,
})

POST

直接传递对象

后台接收到的参数: {uname: “aaa”, uage: 12}

let data =  {
    uname: "aaa",
    uage: 12,
};
this.$axios({
    method: "post",
    url: "/post1",
    headers: { "content-type": "application/json" },
    data:data,
})

JSON.stringify处理对象后传递

后台接收:{“uname”:“aaa”,“uage”:12,“gfInfo”:{“name”:“aaa”,“sex”:0,“age”:18}}

let data =  {uname: "aaa", uage: 12, gfInfo: {name: "aaa", sex: 0, age: 18}};
this.$axios({
    method: "post",
    url: "/post1",
    headers: { "content-type": "application/json" },
    data:JSON.stringify(data)
})

qs处理对象后传递序列化为字符串:%5B %5D<===>[ ]

后台接收:/gxa/post1?uname=aaa&uage=12&gfInfo%5Bname%5D=aaa&gfInfo%5Bsex%5D=0&gfInfo%5Bage%5D=18

//main.js全局引入挂载qs
import qs from 'qs'
Vue.prototype.$qs = qs

----------------------------
let data =  {
    uname: "aaa",
    uage: 12,
};
this.$axios({
    method: "post",
    url: "/post1",
    headers: { "content-type": "application/x-www-form-urlencoded" },
    data:this.$qs.stringify(data) 
})

拦截器的使用

以加载动画为案例

// 声明一个空的对象;
let loadingInstance;
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
  // console.log(config);
  // 在发送请求之前做些什么,全屏加载
  // 显示加载动画
  loadingInstance = ElementUI.Loading.service({ fullscreen: true ,text:"努力加载中...","background":"rgba(0,0,0,0.5)"});
  return config;
}, function (error) {
  // 对请求错误做些什么
  return Promise.reject(error);
});

// 添加响应拦截器
axios.interceptors.response.use(function (response) {
  // 对响应数据做点什么
  // 关闭动画
  loadingInstance.close();
  return response;
}, function (error) {
  // 对响应错误做点什么
  return Promise.reject(error);
});

axios的封装

main.js配置

// 静态资源的基础路径 ,根据项目的部署方式来修改IP。
Vue.prototype.staticBaseUrl= 'http://127.0.0.1:8000'

// 导入封装了token功能 的axios实例的模块;
import axios from './http/http.js';
Vue.prototype.$axios = axios;

http/http.js配置

import Axios from "axios";
import router from './../router'
import { Loading } from 'element-ui';
// 创建一个axios实例
let http = Axios.create({
    timeout: 10000,
    baseURL: process.env.VUE_APP_BASE_URL
});

export default http;

let loadingInstance;
// 请求前拦截,
http.interceptors.request.use(
    reqConfig => {
        // console.log('请求前:', reqConfig);

        // 当你登录 成功后,会在本地存储一个sessionStorage.setItem("token","sdfasfd2323"),
        let token = sessionStorage.getItem('token');
        // 如果有存储token,则把token添加到请求头。
        // 要问一下后端token验证时,headers中是哪一个属性名;
        token && (reqConfig.headers['authenticate'] = token);
        // 显示加载动画
        loadingInstance = Loading.service({ fullscreen: true, text: "努力加载中...", "background": "rgba(0,0,0,0.5)" });
        return reqConfig
    },
    error => Promise.reject(error));
//响应后干什么
http.interceptors.response.use(resp => {
    // console.log(resp)
    //后台给我们token 存起来
    // 直接把拦截器放到main.js中,多一个.data
    // resp.data.data.token && sessionStorage.setItem('token',resp.data.data.token);
    //封装在HTTP.JS中,就少写一个.data;
    // 如果响应回来 的数据中,带有token,就把token做本地存储;自动更新token;
    resp.data.token && sessionStorage.setItem('token', resp.data.token);

    // 关闭动画
    loadingInstance.close();
    
    return resp
}, error => {
    // error直接打出来,是错误信息的内容;
    // console.log(error)
    // 但是error也是 一个对象;
    // console.log(error.response)
    let _resp = error.response;
   
    switch (_resp.status) {
        case 401:
        case 500:
            // 哪些情况下,需要清除token,请自己添加case 状态码;
            //把本地的token清除  跳转到login
            sessionStorage.removeItem('token')
            // sessionStorage.removeItem('userName')
            // sessionStorage.removeItem('type')
            // alert('身份已过期,请重新登录')
            return router.push('/login')  // 跳转到登录页面;
    }
    return Promise.reject(error.response.data)
});

v-slot插槽缩写#

slot:组件功能的扩展
父组件:

<ProductZhanShi title="全球预售">
   <template>
        预售倒计时 0天12小时2分10秒
   </template>
   <template v-slot:more>
       <span>More</span>
    </template>
 </ProductZhanShi>

子组件:

<!-- 默认的插槽, 在调用子组件时,把子组件当双标签使用,标签元素的内容,默认就是传递给默认插槽的数据; -->
 <!-- 一个不带 name 的 <slot> 出口会带有隐含的名字“default”。 -->
<slot></slot>
 <!--  具名的插槽 -->
<slot name="more"></slot>

插槽绑定值传给父组件

子组件:

<slot name="userInfo"  :user="tempData" :age="18"></slot>

父组件:

<template v-slot:userInfo="{user, age}">
   <h3>{{user.username}}</h3>
   <h1>{{user.userpwd}}</h1>
   <h1>{{age}}</h1>
</template>


//或者
<template #userInfo="{user, age}">
   <h3>{{user.username}}</h3>
   <h1>{{user.userpwd}}</h1>
   <h1>{{age}}</h1>
</template>

当然也可以传递对象:

//子组件
<slot name="userInfo"  :scope="{user:{}, age:18}" ></slot>

//父组件
<template #userInfo="scope">
   <h3>{{scope.user.username}}</h3>
   <h1>{{scope.user.userpwd}}</h1>
   <h1>{{scope.age}}</h1>
</template>

跨域

后端配置了CORS跨域

前端不做代理;
开发环境下:
axios.defaults.baseURL = “http://172.16.2.34:8000/api”

打包前: 要修改axios.defaults.baseURL;
部署在JAVA环境下: axios.defaults.baseURL = "/gxa"带前缀 || ""不带前缀;

前后端分离部署:
nginx来部署前端,通过Nginx代理来请求JAVA服务器;
axios.defaults.baseURL = “/api”

代理服务器

axios.defaults.baseURL = “/api”
代理服务器,只在开发环境下有效!

设置vue.config.js文件:

module.exports = {
    publicPath: process.env.NODE_ENV === 'production' ? './' : '/',
    devServer: {  //开发用的服务器配置
        proxy: {
            // 前端/api/login  =传给后台=> 后台/gxa/login
            '/api': {
                target: 'http://127.0.0.1:8000',  //这里是目标服务器地址
                changeOrigin: true, //改变源地址,必须是true,代理才有效
                pathRewrite: { //路径重写
                    // 如果后端完整的接口名,没有/api,就替换成"",如果有,就把/api,替换成指定的前缀。
                    //表示把前端所有的/api换为/gxa
                    '^/api': '/gxa'       //这里一定要为空
                }
            },
            //代理不同的地址
            '/bpi':{
                target: 'http://127.0.0.1:8001',
                changeOrigin: true,
                pathRewrite: {
                    '^/api': ''
                }
            }
        }
    }
}

自动切换baseURL

添加.env.development和.env.production两个文件。
在这里插入图片描述
分别写入:

VUE_APP_BASE_URL=’/api’
VUE_APP_BASE_URL=’/gxa’

配置axios,所有的后台接口请求,都会带上baseURL的值做基础路径:

axios.defaults.baseURL = process.env.VUE_APP_BASE_URL

文件上传

案例上传多张图片并预览

<form name="photoList">
   <div class='file'>选择文件
        <input type="file" name="photo" multiple @change='getFile' class='addfile'/>
        | 已选:<span v-for='(obj,index) in photoname' :key='index'>{{obj}} 🐷 </span>
    </div>
</form> 
<el-button type="primary" @click="mySubmit">保存图片</el-button>
 getFile(){
    let fileIpt = document.getElementsByName("photo")[0];
    // 获取上传文件的对象的值fileIpt.files;
    this.$data.photoList.files = fileIpt.files;
    console.log('photoList',this.$data.photoList);
    this.$data.photoname = []
    for(let i =0;i<fileIpt.files.length;i++){
        this.$data.photoname.push(fileIpt.files[i].name)
    }

},

 mySubmit() {
       let formData = new FormData()
       //每一个formData内的数据都要单独append
       //给formData添加files对象
       for(let i = 0;i<this.$data.photoList.files.length;i++){
           formData.append('files',this.$data.photoList.files[i])
       }
       //给formData添加id值
       formData.append('id',this.$data.fid)
       formData.append('zhaoPianDiZhi',this.$data.zhaoPian)
       console.log('formData',formData);
       this.$axios({
           method: "post",
           url: "/fangJian/shangChuanTuPian",
           //必须修改请求头,且不需要序列化
           headers: { "content-type": "multipart/form-data" },
           data: formData
       }).then((res)=>{
           console.log(res);
            if(res.status==200){
               console.log('上传图片成功',res);
               this.$message({
                   message:'上传图片成功',
                   type:'success'
               })
               //页面刷新数据
               this.reload()
           }
       })
   },

页面自动刷新(如请求成功刷新页面数据)

使用provide和inject

App.vue

<template>
  <div id="app">
    <router-view v-if="isRouterAlive"/>
  </div>
</template>

<script>
export default {
  name: 'App',
  provide () {
    return {
      reload: this.reload
    }
  },
  data () {
    return {
      isRouterAlive: true
    }
  },
  methods: {
    reload () {
      this.isRouterAlive = false
      this.$nextTick(function () {
        this.isRouterAlive = true
      })
    }
  }
}
</script>

在要使用刷新的vue页面中:

inject:['reload'],
methods: {
	mySubmit() {
        this.$axios({
            //...
        }).then((res)=>{
             if(res.status==200){
                //页面刷新数据 也可以加一个setTimeout定时器
                this.reload()
            }
        })
    },
}

VueX

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

安装

npm i --save vuex

基础使用

在src下,创建一个store目录 ,再store创建一个index.js;

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

Vue.use(Vuex)

//导出一个Vuex.Store 仓库的实例
export default new Vuex.Store({
  state: {
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }
})

在main.js中,引入index.js

import store from './store/index.js"
//import store from './store',//或者,默认就是找这个目录下的index.js文件。

//再把store注入Vue实例中;
new Vue({
  router,
  store,  //可以在组件中,通过 this.$sotre拿获取Store中的状态和方法。
  render: h => h(App)
}).$mount('#app')

VueX应用

dispatch传值给actions做数据存储

this.$store.dispatch(‘setAllfs’,res.data.data)

actions处理dispatch函数,提交commit给mutations

actions: {
    //方式一
    // setAllfs(context,obj){
    //   context.commit('setAllfsData',obj)
    // }
    //方式二
    setAllfs({commit},obj){
      commit('setAllfsData',obj)
    }
  },

mutations处理actions函数,更改state数据

state: {
    allfsdata:[]
  },
mutations: {
  setAllfsData(state,obj){
    state.allfsdata = obj
  }
},

getter:Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

 getters: {
    getData(state){
      return state.allfsdata
    }
  }

使用getters,当状态的值改变时,页面没有重选渲染,就要使用getters

<div>{{$store.getters.getData}}</div>

注:只允许在actions中的任务方法中,实现异步的逻辑代码;不允许在 mutations 中写异步的逻辑代码,因为VueTools中不能跟踪到state的改变。规范中就要求不要在mutations中写异步。

VueX映射

import {mapState,mapActions,mapGetters,mapMutations} from “vuex”

   // 映射Store中的State和getters, 当本组内部的计算属性来使用;
  computed:{
    ...mapState(['loginState','userInfo']),
    ...mapGetters(['_login'])
  },
  // 映射mutations, actions, 当本组内部的方法来使用;如果不需要传参数,就直接使用,如果要传参数,就需要单独声明一个方法,来调用映射过来的方法。
  methods: {
    ...mapActions(['testLogin']),//指向dispatch
    ...mapMutations(['testAsync']),//指向commit

    _testAsync(){
      this.testAsync("hello") ;因为需要传参数 ,所以单独声明一个函数来调用它
    },
    _testLogin(){
      this.$store.dispatch("testLogin")
    },
  }
 

$refs

一个对象,持有注册过 ref attribute 的所有 DOM 元素和组件实例。

<ShopCars ref="shopCars" :table-data="shopCars" @my-jia="myJia" @my-jian="myJian"></ShopCars>

<el-button type="success" @click="orderTrue">下订单</el-button>
orderTrue(){
//打印所有的选中项
 console.log(this.$refs.shopCars.multipleSelection);
}

Bus

EventBus 主要解决非父子组件之间的通信。不适合用于大型的项目;大型项目,一般用Vuex来处理;

import Vue from ‘vue’;
let Bus = new Vue();
export default Bus;

创建bus.js
凡是要共享数据 的组件,都要引用bus.js文件;每一个Vue实例对象,都会有一个$on(),$emit()两个方法;
Bus.$on(自定义的事件名,回调函数(形参)): 监听事件
Bus.$emit(自定义的事件名, 实际参数): 触发事件
Bus.$off(自定义的事件名) : 销毁事件

$parent、$children、$root

$parent:获取当前组件的直接父组件的实例对象。可以链式写法。

$children:获取直接子组件的实例对象,如果有多个直接的子组件对象,它们的顺序是不固定的。$children返回一个数组对象。

$:当前组件树的根 Vue 实例。如果当前实例没有父实例,此实例将会是其自己。

$attrs

<AttrSubCom :html="course.html" :css="course.css" :js="course.js" :vue="vue"></AttrSubCom>
   props:["html","css"],
   created() {
        // 可以看到所有props声明过的属性;console.log(this.$props);//["html","css"],
        // 父组件给绑定了的属性,但props中没有声明有,可以通过$attrs来获取。
        console.log(this.$attrs); //{js,vue}
    }
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Da Zeng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值