vue配置静态

只执行一次的命令

1.安装vscode扩展插件

vetur和Vue 3 Snippets

2.打开vscode终端gitbash--安装vue-cli脚手架

npm install -g @vue/cli@4

3.查看vue脚手架是否安装成功

vue --version

4.创建一个新项目

vue create fresh (fresh是项目的名称--自定义)

5.执行命令

npm run serve

6.devtool在谷歌浏览器上下载插件

下载极简插件地址: https://chrome.zzzmh.cn/#/index 搜索vue找到需要下载的插件,安装在谷歌浏览器上

7.安装less模块,允许使用less编写样式

npm install less less-loader@6.0.0 --save-dev
(在style里面编写less样式时,style标签后面需要添加样式格式,也就是lang="less")

配置简单的路由

1.安装路由插件

npm i vue-router@3.0

2.在src下创建自定义文件夹views,在此创建各个模块的组件

image.png

模块的内容可被修改

image.png

3.在src文件夹中创建新自定义文件夹router,

在router文件夹中创建一个自定义文件inex.js

3.1:在index.js文件中配置并导出路由模块

//导入模块
import Vue from "vue";
import Router from "vue-router";
//使用模块
Vue.use(Router);

// 路由数组
const routes = [
  {
      //根目录地址加/goods就是商品页面的地址
    path: "/goods",
      //这个页面的在文件中的地址
    component: () => import("../views/goods/goodsList.vue")
  },
  {
    path: "/type",
    component: () => import("../views/goods/type.vue")
  },
  {
    path: "/cart",
    component: () => import("../views/cart/cart.vue")
  },
  {
    path: "/my",
    component: () => import("../views/my/my.vue")
  }
];

const router = new Router({
  routes
});
//导出路由模块
export default router;

3.2:挂载路由

在自动生成的main.js文件夹输入内容

// main.js 代码
import Vue from 'vue'
import App from './App.vue'
//导入这个模块路由
import router from './router/index'
?
Vue.config.productionTip = false
?
new Vue({
  // 把router挂载到vue实例
  router,
  render: h => h(App),
}).$mount('#app')

3.3:配置子路由出口(把子路由对应的组件渲染在什么地方)

App.vue是根路由文件,在不跳转到其它页面的情况下,显示的是最首页的页面内容

配置子路由

在App.vue文件中输入路由出口

<template>
  <div id="app"> 
    <!-- 路由出口 -->
    <router-view></router-view>
  </div>
</template>

这个时候,当输入商品页面的接口时,就可以输入/goods,就能跳转到商品页面

4.底部栏,路由跳转

在App.vue文件中输入静态和样式

<template>
  <div id="app">
    <!-- 子路由出口(子路由对应的组件展示在这里) -->
    <router-view></router-view>
    <footer>
        //利用to='地址'实现点击该链接,跳转到这个路由对应的页面
        //router-link就相当与a标签
      <router-link to="/goods">首页</router-link>
      <router-link to="/type">分类</router-link>
      <router-link to="/cart">购物车</router-link>
      <router-link to="/my">我的</router-link>
    </footer>
  </div>
</template>
<style lang="less">
body {
  background: #f4f4f4;
}
footer {
  position: fixed;
  bottom: 0;
  height: 50px;
  background: #fff;
  display: flex;
  justify-content: space-around;
  align-items: center;
  width: 100%;
}
</style>

5.active-class

active-class是vue-router模块的router-link组件中的属性,用来做选中样式的切换;
//目前在App.vue页面中

<footer>
    <router-link active-class="active" to="/goods">首页</router-link>
    <router-link active-class="active" to="/type">分类</router-link>
    <router-link active-class="active" to="/cart">购物车</router-link>
    <router-link active-class="active" to="/my">我的</router-link>
</footer>

6.history模式

  1. vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。

  2. 如果不想要很丑的 hash,我们可以用路由的 history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面

  3. 使用history需要后端支持, vue-cli创建的devServer可以支持

注意:history模式需要服务器的支持

//index.js
const router = new VueRouter({
  mode: 'history',  // 默认hash
  routes: [...]
})

7. redirect重定向

当访问 '/', 我们使用redirect使它默认跳到 '/product'这个路由地址页面

//index.js
{
    path: '/',
    redirect: '/product'
},

8.404配置

假如用户访问了一个没有的路由, 我们让它跳转到404页面

