組件化開發(fā)、Vue Router飞苇、Vue CLI

此筆記是我在拉勾學(xué)習(xí)課程過程中的總結(jié)菌瘫,文字原創(chuàng)洋闽,筆記里很多技巧和知識是老師總結(jié)的,如果有侵權(quán)突梦,請聯(lián)系本人诫舅!

組件化開發(fā)、Vue Router宫患、VueCLI

Vue.js組件

用于將每個區(qū)域進(jìn)行封裝刊懈,將結(jié)構(gòu)、樣式娃闲、邏輯代碼封裝為整體虚汛。
提高功能復(fù)用性和可維護(hù)性。
組件使用時為自定義的html標(biāo)簽皇帮,通過組件作名為自定義標(biāo)簽名

組件的注冊

全局注冊

全局注冊的組件可以用于任意實例或組件中Vue.component('組件名'卷哩,{選項對象})
注:
全局注冊必須在根Vue實例之前創(chuàng)建,需要在根實例之內(nèi)使用

  <div id="app">
   <p>這是p標(biāo)簽</p>
   <my-compoment></my-compoment>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    // 全局組件
      Vue.component('my-compoment',{
        template: '<div>這是第一個我們自己的組件</div>'
      });
      
      // 根實例
      new Vue({
        el:'#app',
        data: {

        }
      });
  </script>

組件基礎(chǔ)

  • 組件是可服用的Vue實例属拾,可以與 new Vue接收相同的選項将谊,例如data,methods以及生命周期鉤子等。

  • 但是 el 這種跟實例特有的選項不行

  • 組件命名規(guī)則:
    · kebab-case:"my-component"
    · PascalCase:"MyComponent"
    注意:
    無論哪種命名方式,dom 中只有kebab-case方法命名可用

  • template選項
    · 用于設(shè)置組件結(jié)構(gòu)电抚,最終被引入根實例或者其他組件中

    · template只能有一個根元素,不可在根元素同級設(shè)置根元素

  • data選項

    · data用于存儲數(shù)據(jù)栋齿,但是組件的data必須為函數(shù),數(shù)據(jù)設(shè)置在返回值對象中

    · 這種實現(xiàn)方式是為了確保每個組件實例可以維護(hù)一份被返回的對象獨立的拷貝襟诸,不會相互影響

局部注冊

  • 只用于當(dāng)前實例或組件中
    new Vue({
      el: '#app',
      data: {

      },
      // 組件
      components: {
        // 組件a
        'my-com-a': {
          template:`
          <div>
            <h3>{{title}}</h3>
            <p>{{content}}</p>
          </div>
          `,
          data () {
            return {
              title:'組件 A 標(biāo)題',
              content:'組件 A 內(nèi)容'
            }
          }
        },
        // 組件b
        'my-com-b': {
          template:`
          <div>
            <h3>{{title}}</h3>
            <p>{{content}}</p>
          </div>
          `,
          data () {
            return {
              title:'組件 B 標(biāo)題',
              content:'組件 B 內(nèi)容'
            }
          }
        }
      }
    });
  • 單獨配置組件的選項對象
  <div id="app">
    <my-com-a></my-com-a>
    <my-com-b></my-com-b>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    // 組件a的選項對象
    var MyComponentA = {
      // 組件a
      template:`
          <div>
            <h3>{{title}}</h3>
            <p>{{content}}</p>
          </div>
          `,
          data () {
            return {
              title:'組件 A 標(biāo)題',
              content:'組件 A 內(nèi)容'
            }
          }
      
    };
    var MyComponentB = {
      template:`
          <div>
            <h3>{{title}}</h3>
            <p>{{content}}</p>
          </div>
          `,
          data () {
            return {
              title:'組件 B 標(biāo)題',
              content:'組件 B 內(nèi)容'
            }
          }
    }
    new Vue({
      el: '#app',
      data: {

      },
      // 組件
      components: {
        //組件a
        'my-com-a': MyComponentA,   //兩種書寫方式均可瓦堵,但是第二種跟更簡潔
        // 組件b
        MyComponentB
      }
    });
  </script>

組件通信

父組件向子組件傳值

  • 通過子組件的 props 選項接收父組件的傳值。

  • props不要與data存在同名屬性

 <!-- 通過 v-for 遍歷數(shù)據(jù) items歌亲,創(chuàng)建組件并生成內(nèi)容 -->
  <div id="app">
    <!-- 這里的key是綁定給v-for來幫助渲染的 -->
      <demo-item
        v-for="item in items"
        :key="item.title"
        :item-title="item.title"
        :item-content="item.content"
      ></demo-item>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    Vue.component('demoItem',{
      props: ["itemTitle", "itemContent"],
      template: `
          <div>
            <h3>{{ itemTitle }}</h3>
            <p>{{  itemContent }}</p>
          </div>
      `
    })
    new Vue({
      el: '#app',
      data: {
        // 給子組件準(zhǔn)備的數(shù)據(jù)
       items:[
         {
           title:'這是標(biāo)題1',
           content:'這是內(nèi)容1'
         },
         {
           title:'這是標(biāo)題2',
           content:'這是內(nèi)容2'
         },
         {
           title:'這是標(biāo)題3',
           content:'這是內(nèi)容3'
         }
       ]
      }
    })
  </script>
  • props命名規(guī)則:建議使用駝峰命名菇用,父組件綁定時用烤串命名
