Vue2.0構建——基礎總結

Miss_Ye發表於2017-11-23

Vue.js基礎總結

一、Vue使用介紹

Vue不支援IE8,因為使用了ES5的很多特性。可以直接通過script標籤來引入vue.js,有開發版本和生產版本,開發版本一般我們在開發專案的時候引入,當最後開發完成上線的時候引入生產版本,開發版本沒有壓縮的,並且有很多提示,而生產版本全部刪掉了。開發版本可以使用vue-devtools檢查程式碼,生產版本不可以使用vue-devtools。

二、vue-router實踐練習

1、傳參及獲取傳參

通過$route獲取相應引數
<div id="app">
  <div>
    <router-link to="/user/jack?age=20">jack</router-link>
    <!--另一種傳參方式-->
    <!--<router-link :to="name:'user',params:{name:'jack'},query:{age:20}">jack</router-link>-->
    <router-link to="/user/midy?age=35">midy</router-link>  //通過to傳遞引數
  </div>
  <div>
    <router-view></router-view>
  </div>

</div>
<script src="https://cdn.bootcss.com/vue/2.5.13/vue.js"></script>
<script src="https://cdn.bootcss.com/vue-router/3.0.1/vue-router.js"></script>
<script>
    var routes = [
        {
          path:'/user/:name',  //動態獲取引數
          component:{
            template:`
              <div>
                <h1>我叫: {{$route.params.name}}</h1>   // 符號'/'後面的用params獲取
                <h1>我今年: {{$route.query.age}} 歲。</h1> // 符號'?'後面的用query獲取
              </div>
            `
          }
        }
      ];

      var router = new VueRouter({
        routes: routes
      })

      new Vue({
        el:"#app",
        router: router,
      })
</script>

2、子路由

路由中設定children,其也是一個陣列
<div id="app">
  <div>
    <router-link to="/user/jack">jack</router-link>
    <router-link to="/user/midy">midy</router-link>
  </div>
  <div>
    <router-view></router-view>
  </div>

</div>
<script src="https://cdn.bootcss.com/vue/2.5.13/vue.js"></script>
<script src="https://cdn.bootcss.com/vue-router/3.0.1/vue-router.js"></script>
<script>

      var routes = [
        {
          path:'/user/:name',
          component:{
            template:`
              <div>
                <h1>我叫: {{$route.params.name}}</h1>
                //方法一:動態繫結路由,to值為動態字串拼接,比如:" /user/jack/more "
                <router-link :to="'/user/'+ $route.params.name +'/more'">顯示更多 
                //方法二:動態繫結路由,to值寫死,加上append屬性,表示在當前路由上追加一個'more'
                <!--<router-link to="more" append>顯示更多 -->                 
                </router-link>
                <router-view></router-view>
              </div>
            `
          }, 
          //定義子路由
          children:[
            {
              path:'more',
              component:{
                template:`
                  <div>
                   <p>我是 {{$route.params.name}},以下是我的更多資訊。</p>
                   <p>哈哈哈哈哈哈~~~~</p>
                  </div>
                `
              }
            }
          ]
        }
      ];

      var router = new VueRouter({
        routes: routes
      })

      new Vue({
        el:"#app",
        router: router,
      })

 </script>
    

3、手動訪問和傳參

this.router.push()方法
<div id="app">
  <div>
    <router-link to="/home">主頁</router-link>
    <router-link to="/user/jack">jack</router-link>
    <router-link to="/user/midy">midy</router-link>
    <button @click="surf">路由自動訪問</button>
  </div>
  <div>
    <router-view></router-view>
  </div>