在index.js文件中添加,并且在components文件夹中添加一个文件,NotFound(自定义的,但是要和下面的名字一样)

//index.js
{
    path: '*',
    component:()=>import('@/components/NotFound')
  }

9.配置子路由

9.1.首先,创建存放子路由的文件夹

在需要有子页面的模块中新建一个自定义文件夹,用来存放子页面的路由.,如在goods模块里面新建一个children文件夹,将goods有关的文件存放在这里.

image.png

9.2.子路由编写内容

分别子路由的页面中编写内容,方便查看,(如:商品详情)

image.png

9.3配置子路由

在上面新建配置路由的文件index.js中来配置子路由

image.png

配置子路由的内容,子路由有一个chilrden数组,存放子页面的路由接口,其中path:'list'里面不需要有'/',因为是子路由,会自动的拼接成'/goods/list'路由,下面的component中的是子页面的存放地址


image.png

在到goods模块里面的goods.vue页面里面去配置出口


image.png
//goods.vue
<template>
  <div>
    <!-- 子路由出口 -->
    <router-view></router-view>
    <!-- 子路由跳转 -->
    <router-link to="/goods/list"></router-link>
    <router-link to="/goods/detail"></router-link>
  </div>
</template>
<script>
export default {

}
</script>
<style>
</style>

其中可以看到goods模块文件夹中有一个分类子页面,没有配置出口,是因为它出现在了底部栏中,(不过也可以和goodslist它们配置在同一个地方),但是这里为了方便,我们配置在了外面


image.png

将goods模块的分类type.vue的子页面配置在了外面,就是在index.js文件中.没有子页面的模块,就只要配置自己的路由接口就可以了


image.png

10.编写静态

10.1:标签元素和less样式的位置

使用less格式编写样式的时候,必须添加lang='less'
编写静态标签元素代码时,必须把内容都用一个div包起来

10.2:支持less格式操作

安装插件,编写代码
npm install less less-loader@6.0.0 --save-dev

image.png

11.配置公共样式和字体图标

1:安装插件

npm i vant@latest-v2 -S

2:生成公共样式和字体图标的样式

字体图标尽量下载到本地使用
样式一般都放到src/assets文件夹下,新建一个自定义style文件夹,将公共样式和字体图标放入进去,并且注意将字体图标单独放一个文件件.


image.png

3.导入所有的样式

在style文件夹中新建一个自定义文件index.js,将需要的样式导入到这个文件中,然后外面使用时,就只要导入这个index.js文件就可以了

//index.js
//如果有多个也可以导入进来
import '../style/font/iconfont.css';
import '../style/common.css';

4.外部导入所有的样式(包括安装的插件样式)

在main.js根文件中来导入样式(注意:地址要对),这样就可以被其它的页面所使用了

图1:导入公共样式和字体图标的样式
image.png
图2:导入插件的样式
//main.js
import Vue from 'vue';
import App from './App.vue';
import router from './router/index';
import Vant from 'vant';
//公共样式和字体图标
import './assets/style/index.js';
import 'vant/lib/index.css';
//使用Vant插件样式
Vue.use(Vant);
Vue.config.productionTip = false
new Vue({
  router,
  render: h => h(App),
}).$mount('#app')

5.使用公共样式

image.png

12.父子组件通信

知识点

父传子:父组件通过(绑定)属性的方式传数据给子组件,子组件使用props接收数据

子传父:父组件在子组件上绑定一个自定义事件,子组件通过$emit触发该自定义事件,同时可以传入数据

1:组件的概念

可以将页面的某一部分做成一个组件,比如页面的导航栏,底部的tab栏等,组件可以重复使用

组件分为:局部组件和全局组件

2:全局组件

全局组件写在main.js页面中,哪里使用就直接使用不需要导入

通过Vue.component()来定义全局组件

定义全局组件必须放在new vue()

//main.js
//全局组件
//Hello就是这个全局组件名,(自定义的)
Vue.component('Hello',{
  data(){
     return{
      title:'华夏中国'
     } 
  },
  template:`<h2>{{title}}</h2>`
})

哪一个页面需要使用这个全局组件,就直接使用组件就可以了,不需要导入

//方式1
<Hello></Hello>
//方式2
<Hello/>
image.png

使用全局组件,需要在文件中新建一个文件vue.config.js(固定的)进行配置才能生效

