Vue學習(四)元件(參考)

起風了發表於2019-03-01

元件

定義Vue元件

什麼是元件: 元件的出現,就是為了拆分Vue例項的程式碼量的,能夠讓我們以不同的元件,來劃分不同的功能模組,將來我們需要什麼樣的功能,就可以去呼叫對應的元件即可; 元件化和模組化的不同:

  • 模組化: 是從程式碼邏輯的角度進行劃分的;方便程式碼分層開發,保證每個功能模組的職能單一;
  • 元件化: 是從UI介面的角度進行劃分的;前端的元件化,方便UI元件的重用;

全域性元件定義的三種方式

  1. 使用 Vue.extend 配合 Vue.component 方法:
var login = Vue.extend({
      template: '<h1>登入</h1>'
    });
    Vue.component('login', login);
複製程式碼
  1. 直接使用 Vue.component 方法:
Vue.component('register', {
      template: '<h1>註冊</h1>'
    });
複製程式碼
  1. 將模板字串,定義到script標籤種:
<script id="tmpl" type="x-template">
      <div><a href="#">登入</a> | <a href="#">註冊</a></div>
    </script>
複製程式碼

同時,需要使用 Vue.component 來定義元件:

Vue.component('account', {
      template: '#tmpl'
    });
複製程式碼

注意: 元件中的DOM結構,有且只能有唯一的根元素(Root Element)來進行包裹!

元件中展示資料和響應事件

  1. 在元件中,data需要被定義為一個方法,例如:
Vue.component('account', {
      template: '#tmpl',
      data() {
        return {
          msg: '大家好!'
        }
      },
      methods:{
        login(){
          alert('點選了登入按鈕');
        }
      }
    });
複製程式碼
  1. 在子元件中,如果將模板字串,定義到了script標籤中,那麼,要訪問子元件身上的data屬性中的值,需要使用this來訪問;

【重點】為什麼元件中的data屬性必須定義為一個方法並返回一個物件

  1. 通過計數器案例演示

使用components屬性定義區域性子元件

  1. 元件例項定義方式:
<script>
    // 建立 Vue 例項,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {},
      components: { // 定義子元件
        account: { // account 元件
          template: '<div><h1>這是Account元件{{name}}</h1><login></login></div>', // 在這裡使用定義的子元件
          components: { // 定義子元件的子元件
            login: { // login 元件
              template: "<h3>這是登入元件</h3>"
            }
          }
        }
      }
    });
  </script>
複製程式碼
  1. 引用元件:
<div id="app">
    <account></account>
  </div>
複製程式碼

使用flag識別符號結合v-ifv-else切換元件

  1. 頁面結構:
<div id="app">
    <input type="button" value="toggle" @click="flag=!flag">
    <my-com1 v-if="flag"></my-com1>
    <my-com2 v-else="flag"></my-com2>
  </div>
複製程式碼
  1. Vue例項定義:
<script>
    Vue.component('myCom1', {
      template: '<h3>奔波霸</h3>'
    })

    Vue.component('myCom2', {
      template: '<h3>霸波奔</h3>'
    })

    // 建立 Vue 例項,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        flag: true
      },
      methods: {}
    });
  </script>
複製程式碼

使用:is屬性來切換不同的子元件,並新增切換動畫

  1. 元件例項定義方式:
  // 登入元件
    const login = Vue.extend({
      template: `<div>
        <h3>登入元件</h3>
      </div>`
    });
    Vue.component('login', login);

    // 註冊元件
    const register = Vue.extend({
      template: `<div>
        <h3>註冊元件</h3>
      </div>`
    });
    Vue.component('register', register);

    // 建立 Vue 例項,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: { comName: 'login' },
      methods: {}
    });
複製程式碼
  1. 使用component標籤,來引用元件,並通過:is屬性來指定要載入的元件:
  <div id="app">
    <a href="#" @click.prevent="comName='login'">登入</a>
    <a href="#" @click.prevent="comName='register'">註冊</a>
    <hr>
    <transition mode="out-in">
      <component :is="comName"></component>
    </transition>
  </div>