</div>
<script src="https://cdn.bootcss.com/vue/2.5.13/vue.js"></script>
<script src="https://cdn.bootcss.com/vue-router/3.0.1/vue-router.js"></script>
<script>

  var routes = [
    {
      path:'/home',
      component:{
        template: `
          <div><h1>我是首頁!</h1></div>
        `
      }
    },
    {
      path:'/user/:name',
      name:'user',   //定義name屬性,供下面的" this.router.push "使用
      component:{
        template:`
          <div>
            <h1>我叫: {{$route.params.name}}</h1>
            <router-link :to="'/user/'+ $route.params.name +'/more'">顯示更多
            </router-link>
            <router-view></router-view>
          </div>
        `
      },
      children:[
        {
          path:'more',
          component:{
            template:`
              <div>
               <p>我是 {{$route.params.name}},以下是我的更多資訊。</p>
               <p>哈哈哈哈哈哈~~~~</p>
              </div>
            `
          }
        }
      ]
    }
  ];

  var router = new VueRouter({
    routes: routes
  })

  new Vue({
    el:"#app",
    router: router,
    methods:{
      surf () {
        //setTimeout函式體內最好不使用箭頭函式,因為this指向容易混淆
        setTimeout(function(){
          this.router.push('/home');
          setTimeout(function(){
            //動態傳參,其中name代表的是路由的'name'屬性值,params是傳遞引數
            this.router.push({name:'user',params:{name:'jack'}})
          },2000)
        },2000)
      }
    }
  })
</script>

4、命名檢視

給router-view定義name屬性
<div id="app">
  <div>
    <router-link to="/user">使用者管理</router-link>
    <router-link to="/post">帖子管理</router-link>
  </div>
  <div>
    //分別為router-view 定義name屬性,在下面定義顯示內容
    <router-view name="sidebar"></router-view>  
    <router-view name="content"></router-view>
  </div>

</div>
<script src="https://cdn.bootcss.com/vue/2.5.13/vue.js"></script>
<script src="https://cdn.bootcss.com/vue-router/3.0.1/vue-router.js"></script>
<script>

  var routes = [
    {
      path:'/user',
      //注意這裡的components,分別定義兩個router-view顯示內容
      components: {
        //sidebar的router-view
        sidebar:{
          template:`
            <ul>
              <li>使用者1</li>
              <li>使用者2</li>
            </ul>
          `
        },
        //content的router-view
        content:{
          template:`
            <div>使用者內容區域</div>
          `
        }
      }
    },
    {
      path:'/post',
      //注意這裡的components,分別定義兩個view顯示內容
      components:{
        sidebar:{
          template:`
            <ul>
              <li>帖子1</li>
              <li>帖子2</li>
            </ul>
          `
        },
        content:{
          template:`
            <div>帖子內容區域</div>
          `
        }
      }
    }
  ];

  var router = new VueRouter({
    routes: routes
  })

  new Vue({
    el:"#app",
    router: router,
  })

</script>

5、導航鉤子

實現的功能:如果使用者在未登入狀態下訪問"/post"或"/post/more"頁面,則會跳轉到"/login"頁面.
//方法一:通過判斷路由的方式
<div id="app">
  <div>
    <router-link to="/">主頁</router-link>
    <router-link to="/login">登入</router-link>
    <router-link to="/post">帖子管理</router-link>
    <router-view></router-view>
  </div>
</div>
<script src="https://cdn.bootcss.com/vue/2.5.13/vue.js"></script>
<script src="https://cdn.bootcss.com/vue-router/3.0.1/vue-router.js"></script>
<script>

  var routes = [
    {
      path:'/',
      component: {
        template:`
          <div>
            <h1>首頁</h1>
          </div>
        `
      }
    },
    {
      path:"/login",
      component:{
        template:`
          <div><h2>登入</h2></div>
        `
      }
    },
    {
      path:'/post',
      component:{
        template:`
          <div>
            <h1>帖子1</h1>
            <router-link to="more" append>檢視更多</router-link>
            <router-view></router-view>
          </div>
        `
      },
      children:[
        {
          path:'more',
          component:{
            template:`
            <h3>我是更多資訊!</h3>
          `
          }
        }
      ]
    }
  ];

  var router = new VueRouter({
    routes: routes
  })

  router.beforeEach(function(to,from,next){
    console.log(to)
    var logged_in = false;
    //some() 方法用於檢測陣列中的元素是否滿足指定條件,如果有一個元素滿足條件,則表示式返回true , 剩餘的元素不會再執行檢測.
    //to.matched返回的是陣列。
    if(!logged_in && to.matched.some(function(val){return val.path == '/post'})){
        this.router.push("/login")
    }
    else{
      next()
    }
  })

  new Vue({
    el:"#app",
    router: router,
  })