<my-component
      :item-title="item.title"
      :item-content="item.content"></my-component>
  </div>
  <script src="lib/vue.js"></script>
  <script>
      Vue.component('my-component',{
        props:['itemTitle','itemContent'],
  • 單向數(shù)據(jù)流
    父子組件間所有的prop都是單項下行綁定的,(只能向子組件傳应结,不能反向影響父組件)
    如果子組件要處理prop數(shù)據(jù)刨疼,應(yīng)當(dāng)存儲在data中后操作。
    如果prop為數(shù)組或?qū)ο蠖炝洌剑瑐鬟f進(jìn)來的是引用,子組件操作將影響到父組件的狀態(tài)扮休。
  <div id="app">
    
    <my-component
    :initial-title="title"
    ></my-component>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    Vue.component('my-component',{
      props:["initialTitle"],//接收父組件的data迎卤,傳給data()處理
      template: `
      <div>
          {{ title }}
          <button @click="fn">按鈕</button>
        </div>
      `,
      data () {
        return{
          title: this.initialTitle//處理完了給賦值表達(dá)式
        }
        
      },
      method: {
          fn () {
            // this.title = "這是新標(biāo)題";//父組件數(shù)據(jù)變化,引起子組件數(shù)據(jù)變化
            // this.initialTitle = "這是新標(biāo)題";//子組件數(shù)據(jù)變化玷坠,不引起父組件變化
            this.obj.name = 'jack';//根元素和原來數(shù)據(jù)都會發(fā)生變化
          }
      }
    })

    new Vue({
      el: '#app',
      data: {
       title:'這是示例內(nèi)容',
       obj : {
         name:'william',
         age:18
       }
      }
    });
  </script>
  • props類型
    · 如果需要prop類型檢查蜗搔,就需要進(jìn)行規(guī)則設(shè)置劲藐,如設(shè)置成一個對象解構(gòu),通過 鍵值對 對應(yīng)樟凄。
    · props中的某一個prop可以同時制定多種類型聘芜,可以寫成數(shù)組類型

  • props驗證
    · 當(dāng)prop需要設(shè)置多種規(guī)則時,可以將prop設(shè)置為選項對象
    · 之前類型檢測可以通過type選項設(shè)置
    · required 用于設(shè)置數(shù)據(jù)為必填項
    · default 用于給可選項設(shè)置默認(rèn)值缝龄,當(dāng)父組件未傳值時生效汰现。
    · default為數(shù)組或?qū)ο螅仨殲楣S函數(shù)返回的形式
    · validator 用于傳入prop設(shè)置校驗函數(shù)叔壤,return值為 false 時發(fā)出警告
    · 驗證函數(shù)中無法使用實例data瞎饲、methods功能,無法使用this

  <div id="app">
    <my-component
      :par-str="str"
      :par-num="num"
      :par-num2="2000"
      :par-arr="arr"
      par-content="lagou: hello world"
    ></my-component>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    Vue.component('MyComponent', {
      props: {
        parStr: {
          // 當(dāng)prop需要設(shè)置多種規(guī)則時炼绘,可以將prop設(shè)置為選項對象
            // 之前類型檢測可以通過type選項設(shè)置
          type: String
        },
        parData: {
          type: [Array, Object]
        },
        parNum: {
          type: Number,
          //required表示此處必須傳值嗅战,不傳報錯
          required: true
        },
        parNum2: {
          type: Number,
          // 默認(rèn)值為100,如果傳值了俺亮,就為傳的值
          default: 100
        },
        parArr: {
          type: Array,
          // 如果傳的值是數(shù)組或?qū)ο笸院矗仨殲楣S函數(shù)返回的形式
          default () {
            return [1, 2, 3];
          }
        },
        parContent: {
          type: String,
          // 用于傳入prop設(shè)置校驗函數(shù),return值為false時發(fā)出警告铅辞,value是傳入的值厌漂,是html元素中設(shè)置的對應(yīng)項的值
          //驗證函數(shù)中無法使用實例data、methods功能斟珊,無法使用this
          validator (value) {
            console.log(this);
            return value.startsWith('lagou');
          }
        }
      },
      template: `<div></div>`
    })

    new Vue({
      el: '#app',
      data: {
        str: '示例內(nèi)容',
        num: 100,
        arr: [10, 20, 30],
        obj: {
          content1: '內(nèi)容1',
          content2: '內(nèi)容2'
        }
      }
    });
  </script>
  • 當(dāng)父組件給子組件設(shè)置了屬性,但此屬性在props中不存在富纸,會自動綁定到子組件的根元素上

  • 如果根元素已經(jīng)存在了對應(yīng)屬性囤踩,則會被組件內(nèi)屬性替換,class和style例外晓褪,會進(jìn)行合并堵漱。
    如果不希望繼承父組件屬性,可以設(shè)置inheritAttrs:false,但是只適用于普通屬性涣仿,class與style不受影響

  <div id="app">
     <!-- 自定義屬性也可以綁定 -->
    <my-component
      :class="colorRed"
      style="background-color:red;"
      :title="'示例標(biāo)題內(nèi)容'"
     
      data-index = "3"
    ></my-component>
  </div>
  <script src="lib/vue.js"></script>
  <script>
  Vue.component('my-component', {
    // 如果不希望繼承父組件屬性勤庐,可以設(shè)置inheritAttrs:false
    inheritAttr:false,
    //class和style屬性會合并,其他屬性會被組件內(nèi)屬性代替
    template:`
      <div data-index="6" 
           title="舊的title" 
           class="abc"
           style="width: 200px;">
           <p>這是組件內(nèi)容</p></div>
    `
  })
  new Vue({
      el: '#app',
      data: {
        
      }
    });
  </script>

子組件向父組件傳值

  • 子組件數(shù)據(jù)變化時好港,通過$emit()觸發(fā)自定義事件愉镰,自定義事件名稱需要用 kebab-case
  • 父組件監(jiān)聽子組件事件,并設(shè)置處理程序
  <h3>購物車</h3>
  <!-- @count-increase接收一個值或者一個功能函數(shù) -->
  <div id="app">
    <product-item
    v-for="item in product"
    :key="product.id"
    :title="product.title"
    @count-increase="totalCount++"
    ></product-item>
    <div>購物車總數(shù):{{ totalCount }}</div>
  </div>
  
  <script src="lib/vue.js"></script>
  <script>
    Vue.component('product-item',{
      props:['title'],
      template:`
      <div>
        <span>商品名稱:{{title}}钧汹,商品個數(shù):{{count}}</span>
        <button @click="Increase">+1</button>

      </div>
      
      `,
      data() {
        return {
            count:0
        }
      },
      methods:{
        Increase() {
          //$emit向父級傳遞數(shù)據(jù)
          this.$emit('count-increase')
          this.count++;
          
        }
      }
    })

    new Vue({
      el: '#app',
      data: {
       product: [
       { id:1, title:'橘子一斤' },
       { id:2,title:"香蕉一斤"},
       {id:3,title:"蘋果一斤"}
       ],
       totalCount:0        
       }
    });
  </script>
  • 自定義事件傳值
    子組件觸發(fā)事件向父組件傳值丈探,父組件在監(jiān)聽事件時接收子組件傳遞的數(shù)據(jù)
  <div id="app">
    <h3>購物車</h3>
    <product-item
      v-for="product in products"
      :key="product.id"
      :title="product.title"
      @count-change="onCountChange"
    ></product-item>
    <p>商品總個數(shù)為:{{ totalCount }}</p>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    // 子組件
    Vue.component('ProductItem', {
      props: ['title'],
      template: `
        <div>
          <span>商品名稱: {{ title }}, 商品個數(shù): {{ count }}</span>
          <button @click="countIns1">+1</button>
          <button @click="countIns5">+5</button>
          
        </div>
      `,
      data () {
        return {
          count: 0
        }
      },
      methods: {
        countIns1 () {
          this.$emit('count-change', 1);
          this.count++;
        },
        countIns5 () {
          this.$emit('count-change', 5);
          this.count += 5;
        }
        
      }
    });
    // 父組件
    new Vue({
      el: '#app',
      data: {
        products: [
          {
            id: 1,
            title: '蘋果一斤'
          },
          {
            id: 2,
            title: '香蕉一根'
          },
          {
            id: 3,
            title: '橙子一個'
          }
        ],
        totalCount: 0
      },
      methods: {
        onCountChange(productZongshu) {//這是模板傳回來的參數(shù)
            // console.log(productZongshu);
            this.totalCount += productZongshu;
        }
      }
    });
  </script>
  • 組件與v-model
    v-model用于組件時,需要通過props與自定義事件實現(xiàn)
  <div id="app">
    <p>輸入的內(nèi)容是:{{ inputValue }}</p>
    <com-input v-model="inputValue"></com-input>    
  </div>
  <script src="lib/vue.js"></script>
  <script>
    var ComInput = {
      props:['value'],
      template:`
      <input 
        type="text" 
        :value="value" 
        @input='onInput'>`,
      methods: {
        onInput (event) {
          this.$emit('input', event.target.value)
        }
      }
    }
    // 根實例
    new Vue({
      el: '#app',
      data: {
        inputValue:''
      },
      components: {
        ComInput
      }     
    });
  </script>

