vue配置靜態(tài)

只執(zhí)行一次的命令

1.安裝vscode擴展插件

vetur和Vue 3 Snippets

2.打開vscode終端gitbash--安裝vue-cli腳手架

npm install -g @vue/cli@4

3.查看vue腳手架是否安裝成功

vue --version

4.創(chuàng)建一個新項目

vue create fresh (fresh是項目的名稱--自定義)

5.執(zhí)行命令

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下創(chuàng)建自定義文件夾views,在此創(chuàng)建各個模塊的組件

image.png

模塊的內(nèi)容可被修改

image.png

3.在src文件夾中創(chuàng)建新自定義文件夾router,

在router文件夾中創(chuàng)建一個自定義文件inex.js

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

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

// 路由數(shù)組
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文件夾輸入內(nèi)容

// 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:配置子路由出口(把子路由對應(yīng)的組件渲染在什么地方)

App.vue是根路由文件,在不跳轉(zhuǎn)到其它頁面的情況下,顯示的是最首頁的頁面內(nèi)容

配置子路由

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

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

這個時候,當輸入商品頁面的接口時,就可以輸入/goods,就能跳轉(zhuǎn)到商品頁面

4.底部欄,路由跳轉(zhuǎn)

在App.vue文件中輸入靜態(tài)和樣式

<template>
  <div id="app">
    <!-- 子路由出口(子路由對應(yīng)的組件展示在這里) -->
    <router-view></router-view>
    <footer>
        //利用to='地址'實現(xiàn)點擊該鏈接,跳轉(zhuǎn)到這個路由對應(yīng)的頁面
        //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 跳轉(zhuǎn)而無須重新加載頁面

  3. 使用history需要后端支持, vue-cli創(chuàng)建的devServer可以支持

注意:history模式需要服務(wù)器的支持

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

7. redirect重定向

當訪問 '/', 我們使用redirect使它默認跳到 '/product'這個路由地址頁面

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

8.404配置

假如用戶訪問了一個沒有的路由, 我們讓它跳轉(zhuǎn)到404頁面

在index.js文件中添加,并且在components文件夾中添加一個文件,NotFound(自定義的,但是要和下面的名字一樣)

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

9.配置子路由

9.1.首先,創(chuàng)建存放子路由的文件夾

在需要有子頁面的模塊中新建一個自定義文件夾,用來存放子頁面的路由.,如在goods模塊里面新建一個children文件夾,將goods有關(guān)的文件存放在這里.

image.png

9.2.子路由編寫內(nèi)容

分別子路由的頁面中編寫內(nèi)容,方便查看,(如:商品詳情)

image.png

9.3配置子路由

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

image.png

配置子路由的內(nèi)容,子路由有一個chilrden數(shù)組,存放子頁面的路由接口,其中path:'list'里面不需要有'/',因為是子路由,會自動的拼接成'/goods/list'路由,下面的component中的是子頁面的存放地址


image.png

在到goods模塊里面的goods.vue頁面里面去配置出口


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

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

其中可以看到goods模塊文件夾中有一個分類子頁面,沒有配置出口,是因為它出現(xiàn)在了底部欄中,(不過也可以和goodslist它們配置在同一個地方),但是這里為了方便,我們配置在了外面


image.png

將goods模塊的分類type.vue的子頁面配置在了外面,就是在index.js文件中.沒有子頁面的模塊,就只要配置自己的路由接口就可以了


image.png

10.編寫靜態(tài)

10.1:標簽元素和less樣式的位置

使用less格式編寫樣式的時候,必須添加lang='less'
編寫靜態(tài)標簽元素代碼時,必須把內(nèi)容都用一個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.父子組件通信

知識點

父傳子:父組件通過(綁定)屬性的方式傳數(shù)據(jù)給子組件,子組件使用props接收數(shù)據(jù)

子傳父:父組件在子組件上綁定一個自定義事件,子組件通過$emit觸發(fā)該自定義事件,同時可以傳入數(shù)據(jù)

1:組件的概念

可以將頁面的某一部分做成一個組件,比如頁面的導航欄,底部的tab欄等,組件可以重復(fù)使用

組件分為:局部組件和全局組件

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(固定的)進行配置才能生效

注意:當配置了這個就需要重新啟動服務(wù)才可以,否則會一直報錯

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文件中編寫內(nèi)容即可


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:父傳子

父就相當與最外層來展示的頁面,子就是父頁面內(nèi)部的各個小模塊,這些小模塊通過props來接收父頁面?zhèn)鬟^來的數(shù)據(jù)

父組件通過屬性傳數(shù)據(jù)給子組件

子組件通過props接收父組件傳過來的數(shù)據(jù)

注意:1.通過普通屬性傳遞的數(shù)據(jù)類型是字符串

2.通過:(冒號)綁定屬性傳遞的數(shù)據(jù)類型是所傳數(shù)據(jù)的類型

例子1:父傳子

父頁面

<template>
  <div>
     <h1>demo父組件</h1>
     <hr>
    //使用局部組件時傳過去的數(shù)據(jù)
    //:money="money"利用了冒號綁定事件來獲取data傳來的數(shù)據(jù)
     <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>
      <!-- 使用接收的數(shù)據(jù) -->
      <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. 自定義事件再綁定一個函數(shù)
  2. 這個函數(shù)也可以是自定義的
  3. 子組件使用$emit觸發(fā)(調(diào)用)該事件,并把數(shù)據(jù)以參數(shù)的形式傳給父組件

例子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">
    <!-- 觸發(fā)左邊的事件 -->
    <p @click="$emit('click-left')">
      <van-icon v-if="typeof leftArrow === 'string'" name="arrow-left" />
      <span>{{ leftText }}</span>
    </p>
    <span>{{ title }}</span>
    <!-- 觸發(fā)右邊的事件 -->
    <span @click="handleClick">{{ rightText }}</span>
  </div>
</template>
?
<script>
export default {
  props: ["left-text", "title", "right-text", "left-arrow"], 
?
  methods: {
    handleClick() {
      // 做點事情
      console.log(11111111111111); 
      // 觸發(fā)事件的同時給父組件傳了個對象
      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響應(yīng)數(shù)據(jù)進行攔截

    • 統(tǒng)一處理請求失敗的情況,這樣就不需要在每個組件里處理失敗的情況
    • 有些接口需要登錄才能訪問,在沒登錄的情況下跳轉(zhuǎn)到登錄頁面
  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, // 請求超時時間(因為需要調(diào)試后臺,所以設(shè)置得比較大)
});
?
// 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 響應(yīng)攔截器
service.interceptors.response.use(
  (response) => {
    Toast.clear();
    const res = response.data;
    if (res.code == 666) {
      return res;
    } else {
      // 成功連接到后臺, 但是沒有返回正確的數(shù)據(jù)
      Toast.fail(res.msg);
    }
  },
  (error) => {
    Toast.clear();
    // 跟后臺連接失敗
    Toast.fail("網(wǎng)絡(luò)異常,請稍后再試");
  }
);
?
export default service;
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容