複製程式碼
  1. 新增切換樣式:
  <style>
    .v-enter,
    .v-leave-to {
      opacity: 0;
      transform: translateX(30px);
    }

    .v-enter-active,
    .v-leave-active {
      position: absolute;
      transition: all 0.3s ease;
    }

    h3{
      margin: 0;
    }
  </style>
複製程式碼

父元件向子元件傳值

  1. 元件例項定義方式,注意:一定要使用props屬性來定義父元件傳遞過來的資料
<script>
    // 建立 Vue 例項,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        msg: '這是父元件中的訊息'
      },
      components: {
        son: {
          template: '<h1>這是子元件 --- {{finfo}}</h1>',
          props: ['finfo']
        }
      }
    });
  </script>
複製程式碼
  1. 使用v-bind或簡化指令,將資料傳遞到子元件中:
<div id="app">
    <son :finfo="msg"></son>
  </div>
複製程式碼

子元件向父元件傳值

  1. 原理:父元件將方法的引用,傳遞到子元件內部,子元件在內部呼叫父元件傳遞過來的方法,同時把要傳送給父元件的資料,在呼叫方法的時候當作引數傳遞進去;
  2. 父元件將方法的引用傳遞給子元件,其中,getMsg是父元件中methods中定義的方法名稱,func是子元件呼叫傳遞過來方法時候的方法名稱
<son @func="getMsg"></son>
複製程式碼
  1. 子元件內部通過this.$emit('方法名', 要傳遞的資料)方式,來呼叫父元件中的方法,同時把資料傳遞給父元件使用
<div id="app">
    <!-- 引用父元件 -->
    <son @func="getMsg"></son>

    <!-- 元件模板定義 -->
    <script type="x-template" id="son">
      <div>
        <input type="button" value="向父元件傳值" @click="sendMsg" />
      </div>
    </script>
  </div>

  <script>
    // 子元件的定義方式
    Vue.component('son', {
      template: '#son', // 元件模板Id
      methods: {
        sendMsg() { // 按鈕的點選事件
          this.$emit('func', 'OK'); // 呼叫父元件傳遞過來的方法,同時把資料傳遞出去
        }
      }
    });

    // 建立 Vue 例項,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {
        getMsg(val){ // 子元件中,通過 this.$emit() 實際呼叫的方法,在此進行定義
          alert(val);
        }
      }
    });
  </script>
複製程式碼

評論列表案例

目標:主要練習父子元件之間傳值

使用 this.$refs 來獲取元素和元件

  <div id="app">
    <div>
      <input type="button" value="獲取元素內容" @click="getElement" />
      <!-- 使用 ref 獲取元素 -->
      <h1 ref="myh1">這是一個大大的H1</h1>

      <hr>
      <!-- 使用 ref 獲取子元件 -->
      <my-com ref="mycom"></my-com>
    </div>
  </div>

  <script>
    Vue.component('my-com', {
      template: '<h5>這是一個子元件</h5>',
      data() {
        return {
          name: '子元件'
        }
      }
    });

    // 建立 Vue 例項,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {
        getElement() {
          // 通過 this.$refs 來獲取元素
          console.log(this.$refs.myh1.innerText);
          // 通過 this.$refs 來獲取元件
          console.log(this.$refs.mycom.name);
        }
      }
    });
  </script>
複製程式碼