非父子組件傳值

  • 兄弟組件傳值拔莱,通過父組件中轉(zhuǎn)
  <div id="app">
    <!-- 父組件接收子組件a的數(shù)據(jù) -->
    <com-a
      @value-change="value = $event"
    ></com-a>
    <!-- 父組件將數(shù)據(jù)傳遞給子組件b -->
    <com-b
      :value = "value"
      ></com-b>      
  </div>
  <script src="lib/vue.js"></script>
  <script>
    // 子組件a: 發(fā)送數(shù)據(jù)
    Vue.component('com-a',{
      template:`
      <div>
          組件a的內(nèi)容:{{ value }}
          <button @click="$emit('value-change',value)"></button>
        </div>
      `,
      // 通過數(shù)據(jù)聲明碗降,向外部傳遞數(shù)據(jù)
      data () {
        return {
          value:'這是組件a中的內(nèi)容'
        }
      }
    });
    // 子組件b:接收數(shù)據(jù)
    Vue.component('com-b',{
      props:['value'],
      template:`
        <div>
          組件b接收的數(shù)據(jù):{{ value }}
          </div>
      `
    });
    // 根實例(父組件)
    new Vue({
      el: '#app',
      data: {
      //  用于數(shù)據(jù)中專
      value:''
      }
    })
  </script>
  • EventBus

    EventBus(事件總線)是一個獨立的事件中心隘竭,用于管理不同組件之間的傳值。
    EventBus通過一個新的Vue實例來管理組件傳值操作讼渊,組件通過給實例注冊事件动看、調(diào)用事件實現(xiàn)數(shù)據(jù)傳遞。

操作步驟:
發(fā)送數(shù)據(jù)的組件觸發(fā)bus事件爪幻,接收的組件給bus注冊對應(yīng)事件

給bus注冊對應(yīng)事件通過$on()操作菱皆。

 // 商品組件
    Vue.component('product-item',{
      template:`
      <div>
        <span>商品名稱:蘋果,商品個數(shù):{{ count }}</span>
        <button
          @click="countIns"
        >+1</button>
      </div>`,
      data() {
        return {
          count:0
        }
      },
      methods: {
        countIns () {
          // 給bus觸發(fā)自定義事件笔咽,傳遞數(shù)據(jù)
          bus.$emit('countChange', 1)
          this.count++;
        }
      }
    })
    // 計數(shù)組件
    Vue.component('product-total',{
      template:`
        <p>商品總數(shù)是:{{ totalCount }}</p>
      `,
      data () {
        return {
          totalCount:0
        }
      },
      created () {
        // 給 bus 注冊事件搔预,并接受數(shù)據(jù),接受函數(shù)名叶组,并調(diào)用回調(diào)函數(shù)
        bus.$on('countChange', (productCount) => {
          this.totalCount += productCount;
        })
        // 實例創(chuàng)建完畢拯田,可以使用 data 等功能
      }
    })
  • 其他通信

    了解即可 $root $refs不建議在功能中使用,會操作其他組件內(nèi)部數(shù)據(jù),出現(xiàn)問題時甩十,不容易找出問題所在

    $root 用于訪問當(dāng)前樹根實例船庇,設(shè)置簡單的Vue應(yīng)用

<div id="app">
    <com-a></com-a>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    // 根實例的子組件A的子組件B
    var ComB = {
      template: `
        <div>
          組件B: {{ $root.count }}
          <button @click="clickFn">按鈕</button>
        </div>
      `,
      methods: {
        clickFn () {
          this.$root.count = 200;
        }
      }
    };
    // 子組件A
    var ComA = {
      template: `
        <div>
          組件A: {{ $root.count }}
          <button @click="clickFn">按鈕</button>
          <com-b></com-b>
        </div>
      `,
      methods: {
        clickFn () {
          this.$root.count = 100;
        }
      },
      components: {
        ComB
      }
    };
    // 根實例
    new Vue({
      el: '#app',
      data: {
        count: 0
      },
      components: {
        ComA
      }
    });
  </script>
  • $refs用于獲取設(shè)置了ref屬性的HTML標(biāo)簽或子組件。

基本操作方式:

  • 給普通HTML標(biāo)簽設(shè)置ref屬性侣监,$refs可以獲取DOM對象 訪問含有ref屬性的元素

  • 給組件設(shè)置 ref 屬性鸭轮,獲取的是DOM對象結(jié)構(gòu),渲染可以通過 $refs 獲取子組件實例

  <div id="app">
    <!-- 給 HTML 標(biāo)簽設(shè)置 ref 屬性 -->
    <input type="text" ref="inp">
    <button @click="fn">按鈕</button>

    <!-- 給子組件設(shè)置 ref 屬性 -->
    <com-a ref="comA"></com-a>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    var ComA = {
      template: `<div>組件A的內(nèi)容:{{ value }}</div>`,
      data () {
        return {
          value: '示例內(nèi)容'
        }
      }
    }

    var vm = new Vue({
      el: '#app',
      methods: {
        fn () {
          // 點擊后修改 HTML 標(biāo)簽焦點狀態(tài)
          this.$refs.inp.focus();

          this.$refs.comA.value = '新的內(nèi)容';
        }
      },
      components: {
        ComA
      },
      mounted () {
        console.log(this.$refs);
        this.$refs.comA.value = "修改后的內(nèi)容";
      },
    });
  </script>

組件插槽

單個插槽

用來像HTML一樣在標(biāo)簽之間書寫內(nèi)容

  • 通過<slot>進(jìn)行插槽設(shè)置橄霉。需要注意模板內(nèi)容渲染位置:
    父組件的數(shù)據(jù)都是在父組件中編譯執(zhí)行的窃爷,
    子組件的數(shù)據(jù)都是在子組件中編譯執(zhí)行的。
    插槽可以設(shè)置默認(rèn)值姓蜂,成為后備內(nèi)容
  <div id="app">
    <com-a>這是組件的內(nèi)容</com-a>
    <com-a>
      這是第二個組件的內(nèi)容:
      <span>這是span的內(nèi)容</span>
    </com-a>
    <com-a>
      這里是父組件的視圖模板按厘,只能使用父組件的數(shù)據(jù):
       {{ parValue }}
    </com-a>    
  </div>
  <script src="lib/vue.js"></script>
  <script>
    Vue.component('ComA', {
      //插槽中沒有內(nèi)容時,會采用<slot>中間的默認(rèn)內(nèi)容
      template: `
        <div>
          <h3>組件標(biāo)題</h3>
          <slot>
            這是插槽的默認(rèn)內(nèi)容
            </slot>
        </div>
      `,
      data() {
        return  {
          value: '子組件的數(shù)據(jù)'
        }
      }
    });

    new Vue({
      el: '#app',
      data: {
        parValue: '這是父組件的數(shù)據(jù)'
      }
    })
  </script>

具名插槽

  • 組建中有多個位置需要設(shè)置插槽钱慢,根據(jù)需要逮京,給<slot>設(shè)置name,成為具名插槽束莫。
    插入一張slot圖片
  <div id="app">
      <com-a>
        <!-- 這里記得是對象書寫形式懒棉,不是屬性書寫方式 -->
        <template v-slot:header>
          <h3>組件頭部內(nèi)容</h3>
        </template>
        <!-- <template #default>
          <p>組件主體內(nèi)容1</p>
          <p>組件主體內(nèi)容2</p>
        </template> -->
        <p>組件主體內(nèi)容1</p>
          <p>組件主體內(nèi)容2</p>
        
<!-- #footer是v-slot:footer的簡寫方式 -->
        <template #footer>
          <p>組件底部內(nèi)容</p>
        </template>
      </com-a>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    // 子組件 
    Vue.component('ComA',{
      template:`
      <div>
      <header>
      // 這里正常書寫name='header'
        <slot name='header'></slot>
      </header>
      <main>
        <slot></slot>
      </main>
      <footer >
        <slot name="footer"></slot>
      </footer>
    </div>
      `
    });
    new Vue({
      el: '#app',
      data: {
      }
    });
  </script>