注意:当配置了这个就需要重新启动服务才可以,否则会一直报错

const path = require('path');
module.exports = {
  lintOnSave: false,
  configureWebpack: (config) => {
    config.resolve = {
      extensions: [".js", ".vue", ".json", ".css"],
      alias: {
        vue$: "vue/dist/vue.esm.js",
        "@": path.resolve("src")
      }
    };
  }
};

3:局部组件

局部变量需要导入才能使用,尽量将公共局部组件写在自动生成的components文件夹中

如:在components文件夹中新建一个局部组件Footer.vue(这是底部导航栏,一般都是大部分页面需要的).然后在这个Footer.vue文件中编写内容即可


image.png
<template>
  <div>
    <footer class="fixed w100p bg-fff flex jc-sa aic f14">
        <router-link active-class="active" to="/goods">
            <p class="flex fdc jc-c aic">
                <i class="iconfont icon-home"></i>
                <span>首页</span>
            </p>
        </router-link>
        <router-link active-class="active" to="/type">
            <p class="flex fdc jc-c aic">
                <i class="iconfont icon-fenlei"></i>
                <span>分类</span>
            </p>
        </router-link>
        <router-link active-class="active" to="/cart">
            <p class="flex fdc jc-c aic">
                <i class="iconfont icon-gouwuchexian"></i>
                <span>购物车</span>
            </p>
        </router-link>
       <router-link active-class="active" to="/my">
        <p class="flex fdc jc-c aic">
            <i class="iconfont icon-wode"></i>
            <span>我的</span>
        </p>
       </router-link>
       <router-link active-class="active" to="/demo" href="./个人中心.html">
        <p class="flex fdc jc-c aic">
            <i class="iconfont icon-wode"></i>
            <span>demo</span>
        </p>
       </router-link>
    </footer>
  </div>
</template>

<script>
export default {

}
</script>

<style lang="less">
  footer{
      bottom: 0;
      height: 50px;
  }
  footer p .iconfont{
      font-size: 20px;
  }
  a{
      text-decoration: none;
      color: #999;
  }
  .active{
    color: red;
  }
</style>

使用局部组件Footer

在使用局部组件的时候,需要先导入局部组件再使用components去注册组件才能使用,哪个页面使用该局部组件,就导入再注册就可使用

注意:注册多个组件,使用逗号分隔开

//假如是购物车页面需要的底部导航栏组件
//cart.vue
<template>
  <div>
    <!-- 使用组件 -->
    <Footer />
  </div>
</template>
<script>
//导入底部导航栏组件
import Footer from '@/components/Footer.vue';
export default {
  components:{
    //注册组件
    Footer,
  }
}
</script>

4:父传子

父就相当与最外层来展示的页面,子就是父页面内部的各个小模块,这些小模块通过props来接收父页面传过来的数据

父组件通过属性传数据给子组件

子组件通过props接收父组件传过来的数据

注意:1.通过普通属性传递的数据类型是字符串

2.通过:(冒号)绑定属性传递的数据类型是所传数据的类型

例子1:父传子

父页面

<template>
  <div>
     <h1>demo父组件</h1>
     <hr>
    //使用局部组件时传过去的数据
    //:money="money"利用了冒号绑定事件来获取data传来的数据
     <Son msg="hello world"  :money="money"  :count="true"/>
  </div>
</template>
?
<script>
 //导入局部组件
import Son from './Son.vue';
export default {
    //注册局部组件
  components: {
    Son
  },
?
  data() {
    return {
      money: 2000
    }
  }
};
</script>

子页面

<template>
  <div>
      <h4>这是子组件</h4>
      <!-- 使用接收的数据 -->
      <p>{{msg}}</p>
      <p>{{money}}</p>
      <p>{{typeof count}}</p>
  </div>
</template>
?
<script>
export default {
    // 接收msg,money,count属性
    props: ['msg','money','count']
}
</script>

例子2:父传子的实践

把生鲜首页拆分为多个子组件

注意:一个组件一个页面

<template>
  <div> 
    //轮播图的组件
    <Swiper/>
    //秒杀的组件
    <Miaosha/>
    //商品分类的组件
    <TypeList/> 
    //底部导航栏的组件
    <Footer/>
  </div>
</template>
?
<script>
   //导入各个组件