</script>

//方法二:在路由中設定meta屬性
<div id="app">
  <div>
    <router-link to="/">主頁</router-link>
    <router-link to="/login">登入</router-link>
    <router-link to="/post">帖子管理</router-link>
    <router-view></router-view>
  </div>
</div>
<script src="https://cdn.bootcss.com/vue/2.5.13/vue.js"></script>
<script src="https://cdn.bootcss.com/vue-router/3.0.1/vue-router.js"></script>
<script>

  var routes = [
    {
      path:'/',
      component: {
        template:`
          <div>
            <h1>首頁</h1>
          </div>
        `
      }
    },
    {
      path:"/login",
      component:{
        template:`
          <div><h2>登入</h2></div>
        `
      }
    },
    {
      path:'/post',
      //設定meta屬性,指定"是否需要登入"
      meta:{
        login_required: true
      },
      component:{
        template:`
          <div>
            <h1>帖子1</h1>
            <router-link to="more" append>檢視更多</router-link>
            <router-view></router-view>
          </div>
        `
      },
      children:[
        {
          path:'more',
          component:{
            template:`
            <h3>我是更多資訊!</h3>
          `
          }
        }
      ]
    }
  ];

  var router = new VueRouter({
    routes: routes
  })

  router.beforeEach(function(to,from,next){
    console.log(to)
    var logged_in = false;
    //some() 方法用於檢測陣列中的元素是否滿足指定條件,如果有一個元素滿足條件,則表示式返回true , 剩餘的元素不會再執行檢測.
    //通過獲取meta值判此頁面是否需要登入後才可訪問
    if(!logged_in && to.matched.some(function(item){return item.meta.login_required })){
        this.router.push("/login")
    }
    else{
      next()
    }
  })

  new Vue({
    el:"#app",
    router: router,
  })

</script>

三、易錯知識點——元件

1、父元件向子元件傳遞資訊時:

在html中定義或者繫結屬性的時候要符合kebab-case規則
<div id="dr2">
    <!-- kebab-case in html -->
    <child2 my-message2="Hello, this is kebab-case message!"></child2>
</div>
在js中定義的屬性名稱如果是"camelCase"規則,則在html定義或者繫結value的時候要用"kebab-case"規則。
Vue.component("child2", {
    //在js中用駝峰命名法
    props: ["myMessage2"],
    template: "<div>myMessage2: {{myMessage2}}</div>"
});
注意:下圖中的<child></child>才是字串模板,是通過template生成的,在這裡的props需要使用kebab-case形式,在js中使用camelCase形式。

圖片描述

2、prop驗證屬性

注意:下圖所說的"諸如data,computed 或methods等例項屬性還無法使用",指的是子元件自身定義的data,computed,methods屬性。而非父元件的相應屬性。

圖片描述

3、props中default屬性

注意:使用default屬性時,在父元件繫結的資料不需要再data函式中賦值。

在元件中的props中,針對String,Number型別中的default,直接對應值。其他型別的default是函式。(如果使用default屬性,就不能加上required:true屬性)如下:
//son元件的props屬性
props:{
    msg:{
      type:String,
      default: "abc"
    },
    num:{
      type:Number,
      default:10
    },
    myObj:{
      type:Object,
      //default為函式
      default: function (){
        return {name:"joy"}
      }
    }
  }
  
  
//parent元件傳遞的值
<son :msg="msgFather"></son>
<script>
export default {
  name: "Parent",
  data() {
    //此處不需要定義msgFather的值
    return {};
  },
  components: {
    son
  }
};
</script>

4、作用域插槽

插槽的資料是子傳父的!!!

注:在vue 2.5.0之前,"slot-scope"必須使用到template身上。如下:

//2.5.0之前寫法——父元件
<template>
  <div class="parent">
    <h1>我是父親!</h1>
    <son>
       //將slot和slot-scope屬性放在template上
      <template slot="slot1" slot-scope="key">
        <h2 >{{ key.text}}</h2>
      </template>
      //slot-scope屬性值可以使任意的,此處為"key"
      <template slot="slot2" slot-scope="key">
        <h2>{{key.text}}</h2>
      </template>
    </son>
  </div>
</template>


//2.5.0以後版本寫——父元件
<template>
  <div class="parent">
  <h1>我是父親!</h1>
  <son>
     //slot-scope屬性值可以使任意的,此處為"key"
    <h2 slot="slot1" slot-scope="key">{{ key.text}}</h2>
    <h2 slot="slot2" slot-scope="key">{{key.text}}</h2>
  </son>
</div>
</template>

//對應的子元件
<template>
<div class="son">
  <slot name="slot1" text="slot111111"></slot>
  <slot name="slot2" text="slot222222"></slot>
</div>
</template>

5、動態元件

<template>
  <div class="big">
  //通過comonent標籤的is屬性繫結當前的view檢視
    <component :is="currentView"> </component>
  </div>
</template>

<script>
  import small1 from "./small1"

  export default {
    name: "big",
    data(){
      return{
        //注意此處的small元件需要加引號
        currentView: 'small1'
      }
    },
    components:{
      small1
    }
  }
</script>

四、易錯知識點——自定義指令

1、全域性定義指令:directive!!!

全域性指令需要在main.js中去定義,如下:
//mian.js,全域性定義中用directive。
Vue.directive('focus',{
  inserted:function(el){
    el.focus();
  }
})

//hello.vue
<template>
  <div>
    //使用指令方式:v-*
    <input type="text" v-focus>
  </div>
</template   

2、區域性定義指令:directives!!!

<template>
  <div class="big">
    <input type="text" v-focus>
  </div>
</template>
<script>
  export default {
    name: "hello",
    //注:區域性定義指令需要用directives,與全域性定義不同。
    directives:{
      focus:{
        inserted (el){
          el.focus();
        }
      }
    }
  }
</script>

五、易錯知識點——路由

1、路由使用物件形式

//通過urlData.*獲得相應值
<router-link :to="urlData.hello">helloworld</router-link>
<router-link :to="urlData.parent">parent</router-link>
<router-view/>

data(){
    return{
      urlData:{
        hello:'/',
        parent:'/parent'
      }
    }
  }

2、路由傳遞引數(常用此方法!!!)

首先,在router/index.js檔案中:
export default new Router({
  routes: [
    {
      //冒號後面跟著引數
      path:'/parent/:father',
      name:'parent',
      component: parent
    }
  ]
})
然後在parent.vue元件
<template>
  <div class="parent">
  //這裡通過$route.params.*獲取傳遞過來的路由引數
  <h1>我是父親:{{$route.params.father}}</h1>
</div>
</template>
<script>
    export default {
      //設定parent.vue元件的name屬性,傳遞引數是需要用到name屬性值
      name: "parent",
    }
</script>
最後,找到parent對應的路由設定元件,配置如下
//router-link的name屬性對應的是parent.vue元件的name值.params是傳遞過去的路由引數
<router-link :to="{name:'parent',params:{father:1}}">parent</router-link>
注意:這樣的傳遞引數方式,最後的路由形式為:'localhost:8080/parent/father/1'。這種事很常見的路由傳遞引數。

3、路由巢狀:children

在router/index.js檔案中:
export default new Router({
  routes: [
    {
      path:"/",
      name:"HelloWorld",
      component:HelloWorld
    },
    {
      path:'/parent',
      name:'parent',
      //重定向,預設進來就顯示father元件的內容,在parent元件路由中配置
      redirect:"/parent/father",
      component: parent,
      children:[
        {
        //這裡的path不加'/',直接寫名字即可,它會自動補全前面的路徑
          path:'father',
          name:'father',
          component:Father
        },
        {
          path:'mother',
          name:'mother',
          component:Mother
        }
      ]
    }
  ]
})
在parent元件中:
//這裡的to屬性值要寫完整的路徑
<router-link to="/parent/father">father</router-link>
<router-link to="/parent/mother">mother</router-link>
<router-view></router-view>