作用域插槽

  • 用于讓插槽可以使用子組件的數(shù)據(jù),
    組件需要使用的數(shù)據(jù)通過v-bind綁定給<slot>,
    這種用于給插槽傳遞數(shù)據(jù)的屬性成為插槽prop

  • 組件綁定數(shù)據(jù)后览绿,通過v-slot接受數(shù)據(jù)

  • 可以通過es6的解構(gòu)操作進(jìn)行數(shù)據(jù)接收 <com-a v-slot:default="{ value }">

 <div id="app">
    <!-- 多個插槽作用域插槽的書寫方式 -->
    <com-a>
      <template v-slot:default="dataObj">
        {{ dataObj.value }}
        {{ dataObj.num }}
      </template>
      <template v-slot:footer="dataObj">
        {{ dataObj.value }}
      </template>
    </com-a>
    <!-- 只具有默認(rèn)插槽的作用域插槽的書寫方式 -->
    <!-- <com-b v-slot="dataObj"> -->
    <com-b v-slot="dataObj">      
      {{ value }}
    </com-b>
    <!-- 通過es6 的解構(gòu)操作接收作用域插槽的數(shù)據(jù) -->
    <com-b #default="{value,num}">      
      {{value}}
      {{num}}
    </com-b>
  </div> 
  <script src="lib/vue.js"></script>
  <script>
      // 子組件b
      var ComB = {
            template:`
            <div>
              <p>組件b的內(nèi)容:</p>
              <slot 
                :value="value"
                :num="num"
              ></slot>
              <slot name = "footer"
                :value="value"></slot>
            </div>
            `,
            data() {
              return {//返回的就是 dataObj 數(shù)據(jù)對象
                value :'這是組件a內(nèi)的數(shù)據(jù)',
                num:200
              }
            }
          }        
    // 子組件a
    var ComA = {
      template:`
      <div>
        <p>組件a的內(nèi)容:</p>
        <slot 
          v-bind:value="value"
          :num="num"
        ></slot>
        <slot name = "footer"
          :value="value"></slot>
      </div>
      `,
      data() {
        return {//返回的就是 dataObj 數(shù)據(jù)對象
          value :'這是組件a內(nèi)的數(shù)據(jù)',
          num:100
        }
      }
    }
    new Vue({
      el: '#app',
      components: {
        ComA,ComB
      }
    });
  </script>

內(nèi)置組件

動態(tài)組件

組件切換處理操作

  • <component> 用于將一個‘元組件’渲染為動態(tài)組件策严,以 is 屬性決定渲染哪個組件

  • 用于實現(xiàn)多個組件的快速切換,例如選項卡效果

  • is 屬性會在每次切換組件時挟裂,創(chuàng)建一個新的組件實例

  <div id="app">
    <!-- 按鈕代表選項卡的標(biāo)題功能 -->
    <button
      v-for="title in titles"
      :key="title"
      @click="currentCom = title"
    >{{ title }}</button>
    <!-- component 設(shè)置動態(tài)組件 -->
    <component :is="currentCom"></component>
  </div>
  <script src="lib/vue.js"></script>
  <script>
    // 這是要切換的子組件的選項對象
    var comA = {
      template:`<p>這是組件a的內(nèi)容:<input type="text"></p>`
    };
    var comB = {
      template:`<p>這是組件b的內(nèi)容:<input type="text"></p>`
    };
    var comC = {
      template:`<p>這是組件c的內(nèi)容:<input type="text"></p>`
    };
    new Vue({
      el: '#app',
      data:{
        // 所有組件名稱
        titles: ["comA","comB","comC"],
        // 當(dāng)前組件名稱
        currentCom:'comA'
      },
      components: {
        // 注冊組件
        comA,comB,comC
      }
    });
  </script>

keep-alive組件

組件動態(tài)切換的緩存處理

  • 主要用于保留組件狀態(tài)或避免組件重新渲染
    利用 <keep-alive max="2">

    <component :is="currentCom"></component>
    </keep-alive>
    包裹享钞,保證組件切換中進(jìn)行緩存,不會被移除

keep-alive需要記住的屬性:

  • include屬性用于指定哪些組件會被緩存,具有多種設(shè)置方式
    <!-- <keep-alive include="ComA,ComB,ComC"> -->
    <!-- <keep-alive :include="['ComA', 'ComB', 'ComC']"> -->
    <!-- <keep-alive :include="/Com[ABC]/"> -->
  • exclude 指定哪些組件不會被緩存
    <!-- <keep-alive exclude="ComD"> -->
    <!-- <keep-alive :exclude="['ComD']"> -->
    <!-- <keep-alive :exclude="/ComD/"> -->
  • max 屬性用于設(shè)置最大緩存?zhèn)€數(shù):
    距離最近的max個被緩存
  <div id="app">
    <button 
      v-for="title in titles"
      :key="title"
      @click="currentCom = title"
    >
      {{title}}
    </button>    
    <keep-alive max="2">
      <!-- 動態(tài)組件 -->
      <component :is="currentCom"></component>
    </keep-alive>
  </div>

過渡組件

控制切換效果和動畫效果

transition組件

  • 用于給元素進(jìn)入或離開過渡

    · 條件渲染 v-if

    · 條件展示 v-show

    · 動態(tài)組件<component>

    · 組件根節(jié)點

提供了6個class栗竖,用于設(shè)置過渡的具體效果
進(jìn)入類名: v-enter(入場前的樣式)
v-enter-to(入場完畢之后樣式)一般不做設(shè)置
v-enter-active(入場過渡)
離開類名:v-leave(離場前)一般不做設(shè)置
v-leave-to(離場后)
v-leave-active(離場過渡)
屬性

  • 給組件設(shè)置name屬性暑脆,用于給多個元素、組件設(shè)置不同的過渡效果狐肢,這時需要將 v- 改為對應(yīng)的 name- 形式

  • 通過 appear 屬性添吗,可以讓組件在初始渲染時實現(xiàn)過渡

  <style>
    /* 第一組過渡效果設(shè)置 */
    .v-enter, .v-leave-to {
      opacity: 0;
    }
    .v-enter-active, .v-leave-active {
      transition: opacity .5s;
    }
    /* 第二組過渡效果設(shè)置 */
    .demo-enter, .demo-leave-to {
      opacity: 0;
      transform: translateX(200px);
    }
    .demo-enter-active, .demo-leave-active {
      transition: all .5s;
    }
  </style>
</head>
<body>
  <div id="app">
    <button @click="show = !show">切換1</button>
    <!-- 沒有設(shè)置name命名的 transition 組件,style中類名以 v-開頭 -->
    <transition appear>
      <p v-if="show">這是要切換的元素1</p>
    </transition>
    <button @click="showDemo = !showDemo">切換2</button>
    <!-- 設(shè)置了name 的transition 組件份名,類名需要將 v- 修改為 demo- -->
    <!-- 通過 appear 屬性碟联,可以讓組件在初始渲染時實現(xiàn)過渡 -->
    <transition 
      name="demo"
      appear>
      <p v-if="showDemo">這是要切換的元素2</p>
    </transition>
  </div>  
  <script src="./lib/vue.js"></script>
  <script>
    new Vue({
      el: '#app',
      data: {
        show: true,
        showDemo: true
      }
    });