什麼是路由

  1. 對於普通的網站,所有的超連結都是URL地址,所有的URL地址都對應伺服器上對應的資源;

  2. 對於單頁面應用程式來說,主要通過URL中的hash(#號)來實現不同頁面之間的切換,同時,hash有一個特點:HTTP請求中不會包含hash相關的內容;所以,單頁面程式中的頁面跳轉主要用hash實現;

  3. 在單頁面應用程式中,這種通過hash改變來切換頁面的方式,稱作前端路由(區別於後端路由);

在 vue 中使用 vue-router

  1. 匯入 vue-router 元件類庫:
<!-- 1. 匯入 vue-router 元件類庫 -->
  <script src="./lib/vue-router-2.7.0.js"></script>
複製程式碼
  1. 使用 router-link 元件來導航
<!-- 2. 使用 router-link 元件來導航 -->
<router-link to="/login">登入</router-link>
<router-link to="/register">註冊</router-link>
複製程式碼
  1. 使用 router-view 元件來顯示匹配到的元件
<!-- 3. 使用 router-view 元件來顯示匹配到的元件 -->
<router-view></router-view>
複製程式碼
  1. 建立使用Vue.extend建立元件
    // 4.1 使用 Vue.extend 來建立登入元件
    var login = Vue.extend({
      template: '<h1>登入元件</h1>'
    });

    // 4.2 使用 Vue.extend 來建立註冊元件
    var register = Vue.extend({
      template: '<h1>註冊元件</h1>'
    });
複製程式碼
  1. 建立一個路由 router 例項,通過 routers 屬性來定義路由匹配規則
// 5. 建立一個路由 router 例項,通過 routers 屬性來定義路由匹配規則
    var router = new VueRouter({
      routes: [
        { path: '/login', component: login },
        { path: '/register', component: register }
      ]
    });
複製程式碼
  1. 使用 router 屬性來使用路由規則
// 6. 建立 Vue 例項,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      router: router // 使用 router 屬性來使用路由規則
    });
複製程式碼

設定路由高亮

設定路由切換動效

在路由規則中定義引數

  1. 在規則中定義引數:
{ path: '/register/:id', component: register }
複製程式碼
  1. 通過 this.$route.params來獲取路由中的引數:
var register = Vue.extend({
      template: '<h1>註冊元件 --- {{this.$route.params.id}}</h1>'
    });
複製程式碼

使用 children 屬性實現路由巢狀

  <div id="app">
    <router-link to="/account">Account</router-link>

    <router-view></router-view>
  </div>

  <script>
    // 父路由中的元件
    const account = Vue.extend({
      template: `<div>
        這是account元件
        <router-link to="/account/login">login</router-link> | 
        <router-link to="/account/register">register</router-link>
        <router-view></router-view>
      </div>`
    });

    // 子路由中的 login 元件
    const login = Vue.extend({
      template: '<div>登入元件</div>'
    });

    // 子路由中的 register 元件
    const register = Vue.extend({
      template: '<div>註冊元件</div>'
    });

    // 路由例項
    var router = new VueRouter({
      routes: [
        { path: '/', redirect: '/account/login' }, // 使用 redirect 實現路由重定向
        {
          path: '/account',
          component: account,
          children: [ // 通過 children 陣列屬性,來實現路由的巢狀
            { path: 'login', component: login }, // 注意,子路由的開頭位置,不要加 / 路徑符
            { path: 'register', component: register }
          ]
        }
      ]
    });

    // 建立 Vue 例項,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {},
      components: {
        account
      },
      router: router
    });
  </script>
複製程式碼

命名檢視實現經典佈局

  1. 標籤程式碼結構:
<div id="app">
    <router-view></router-view>
    <div class="content">
      <router-view name="a"></router-view>
      <router-view name="b"></router-view>
    </div>
  </div>
複製程式碼
  1. JS程式碼:
<script>
    var header = Vue.component('header', {
      template: '<div class="header">header</div>'
    });

    var sidebar = Vue.component('sidebar', {
      template: '<div class="sidebar">sidebar</div>'
    });

    var mainbox = Vue.component('mainbox', {
      template: '<div class="mainbox">mainbox</div>'
    });

    // 建立路由物件
    var router = new VueRouter({
      routes: [
        {
          path: '/', components: {
            default: header,
            a: sidebar,
            b: mainbox
          }
        }
      ]
    });

    // 建立 Vue 例項,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {},
      router
    });
  </script>
複製程式碼
  1. CSS 樣式:
  <style>
    .header {
      border: 1px solid red;
    }

    .content{
      display: flex;
    }
    .sidebar {
      flex: 2;
      border: 1px solid green;
      height: 500px;
    }
    .mainbox{
      flex: 8;
      border: 1px solid blue;
      height: 500px;
    }
  </style>
複製程式碼

相關文章