import Footer from '@/components/Footer.vue';
import Swiper from "./goodList/Swiper.vue";
import Miaosha from "./goodList/Miaosha.vue";
import TypeList from "./goodList/TypeList.vue";
export default {
    //注册各个组件
  components: {
    Footer,
    Swiper,
    Miaosha,
    TypeList
  }
};
</script>

5:子传父

父组件在子组件上绑定了一个自定义事件(事件名称我们自己定义,就是vue本身没有的事件)

  1. 自定义事件再绑定一个函数
  2. 这个函数也可以是自定义的
  3. 子组件使用$emit触发(调用)该事件,并把数据以参数的形式传给父组件

例子1:一个简单的例子

父组件页面

<template>
  <div>
    <h3>父组件</h3>
    <hr />
    <Son @aaa="say"/>
  </div>
</template>
?
<script>
import Son from "./Son";
export default {
  components: {
    Son,
  },
  data() {
    return { 
    };
  },
  methods: {
    say(data) {
      alert(data)
    }
  } 
};
</script> 

子组件页面

<template>
  <div>
    <h4>子组件</h4>
    <button @click="handleClick">点击</button>
  </div>
</template>
?
<script>
export default {
  methods: {
    handleClick() {
      this.$emit("aaa", "我是子组件");
    }
  }
};
</script>

例子2:自定义导航栏组件

//Header.vue

<template>
  <div class="nav flex jc-sb aic pl-15 pr-15">
    <!-- 触发左边的事件 -->
    <p @click="$emit('click-left')">
      <van-icon v-if="typeof leftArrow === 'string'" name="arrow-left" />
      <span>{{ leftText }}</span>
    </p>
    <span>{{ title }}</span>
    <!-- 触发右边的事件 -->
    <span @click="handleClick">{{ rightText }}</span>
  </div>
</template>
?
<script>
export default {
  props: ["left-text", "title", "right-text", "left-arrow"], 
?
  methods: {
    handleClick() {
      // 做点事情
      console.log(11111111111111); 
      // 触发事件的同时给父组件传了个对象
      this.$emit("click-right", {username: '张三', age:18});
    }
  }
};
</script>
?
<style lang="less" scoped>
.nav {
  height: 50px;
  border: 1px solid;
}
</style>

//demo.vue

//哪个页面需要就导入
<template>
  <div>
    <NavBar @click-left="onClickLeft"  @click-right="onClickRight" left-text="返回" title="购物车" right-text="编辑" left-arrow/>
  </div>
</template>
?
<script>
import NavBar from "@/components/NavBar.vue";
export default {
  components: {
    NavBar
  },
?
  data() {
    return {
      money: 2000
    };
  },
?
  methods: {
    onClickLeft() {
      alert("点击左边");
    },
    onClickRight(data) {
      alert(data.username);
    }
  }
};
</script>

13:配置axios拦截器

  1. 对ajax请求进行拦截

    • 在请求头添加token
  2. 对ajax响应数据进行拦截

    • 统一处理请求失败的情况,这样就不需要在每个组件里处理失败的情况
    • 有些接口需要登录才能访问,在没登录的情况下跳转到登录页面
  3. 需要配置axios拦截器

    在src文件夹下新建一个自定义文件夹api,在api文件夹下新建一个自定义文件ruquest.js

//ruquest.js
import axios from "axios";
import Vue from "vue";
import { Toast } from "vant";
Vue.use(Toast);
?
const service = axios.create({
  baseURL: "http://huruqing.cn:3003",
  timeout: 50000, // 请求超时时间(因为需要调试后台,所以设置得比较大)
});
?
// request 对请求进行拦截
service.interceptors.request.use(
  (config) => {
    // 开启loading
    Toast.loading({
      message: "加载中...",
      forbidClick: true,
      loadingType: "spinner",
    });
    // 请求头添加token
    config.headers["token"] =
      "gg12j3h4ghj2g134kj1g234gh12jh34k12h34g12kjh34kh1g";
    return config;
  },
  (error) => {
    Promise.reject(error);
  }
);
?
// response 响应拦截器
service.interceptors.response.use(
  (response) => {
    Toast.clear();
    const res = response.data;
    if (res.code == 666) {
      return res;
    } else {
      // 成功连接到后台, 但是没有返回正确的数据
      Toast.fail(res.msg);
    }
  },
  (error) => {
    Toast.clear();
    // 跟后台连接失败
    Toast.fail("网络异常,请稍后再试");
  }
);
?
export default service;
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容