自定義過渡類名

自定義類名比普通類名優(yōu)先級高,才能替代第三方動畫庫

  • 用于自定義過渡類名的屬性
    · enter-class 入場初始狀態(tài)

    · enter-active-class 入場過程

    · enter-to-class 入場最終效果

    · leave-class 入場初始狀態(tài)

    · leave-active-class 入場過程

    · leave-to-class 入場最終效果

  • 用于初始過渡類名的屬性:
    · appear-class

    · appear-to-class

    · appear-active-class

    .test {
      transition: all 3s;
    }
  </style>
</head>
<body>
  <div id="app">
    <button @click="show = !show">切換</button>
    <!-- 自定義類名的優(yōu)先級更高 -->
    <transition
     enter-active-class="test"
     leave-active-class="test"
    >
      <p v-if="show">這是 p 標(biāo)簽</p>
    </transition>
  </div>  
  • Animate.css 是一個第三方動畫庫僵腺,通過設(shè)置類名給元素添加效果
    注意點
    · animate__ 前綴與compat版本

    · 基礎(chǔ)類名 animate__animated 設(shè)置

  <link
    rel="stylesheet"    
  />

  <!-- 不需要添加 animate__ 的兼容版本鲤孵,但是官方建議使用完整版本 -->
  <!-- "https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.0.0/animate.compat.css" -->
</head>
<body>
  <div id="app">
    <button @click="show = !show">按鈕</button>

    <!-- 通過自定義過渡類名設(shè)置,給組件添加第三方動畫庫的類名效果 -->
    <transition
      enter-active-class="animate__bounceInDown"
      leave-active-class="animate__bounceOutDown"
    >
      <!-- 必須給要使用動畫的元素設(shè)置基礎(chǔ)類名 animate__animated -->
      <p 
        v-if="show"
        class="animate__animated"  
      >hello world</p>
    </transition>
  </div>

transition-group組件

  • <transition-group> 用于給列表統(tǒng)一設(shè)置過渡動畫

    · tag 屬性用于設(shè)置容器元素辰如,默認(rèn)為<span>

    · 過渡應(yīng)用于內(nèi)部元素普监,不是容器

    · 子節(jié)點必須有獨立的key,動畫才能正常工作

    · 當(dāng)列表元素變更導(dǎo)致元素位移琉兜,可以通過 .v-move 類名設(shè)置移動效果

  <style>
    ul {
      position: relative;
    }
    .v-enter, .v-leave-to {
      opacity: 0;
      transform: translateX(100px);
    }
    .v-enter-active, .v-leave-active {
      transition: all .5s;
    }
    /* 讓元素在離場的過程中脫離標(biāo)準(zhǔn)流 */
    .v-leave-active {
      position: absolute;
    }
    .v-move {
      transition: all .5s;
    }
  </style>
</head>
<body>
  <div id="app">
    <input type="text"
      v-model="newTitle"
      @keyup.enter="addItem"
    >

    <transition-group
      tag="ul"
    >
      <li
        v-for="item in items"
        :key="item.id"
        @click="removeItem(item)"
      >
        {{ item.title }}
      </li>
    </transition-group>
  </div>  
  <script src="./lib/vue.js"></script>
  <script>
    new Vue({
      el: '#app',
      data: {
        items: [
          { id: 1, title: '示例內(nèi)容1'},
          { id: 2, title: '示例內(nèi)容2'},
          { id: 3, title: '示例內(nèi)容3'},
          { id: 4, title: '示例內(nèi)容4'},
          { id: 5, title: '示例內(nèi)容5'},
        ],
        newTitle: '',
        latestId: 5
      },
      methods: {
        addItem () {
          this.items.push({
            id: this.latestId + 1,
            title: this.newTitle
          });
          this.latestId++;
          this.newTitle = '';
        },
        removeItem (item) {
          var i = this.items.indexOf(item);
          this.items.splice(i, 1);
        }
      }
    });
  </script>

Vue Router

Vue Router是Vue.js的官方插件凯正,用來快速實現(xiàn)單頁應(yīng)用

單頁應(yīng)用

SPA(Single Page Application)單頁面應(yīng)用程序,簡稱單頁應(yīng)用豌蟋。指的是網(wǎng)站的 “所有” 功能都在單個頁面
中進(jìn)行呈現(xiàn)廊散。

  • 后臺管理系統(tǒng)、移動端梧疲、小程序等適合單頁面應(yīng)用允睹。

優(yōu)點:
· 前后端分離開發(fā),提高開發(fā)效率
· 業(yè)務(wù)場景切換時幌氮,局部更新結(jié)構(gòu)
· 用戶體驗好擂找,接近本地應(yīng)用
缺點:
· 不利于SEO
· 初次加載速度慢
· 頁面復(fù)雜度高

前端路由

  • URL 與內(nèi)容之間的映射關(guān)系

    前端路由的必備條件: URL、內(nèi)容浩销、映射關(guān)系

實現(xiàn)方式

Hash方式實現(xiàn)前端路由

通過hashchange 事件監(jiān)聽hash變化,進(jìn)行網(wǎng)頁內(nèi)容更新

通過 onhashchange 事件監(jiān)聽 hash 變化听哭,進(jìn)行網(wǎng)頁內(nèi)容更新

  • 封裝hash函數(shù)以備復(fù)用

總結(jié):
· hash兼容性好

· 地址中具有 # 慢洋,不太美觀

· 前進(jìn)后退功能較繁瑣
    <div>
        <a href="#/">首頁</a>
        <a href="#/category">分類頁</a>
        <a href="#/user">用戶頁</a>
    </div>
    <div id="container">
        這是首頁功能
    </div>

    <script>
        // 準(zhǔn)備對象,用于封裝 hash 功能
        var router = {
            // 路由存儲位置:保存了 url 與 內(nèi)容處理函數(shù)的對應(yīng)關(guān)系
            routes: {},
            // 定義路由規(guī)則的方法
            route: function (path, callback) {//path相當(dāng)于鍵陆盘,callback相當(dāng)于值
                this.routes[path] = callback;
            },
            // 初始化路由的方法
            init: function () {
                window.onhashchange = function () {
                    // 將外部的router傳進(jìn)來
                    var that = this;
                    // 當(dāng) hash 改變普筹,需要得到當(dāng)前新的 hash
                    var hash = location.hash.replace('#','');
                    // 根據(jù)hash 觸發(fā) routes 對象中的對應(yīng) callback
                    // 利用邏輯與運算,前面成立,則執(zhí)行 && 后面的內(nèi)容隘马,如果前面路由是真太防,則執(zhí)行回調(diào)函數(shù)
                    that.routes[hash] && that.routes[hash]();//&& 后面是對象實例化
                }
            }
        };
        var container = document.getElementById('container');
        // 定義路由規(guī)則
        router.route("/", function () {
            container.innerHTML = '這是首頁功能';
        });
        router.route("/category", function () {
            container.innerHTML = '這是分類功能';
        });
        router.route("/user", function () {
            container.innerHTML = '這是用戶功能';
        });
        // 初始化路由
        router.init();
    </script>

History方式實現(xiàn)前端路由

  • History 方式采用 html5 提供的新功能實現(xiàn)前端路由

  • 在操作時通過 history.pushState() 變更url執(zhí)行對應(yīng)操作。

  • 實現(xiàn)前進(jìn)后退功能酸员,首先需要再更改url時保存路由標(biāo)記蜒车;通過popstate事件監(jiān)聽前進(jìn)后退按鈕操作酿愧,并檢測 state庞钢;調(diào)用初始化方法監(jiān)聽操作基括。