4、路由高亮
(1)、被選中的路由會帶有"router-link-exact-active 、router-link-active"樣式,所以可以給啟用狀態的路由設定樣式。

//新增啟用樣式
.router-link-active{color:red;}
注意:此時會有一個問題,對於首頁路由"/",會在同級路由被選中的時候依然會帶有router-ink-active類名,這時候需要做在首頁路由做修改:
//在router-link上新增exact屬性
<router-link to="/" exact>home</router-link>

(2)router-link-active這個啟用類名比較長,對此,我們可以在router/index.js中進行全域性配置:

export default new Router({
  //全域性設定linkActiveClass為acitve,這樣啟用狀態的class就會變為active,相應的樣式就可以改為.active{color:red;}
  linkActiveClass:"active",
  routes: [
    {
      path:'/',
      name:HelloWorld,
      component:HelloWorld
    },
    {
      path:'/parent/:father',
      name:'parent',
      component: parent
    }
  ]
})

六、易錯知識點——methods

(1)、箭頭函式不可用

注意: 在methods屬性中定義的方法不能使用箭頭函式,因為此時的this指向的是window,而不是Vue例項。

(2)、

//此處直接呼叫事件,並沒有'()'
<button @click="showSome">click me </button>

methods:{
    showSome :function (event){
       //得到的就是滑鼠事件
        console.log(event)
    }
}

結果:
圖片描述
(3)、

//此處直接呼叫事件,並加上'()',但是並沒有引數傳遞![圖片描述][4]
<button @click="showSome()">click me </button>

methods:{
    showSome :function (event){
    //這樣得到event就是'undefined'
        console.log(event)
    }
}

結果:
圖片描述

(4)、

//此處直接調事件,如果想獲得滑鼠事件,傳遞的引數必須是$event否則就不要傳遞引數了
<button @click="showSome($event)">click me </button>

methods:{
    showSome :function (event){
    //這樣得到event就是'滑鼠事件'
        console.log(event)
    }
}

結果:圖片描述

!!! (5)、methods 和 computed 不同使用方式:

computed可以向methods一樣傳遞引數:解決辦法是使用閉包
//key是傳遞的引數
computed:{
    getTitle(key):function(){
        return function(){
            return key + "abc"
        }
    }
}

七、易錯知識點——select預設選中

1、vue中設定select預設選中:v-model

<template>
  <div class="hello">
  //select上通過v-model繫結預設選中項
    <select name="" id="" v-model="city">
      <option value="" v-for="item in cityList" :value="item.value" v-text="item.city"></option>
    </select>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      cityList:[
        {value:"001",city:"南京市"},
        {value:"002",city:"深圳市"},
        {value:"004",city:"杭州市"},
        {value:"005",city:"北京市"},
        {value:"003",city:"上海市"},
      ],
      //通過city值設定預設選中城市
      city:"003"
    }
  }
}
</script>

結果如圖所示:
圖片描述

八、易錯知識點——v-model

1、一般form表單會使用v-model比較多,實現資料的雙向繫結

<input v-model="sth" />
<input v-bind:value="sth" v-on:input="sth = $event.target.value" />

要理解這行程式碼,首先你要知道 input 元素本身有個 oninput 事件,這是 HTML5 新增加的,類似 onchange ,每當輸入框內容發生變化,就會觸發 oninput ,把最新的value傳遞給 sth。進而實現了資料雙向繫結。

總結:
在給元素新增v-model屬性時,預設會把value作為元素的屬性,然後把input 事件作為實時傳遞value的觸發事件。

//子元件
Vue.component('currency-input', {
  template: `
    <span>
      <input
        @input="$emit('input', $event.target.value)">
        </span>
      `
})
//父元件中呼叫子元件
<currency-input v-model="price"></currentcy-input>
<!--上行程式碼是下行的語法糖-->
<currency-input :value="price" @input="price = arguments[0]"></currency-input>

相關文章