<body>
    <div>
        <a href="/">首頁</a>
        <a href="/category">分類頁</a>
        <a href="/user">用戶頁</a>
    </div>
    <div id="container">
        這是首頁功能
    </div>

    <script>
        var router = {
            // 存儲路由的對象
            routes: {},
            // 定義路由的方法
            route (path, callback) {
                this.routes[path] = callback;
            },
            // go 用于 觸發(fā) 指定的路由操作
            go (path) {
                // 更改url饭冬,前進(jìn)后退功能炊苫,需要pushstate方法將更改url時的標(biāo)記存儲在第一個參數(shù)中,方便后面popstate調(diào)用
                history.pushState({path : path}, null, path);//第一個參數(shù)是與數(shù)據(jù)有關(guān)的唠梨,第二個參數(shù)瀏覽器目前不支持
                // 觸發(fā)路由對應(yīng)的回調(diào)函數(shù)
                this.routes[path] && this.routes[path]();
                // console.log(this.routes[path]());
            },
            init() {
                var that = this;
                window.addEventListener('popstate', function(e) {//監(jiān)聽前進(jìn)后退操作醉箕,并檢測state
                    var path = e.state ? e.state.path : '/';
                    // 觸發(fā)路由對應(yīng)的回調(diào)函數(shù)
                    that.routes[path] && that.routes[path]();
                });
            }
        };
        // 初始化操作
        router.init();
        // 設(shè)置 a 標(biāo)簽 功能 
        var links = document.querySelectorAll('a');
        var container = document.querySelector('#container');

        links.forEach(function (ele) {
            ele.addEventListener ('click', function (event) {
                router.go(this.getAttribute('href'));
                event.preventDefault();//防止跳轉(zhuǎn)
            });
        });
        // 定義路由規(guī)則
        router.route("/", function () {
            container.innerHTML = '這是首頁功能';
        });
        router.route("/category", function () {
            container.innerHTML = '這是分類功能';
        });
        router.route("/user", function () {
            container.innerHTML = '這是用戶功能';
        });
    </script>

總結(jié):
history可以實現(xiàn)前進(jìn)后退
url沒有#剧辐,更加美觀
hash傳遞數(shù)據(jù)最大2k,history的pushstate可以存儲640k鳄梅;
history只兼容HTML5

VueRouter

Vue.js官方路由管理器悲雳,讓構(gòu)建單頁面應(yīng)用更簡單

基本使用

安裝

基本使用

  • Vue Router 提供了 <router-link>和 <router-view> 組件來進(jìn)行路由設(shè)置
    <router-link> 鏈接跳轉(zhuǎn)挎峦,默認(rèn)就是a標(biāo)簽,如果希望改變合瓢,可以用tag屬性進(jìn)行改變
    <router-view> 進(jìn)行視圖區(qū)域變換坦胶,用來顯示路由匹配到的組件

<router-link>使用
- 定義路由需要的組件,進(jìn)行規(guī)則設(shè)置晴楔,
- 創(chuàng)建vue Router實例迁央,通過 Routes屬性配置路由
- 創(chuàng)建vue 實例,通過 router 屬性注入路由滥崩。

    <div id="app">
        <!-- 設(shè)置用于進(jìn)行路由操作的組件 -->
        <router-link to="/">首頁</router-link>
        <router-link to="/user">用戶</router-link>
        <router-link to="/category">分類</router-link>
        <!-- 用于切換顯示組件 -->
        <router-view></router-view>
    </div>
    <script src="lib/vue.js"></script>
    <script src="lib/vue-router.js"></script>
    <script>
        console.log(VueRouter);

        // 2.定義組件信息
        var Index = {
            template:`<div>這是首頁信息</div>`
        };
        var User = {
            template:`<div>這是用戶信息</div>`
        };
        var Category = {
            template:`<div>這是分類信息</div>`
        };
        // 1.定義路由規(guī)則
        var routes1 = [
            { path: '/', component: Index},
            { path: '/user', component: User},
            { path: '/category', component: Category},
        ];
        // 3. 創(chuàng)建 Vue Router實例
        var router = new VueRouter({
            // 配置對象屬性routes,將配置好的路由規(guī)則加入進(jìn)來
            routes:[
                    { path: '/', component: Index},
                    { path: '/user', component: User},
                    { path: '/category', component: Category},
                   ]
        });
        // 4.創(chuàng)建vue 實例,注入router
        new Vue({
            el:"#app",
            router
        });
    </script>

<router-view>基本使用
- 導(dǎo)航(跳轉(zhuǎn))后讹语,希望統(tǒng)計展示多個視圖(組件)钙皮,這是就需要進(jìn)行命名視圖。
- 路由中通過 components 屬性進(jìn)行設(shè)置不同視圖的對應(yīng)組件。

    // 側(cè)邊欄結(jié)構(gòu)
    var SideBar1 = {
      template:`<div>側(cè)邊欄1功能</div>`
    };
    var SideBar2 = {
      template:`<div>側(cè)邊欄2功能</div>`
    };

    var Index = {
      template:`<div>首頁功能</div>`
    };
    var User = {
      template:`<div>用戶功能</div>`
    };

    // 定義路由規(guī)則
    var rules = [
      {
        path:'/',
        components: {
          // router-view 的name: 組件配置對象
          default: Index,
          sidebar: SideBar1
        }
      },
      {
        path:'/user',
        components: {
          // router-view 的name: 組件配置對象
          default: User,
          sidebar: SideBar2
        }
      }
    ];

    // 創(chuàng)建 Vue Router 實例
    var router = new VueRouter({
      routes: rules
    });

    // 創(chuàng)建 Vue 實例
    new Vue({
      el: '#app',
      router
    });
  </script>

動態(tài)路由處理

多個url對應(yīng)一個組件的方式

  • 應(yīng)用場景:
    需要將一類URL都映射到一個組件短条,就需要使用動態(tài)路由

  • 使用方法
    · 定義動態(tài)路由規(guī)則時导匣,將路徑中的某個部分使用:冒號進(jìn)行標(biāo)記,即可設(shè)置為動態(tài)路由
    · 設(shè)置動態(tài)路由后茸时,動態(tài)部分為任意內(nèi)容均跳轉(zhuǎn)到同一組件
    · 冒號:部分對應(yīng)的信息成為路徑參數(shù)贡定,存儲在 vm.$route.params 中

  • 偵聽路由參數(shù)
    · 如果要相應(yīng)路由參數(shù)變化,可以通過watch監(jiān)聽 $route

  <div id="app">
    <router-link to="/user/1">用戶1</router-link>
    <router-link to="/user/2">用戶2</router-link>
    <router-link to="/user/3">用戶3</router-link>

    <router-view></router-view>

  </div>
  <script src="lib/vue.js"></script>
  <script src="lib/vue-router.js"></script>
  <script>
    // 設(shè)置組件 
    var User = {
      template: `
        <div>
          這是用戶 {{ $route.params.id }} 的功能
          <input type="text">
        </div>`,
      // 由于組件沒有重新創(chuàng)建可都,所以生命周期鉤子只能執(zhí)行一次
      /* created () {
        console.log('創(chuàng)建了組件的實例');//只輸出了一次
      } */
      // 監(jiān)聽路由參數(shù)
      watch: {
        $route (route) {
          console.log($route.params.id);
        }
        
      }
    };

    // 設(shè)置路由規(guī)則
    var routes = [
      {
        path: '/user/:id', component: User
      }
    ];

    var router = new VueRouter({ routes });
    var vm = new Vue({
      el: '#app',
      router
    });
  </script>
  • 路由傳參處理
    · 通過路由的props設(shè)置數(shù)據(jù)缓待,并通過組件 porps 接收
 <div id="app">
    <router-link to="/user/1">用戶1</router-link>
    <router-link to="/user/2">用戶2</router-link>
    <router-link to="/user/3">用戶3</router-link>

    <router-link to="/category/1">分類1</router-link>
    <router-link to="/category/2">分類2</router-link>
    <router-link to="/category/3">分類3</router-link>

    <router-view></router-view>
    <router-view name="sidebar"></router-view>
    <router-view name="sidebar2"></router-view>
  </div>
  <script src="lib/vue.js"></script>
  <script src="lib/vue-router.js"></script>
  <script>
    // 組件的配置對象
    var User = {
      template: `<div>這是用戶 {{ $route.params.id }} 功能</div>`
    };

    var Category = {
      props: ['id'],
      template: `<div>這是分類 {{ id }} 功能</div>`
    };

    var SideBar = {
      template: `<div>側(cè)邊欄功能</div>`
    };

    var SideBar2 = {
      props: ['a', 'b'],
      template: `
      <div>
        側(cè)邊欄2功能: {{ a }} {{ b }}
      </div>`
    };

    // 設(shè)置路由規(guī)則
    var routes = [
      {
        path: '/user/:id',
        component: User
      },
      {
        path: '/category/:id',
        components: {
          default: Category,
          sidebar: SideBar,
          sidebar2: SideBar2
        },
        props: {
          default: true,
          sidebar: false,
          sidebar2: {
            a: '狀態(tài)1',
            b: '狀態(tài)2'
          }
        }
      }
    ];

    var router = new VueRouter({ routes });
    var vm = new Vue({
      el: '#app',
      router
    });
  </script>
  • 路由傳參其他方式
    · 包含多個命名視圖時,需要將路由的 props 設(shè)置為對象
    · 如果希望設(shè)置靜態(tài)數(shù)據(jù)渠牲,可以將 props 中的額某個組件對應(yīng)的選項設(shè)置為對象旋炒,內(nèi)部屬性會綁定給 props
  <div id="app">
    <router-link to="/user/1">用戶1</router-link>
    <router-link to="/user/2">用戶2</router-link>
    <router-link to="/user/3">用戶3</router-link>

    <router-link to="/category/1">分類1</router-link>
    <router-link to="/category/2">分類2</router-link>
    <router-link to="/category/3">分類3</router-link>

    <router-view></router-view>
    <router-view name="sidebar"></router-view>
    <router-view name="sidebar2"></router-view>
  </div>
  <script src="lib/vue.js"></script>
  <script src="lib/vue-router.js"></script>
  <script>
    // 組件的配置對象
    var User = {
      template: `<div>這是用戶 {{ $route.params.id }} 功能</div>`
    };

    var Category = {
      props: ['id'],
      template: `<div>這是分類 {{ id }} 功能</div>`
    };

    var SideBar = {
      template: `<div>側(cè)邊欄功能</div>`
    };

    var SideBar2 = {
      props: ['a', 'b'],
      template: `
      <div>
        側(cè)邊欄2功能: {{ a }} {{ b }}
      </div>`
    };

    // 設(shè)置路由規(guī)則
    var routes = [
      {
        path: '/user/:id',
        component: User
      },
      {
        path: '/category/:id',
        components: {
          default: Category,
          sidebar: SideBar,
          sidebar2: SideBar2
        },
        // 多個視圖時,需要將props改為對象签杈,并設(shè)置加載方式
        props: {
          default: true,
          sidebar: false,
          sidebar2: {
            a: '狀態(tài)1',
            b: '狀態(tài)2'
          }
        }
      }
    ];

    var router = new VueRouter({ routes });
    var vm = new Vue({
      el: '#app',
      router
    });
  </script>

嵌套路由

路由通常由多層嵌套的組件組合而成瘫镇,這是需要使用嵌套路由配置。
· 使用 children 來進(jìn)行嵌套路由中的子路由設(shè)置答姥。
  <div id="app">
    <router-link to="/user">用戶功能</router-link>
    <router-view></router-view>

  </div>
    <script src="lib/vue.js"></script>
    <script src="lib/vue-router.js"></script>
    <script>
      var User = {
        template:`
        <div>
          <h3>這是 User 組件的功能</h3>
          <router-link to="/user/hobby">愛好功能</router-link>
          <router-link to="/user/info">用戶信息</router-link>
          <router-view></router-view>
        </div>
        `
      };

      // 愛好
      var UserHobby = {
        template: `<div> UserHobby 組件</div>`
      };
      // info
      var UserInfo = {
        template: `
        <div> 
          UserInfo 組件
          <router-link to="/user/info/school">學(xué)校信息</router-link>
          <router-view></router-view>
          </div>`
      };
      var UserInfoSchool = {
        template:`<div> UserInfoSchool 組件</div>`
      };

      // 路由規(guī)則設(shè)置
      var routes = [
        {
          path: '/user',
          component: User,
          children: [
            {
              path: 'hobby',
              component: UserHobby
            },
            {
              path: 'info',
              component: UserInfo,
              children: [
              {
                path: 'school',
                component: UserInfoSchool
              }
              ]
            }
          ]
        }
      ];

      var router = new VueRouter({ routes });
      var vm = new Vue({
        el:'#app',
        router
      });
    </script>

編程式導(dǎo)航

指的是通過方法設(shè)置導(dǎo)航铣除。

  • router.push() 用來導(dǎo)航一個新的URL

  • <router-link> 的 to 屬性 使用綁定方式時也可以是 屬性對象結(jié)構(gòu)

  <div id="app">
    <!-- 聲明式導(dǎo)航 -->
    <!-- <router-link to="/user/200">用戶200</router-link> -->

    <!-- 編程式導(dǎo)航 -->
    <router-link :to="{ path: '/user/700' }">用戶700</router-link>

    <router-view></router-view>
  </div>
  <script src="./lib/vue.js"></script>
  <script src="./lib/vue-router.js"></script>
  <script>
    var User = {
      template: `<div> 這是用戶 {{ $route.params.id }} </div>`
    };
    // 設(shè)置路由規(guī)則
    var routes = [
      {
        path: '/user/:id',
        component: User
      }
    ];
    var router = new VueRouter({ routes });
    var vm = new Vue({
      el: '#app',
      router
    }); 
  </script>

命名路由

  • 設(shè)置路由時添加 name 屬性,根據(jù)name處理路由

  • 在 push() 中設(shè)置 name 導(dǎo)航到對應(yīng)路由鹦付,參數(shù)通過 params 設(shè)置

<div id="app">
   <!-- <router-link :to="{ name: 'school', params: { id: 10 } }">學(xué)校10</router-link> -->
   <!-- 通過name屬性尋找對應(yīng)的組件 -->
   <router-link :to="{ name: 'school', params: { id :10 }}">學(xué)校10</router-link>
   <router-view></router-view>
 </div>
 <script src="lib/vue.js"></script>
 <script src="lib/vue-router.js"></script>
 <script>
     var School = {
       template: `
       <div>school 組件的功能: {{ $route.params }}</div>`
     };

     var routes = [
       {
         path:'/user/:id/info/school',
         name: 'school',
         component: School
       }
     ];
   var router = new VueRouter({ routes });
   var vm = new Vue({
     el: '#app',
     router
   });
 </script>

重定向

訪問不合理的URL時尚粘,被重新指定到了一個位置

  <div id="app">
    <router-link to="/">首頁</router-link>
    <router-link to="/category/2">分類2</router-link>
    <router-link to="/category"> /category 錯誤演示 </router-link>

    <router-view></router-view>
  </div>
  <script src="./lib/vue.js"></script>
  <script src="./lib/vue-router.js"></script>
  <script>
    var Index = {
      template: `<div>首頁功能</div>`
    };

    var Category = {
      template: `<div>分類 {{ $route.params.id }} 功能</div>`
    };

    var router = new VueRouter({
      routes: [
        {
          path: '/',
          component: Index
        },
        {
          path: '/category/:id',
          component: Category
        },
        // 如果id沒有書寫的話,無法訪問到對應(yīng)的category睁壁,那我們就需要重新定向
        {
          path: '/category',
          redirect: '/'
        }
      ]
    });

    var vm = new Vue({
      el: '#app',
      router
    });
  </script>

別名功能

  <div id="app">
    <!-- 命名式路由 -->
    <router-link :to="{ name: 'school', params: { id: 10, date: '0612'} }">學(xué)校信息</router-link>
    <!-- 導(dǎo)航別名 -->
    <router-link to="/20/1234">學(xué)校信息2</router-link>
    <router-view></router-view>
  </div>
  <script src="lib/vue.js"></script>
  <script src="lib/vue-router.js"></script>
  <script>
    // 組件
    var School = {
      template: `
        <div>School 組件</div>
      `
    };
    // 路由規(guī)則
    var router = new VueRouter({
      routes: [
        {
          path: '/user/:id/info/school/:date',
          name: 'school',
          component: School,
          // 設(shè)置別名背苦,此處綁定id和日期,為了傳參使用
          alias: '/:id/:date'
        }
      ]
    });
    var vm = new Vue({
      el: '#app',
      router
    });
  </script>

導(dǎo)航守衛(wèi)

  • 某些特定網(wǎng)址可能需要登錄潘明,所以需要使用導(dǎo)航守衛(wèi)進(jìn)行跳轉(zhuǎn)
  • to到哪里去行剂,from來自哪里,需要守衛(wèi)時調(diào)用next钳降,調(diào)用且調(diào)用一次
  • next可以傳入false組織本次導(dǎo)航厚宰,無法往后執(zhí)行
  • 傳入?yún)?shù)跳轉(zhuǎn)到登錄頁面,傳入?yún)?shù)和router-link中的參數(shù)傳入的是相同的
    router.beforeEach(function (to, from, next){
    函數(shù)體
    next();
    });
  <script>
    var Index = {
      template: `<div>這是首頁功能</div>`
    };
    var User = {
      template: `<div>這是用戶功能</div>`
    };
    var Category = {
      template: `<div>這是分類功能</div>`
    };
    // 建立導(dǎo)航對象 router
    var router = new VueRouter({
      routes: [
        { path: '/', component: Index },
        { path: '/user', component: User },
        { path: '/category', component: Category },
      ]
    });
    // 通過上面建立的導(dǎo)航對象router遂填,設(shè)置導(dǎo)航守衛(wèi)
    router.beforeEach(function (to ,from, next) {
      console.log(to,from);
      //阻止了導(dǎo)航繼續(xù)操作
      // next(false);
      
      // 按條件跳轉(zhuǎn)
      if(to.path === '/user') {
        next('/category');
      }else {
        next();
      }
    });
    var vm = new Vue({
      el: '#app',
      router
    })
  </script>

history 模式

vue router默認(rèn)使用的hash模式設(shè)置

也可以提供history模式铲觉,需要Vue Router實例的mode 選項設(shè)置,這樣可以是 URL更加美觀吓坚,需要后端支持避免出現(xiàn)問題

    var router = new VueRouter({
      mode: 'history',
      routes: [
        { path: '/', component: Index },
        { path: '/user', component: User },
        { path: '/category', component: Category },
      ]
    });

Vue CLI

基于 Vue.js 進(jìn)行快速開發(fā)的完整系統(tǒng)撵幽,稱為為腳手架工具,

  • 統(tǒng)一架構(gòu)風(fēng)格礁击,

  • 初始化配置項目依賴盐杂。

  • 提供單文件組件功能逗载。

Vue CLI安裝

? 安裝
? npm install –g @vue/cli
? 升級
? npm update –g @vue/cli

項目搭建

? 創(chuàng)建項目:
vue create project-demo
? 選擇 Preset:

? 選擇包管理器:

  • 運行項目:
    ? npm run serve

目錄與文件

? 文件目錄介紹:
└─ 根目錄
├─ public 預(yù)覽文件目錄
└─ src
├─ assets 靜態(tài)資源目錄
└─ components 項目組件目錄
└─ App.vue 根組件
└─ main.js 入口文件

  • 單文件組件
    可以將組件的功能統(tǒng)一保存在以.vue為擴(kuò)展名的文件中。

打包與部署

打包

? 打包就是將 Vue CLI 項目編譯為瀏覽器可識別的文件链烈。
? 命令:
npm run build

部署

? 部署指的是將 Vue 項目dist 目錄部署到服務(wù)器上厉斟。
? 安裝靜態(tài)文件服務(wù)器:

  • npm install -g serve
    ? 在 dist 下通過 serve 命令部署
    先到dist目錄下:cd dist
    再運行服務(wù)器:serve
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市强衡,隨后出現(xiàn)的幾起案子擦秽,更是在濱河造成了極大的恐慌,老刑警劉巖漩勤,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件感挥,死亡現(xiàn)場離奇詭異,居然都是意外死亡锯七,警方通過查閱死者的電腦和手機(jī)链快,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來眉尸,“玉大人域蜗,你說我怎么就攤上這事≡牖” “怎么了霉祸?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長袱蜡。 經(jīng)常有香客問我丝蹭,道長,這世上最難降的妖魔是什么坪蚁? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任奔穿,我火速辦了婚禮,結(jié)果婚禮上敏晤,老公的妹妹穿的比我還像新娘贱田。我一直安慰自己,他們只是感情好嘴脾,可當(dāng)我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布男摧。 她就那樣靜靜地躺著,像睡著了一般译打。 火紅的嫁衣襯著肌膚如雪耗拓。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天奏司,我揣著相機(jī)與錄音乔询,去河邊找鬼。 笑死韵洋,一個胖子當(dāng)著我的面吹牛哥谷,可吹牛的內(nèi)容都是我干的岸夯。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼们妥,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了勉吻?” 一聲冷哼從身側(cè)響起监婶,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎齿桃,沒想到半個月后惑惶,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡短纵,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年带污,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片香到。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡鱼冀,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出悠就,到底是詐尸還是另有隱情千绪,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布梗脾,位于F島的核電站荸型,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏炸茧。R本人自食惡果不足惜瑞妇,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望梭冠。 院中可真熱鬧辕狰,春花似錦、人聲如沸妈嘹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽润脸。三九已至柬脸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間毙驯,已是汗流浹背倒堕。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留爆价,地道東北人垦巴。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓媳搪,卻偏偏與公主長得像,于是被迫代替她去往敵國和親骤宣。 傳聞我的和親對象是個殘疾皇子秦爆,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,834評論 2 345