VUE 學習筆記

VUE學習筆記

VUE CLI 腳手架

優勢:

腳手架是經過webpack搭建的開發環境php

使用ES6語法html

打包和壓縮JS爲一個文件vue

項目文件在環境中編譯,而不是瀏覽器node

實現頁面自動刷新webpack

環境要求:

nodejs ≥ 6.9ios

npm ≥ 3.10web

安裝

$ npm install -g vue-clivue-router

$ vue --versionvuex

使用

$ vue init <template-name> <project-name>vue-cli

好比,

$ vue init webpack my-project

$ cd my-project

$ npm install

$ npm run dev

執行流程

index.html --> main.js --> App.vue

精簡App.vue文件
// 一、模板:html結構 template子元素有且只能有一個
<template>
 <div id="app">
   <h1>{{ title }}</h1>
 </div>
</template>
// 二、行爲:處理邏輯
<script>
export default {
 name: 'App',
 data() {
   return {
     title: 'Hello VUE!'
  }
}
}
</script>
// 三、樣式:解決
<style>

</style>

Vue.js規定:在定義組件的選項時,datael選項必須使用函數。 另外,若是data選項指向某個對象,這意味着全部的組件實例共用一個data。 咱們應當使用一個函數做爲 data 選項,讓這個函數返回一個新對象: Vue.component('my-component', { data: function() { return { title: 'Hello VUE!' } } })

組件的註冊

全局
// 在 main.js 中全局註冊組件
import Users from './components/Users'
Vue.component('users', Users);
局部
<script>
// 局部註冊組件
import Users from './components/Users'

export default {
 name: 'App',
 data() {
   return {
     title: 'Hello VUE!'
  }
},
 components: {
   "users": Users
}
}
</script>

 

組件CSS做用域

<!-- Add "scoped" attribute to limit CSS to this component only -->

若是在 <sytle> 中不加 scoped 則後面的屬性覆蓋前面的,不然每一個組件各自用各自的樣式。

<style scoped>
...
</style>

 

Vue 屬性傳值Props

父傳子

<!-- 給子組件傳值 -->
<users v-bind:users="users"></users>

export default {
 name: "App",
 data() {
   return {
     title: "Hello VUE!",
     users: [
      { name: "Henry", position: "WEB", show: true },
      { name: "Bucky", position: "PHP", show: false },
      { name: "Emily", position: "C", show: true },
      { name: "Tom", position: "JAVA", show: true },
      { name: "Jerry", position: "Python", show: true },
      { name: "Tim", position: "Go", show: false },
      { name: "Bob", position: "C#", show: true }
    ]
  }
}
};
export default {
 name: "Users",
 // 獲取父組件的傳遞的值
 // props: ["users"],
 // 官方推薦的標準寫法  
 props: {
   users: {
     type: Array,
     required: true
  }
},
 data() {
   return {

  };
}
};

 

傳值和傳引用

傳值:string、number、boolean

引用(會改變相關數據):array、object

 

事件傳值

<!-- 子傳父 -->
<template>
 <div class="header">
   <h1>{{ title }}</h1>
   <!-- 1、監聽事件 -->
   <p @click="changeTitle">{{ app_title }}</p>
 </div>
</template>

methods: {
   changeTitle: function() {
     // 二、觸發事件  
     this.$emit("titleChanged", "子傳父");
  }
}
<!-- v-on 子傳父 v-bind 父傳子 -->
<app-header v-on:titleChanged="updateTitle($event)" v-bind:app_title="title"></app-header>

methods: {
   updateTitle: function(title){
     this.title = title;
  }
}

 

生命週期

生命週期鉤子的函數:

beforeCreate: 組件實例化以前;可作加載動畫

created: 組件建立、屬性綁定、DOM未生成;可作數據請求,付給屬性,結束加載動畫

beforeMount: 組件掛在以前,頁面仍未顯示,虛擬DOM已配置;

mounted: 組件掛在以後,頁面已顯示;

beforeUpdate: 組件更新以前,頁面仍未更新,虛擬DOM已配置;

updated: 組件更新以後,顯示新的頁面;

beforeDestory: 組件銷燬以前;

destoryed: 組件銷燬以後;

 

路由和Http

路由:

安裝:$ npm install vue-router --save-dev

main.js中

import VueRouter from 'vue-router'

Vue.use(VueRouter)

// 配置路由

const router = new VueRouter({
   routes: [
    {path:'/', component: Home},
    {path:'/hello', component: HelloWorld},
    {path: '*', redirect: '/' } // miss路由
  ],
  // 去除url地址中的 #
  mode: "history"
});

new Vue({

 router,

 el: '#app',

 components: { App },

 template: '<App/>'

})

App組件中

// 在APP組件中
<!-- 路由匹配到的組件將渲染在這裏 -->
<router-view></router-view>

跳轉

<a href="/">Home</a>
<router-link to="/">Home</router-link>
// router-link 默認是 a 標籤,可以使用 tag 屬性來改變,如 tag=「div」
// v-bind:to 動態綁定值
<router-link v-bind:to="homeLink" tag="div">主頁</router-link>
<script>
export default {
 data (){
   return {
       homeLink: '/'
  }
}
}
</script>
// 或者若有註冊時,name屬性綁定
const routes = [
{ path: '/', name:'homeLink', component: Home },
]
<router-link v-bind:to="{name:'homeLink'}">主頁</router-link>
跨域處理:
// 在根目錄下config的index.js中的proxyTable屬性配置跨域請求
proxyTable: {
   '/apis': { //替換代理地址名稱
       target: 'http://php.test', //代理地址
           changeOrigin: true, //能否跨域
               pathRewrite: {
                   '^/apis': '' //重寫接口,去掉/apis
              }
  }
},
Http:

安裝 vue-resource$ npm install vue-resource --save-dev

注:此插件已再也不維護

import VueSource from 'vue-resource'
Vue.use(VueSource)
created: function(){
   this.$http.get("https://jsonplaceholder.typicode.com/users")
  .then((data) => {
       // 賦值
       this.users = data.body;
  })
}

安裝 axios$ npm install axios 安裝 qs$ npm install --save qs

import Axios from 'axios'
import Qs from 'qs'
Axios.defaults.headers.common['token'] = 'xxxxxxxxxx'
Axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'
// 轉爲數組形式 而不是json
Axios.defaults.transformRequest = [ function (data) {
   data = Qs.stringify(data);
   return data;
}]

Vue.prototype.$axios = Axios

// 使用axios
this.$axios.post("/apis/api/hello.php", {
   username: "tome",
   password: 123456
}).then(result => {
   console.log(result.data);
});

使用fetch

// 或者使用fetch()
fetch("/apis/api/hello.php", { //即親求 http://php.test/api/hello.php
   method: "post",
   headers: {
       "Content-Type": "application/json",
       token: "xxxxxxxxxx"
  },
   // 以post方法 request payload json形式發送的數據 php後臺獲取數據爲:
   // $post = json_decode(file_get_contents('php://input'), true);
   body: JSON.stringify({ username: "tom", password: 123456 })
}).then(result => {
   // console.log(result)
   return result.json();
}).then(data => {
   console.log(data);
});

 

搭建腳手架

$ vue init webpack-simple xxx

 

路由跳轉

<script>
export default {
 methods: {
   goToMenu: function() {
     // 跳轉到上一個頁面
     this.$router.go(-1);
     // 指定跳轉的地址
     this.$router.replace('/menu');
     // 指定跳轉路由的名字下
     this.$router.replace({name:'menuLink'});
     // 經過push跳轉
     this.$router.push('/menu');
     this.$router.push({name:'menuLink'});
  }
}
};
</script>

 

二級路由和三級路由

// children屬性定義 三級路由雷同
const routes = [
{
   path: '/about', name: 'aboutLink', component: About, children: [
    { path: 'history',name:'historyLink', component: History }, // /about/history
    { path: '/delivery',name:'deliveryLink', component: Delivery },// /delivery
  ]
}
]

 

導航守衛

全局守衛
// 全局守衛
router.beforeEach((to, from, next) => {
 if (to.path == '/login' || to.path == '/register') {
   // 正常展現
   next();
} else {
   alert('請先登陸!');
   next('/login');
}

})
路由獨享
const routes = [
{
   path: '/admin', name: 'adminLink', component: Admin, beforeEnter: (to, from, next) => {
     // 路由獨享守衛
     alert('請先登陸');
     next('/login');
     // next(false);
  }
},
]
組件內守衛
<script>
export default {
 data() {
   return {
     name: "Herry"
  };
},
 beforeRouteEnter: (to, from, next) => {
   // 此時還獲取不到data
   alert("Hello " + this.name);
   // 回調
   next(vm => {
     alert("Hello " + vm.name);
  });
},
 beforeRouteLeave: (to, from, next) => {
   // 離開
   if (confirm("肯定離開嗎")) {
     next();
  } else {
     next(false);
  }
}
};
</script>

 

複用router-view

// App.vue中複用orderingGuide、deliver、history組件
<div class="container">
   <div class="row">
       <div class="col-sm-12 col-md-4">
           <router-view name="orderingGuide"></router-view>
       </div>
       <div class="col-sm-12 col-md-4">
           <router-view name="deliver"></router-view>
       </div>
       <div class="col-sm-12 col-md-4">
           <router-view name="history"></router-view>
       </div>
   </div>
</div>
// 路由組測分離到單獨文件 routes.js
// 複用其餘路由組件 把 components 屬性值改成對象形式並把組件組測進來
// 此時 Home組件就能夠複用 router-view 了
export const routes = [
{
   path: '/', name: 'homeLink', components: {
     default: Home,
     'orderingGuide': OrderingGuide,
     'deliver': Delivery,
     'history': History
  }
},
]
// 並在main.js中引入
import {routes} from './routes'

 

控制滾動行爲

// main.js
const router = new VueRouter({
 routes,
 mode: 'history',  
 // 只在支持 history.pushState 的瀏覽器中
 scrollBehavior(to, from, savedPosition) {
   return { x: 0, y: 100 };
   return { selector: '.btn' }; // 跳轉到 .btn 樣式位置
}
})

Vuex

概述

主要應用於Vue.js中管理數據狀態的一個庫

經過建立一個集中的數據存儲,供程序中全部組件訪問

安裝

$ npm install vuex --save

使用
// 建立 store.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export const store = new Vuex.store({
   // 嚴格模式
   strict: true,
   // 存儲數據
   state: {
       products: [
          { name: "馬雲", price: 200 },
          { name: "馬化騰", price: 140 },
          { name: "馬冬梅", price: 20 },
          { name: "馬蓉", price: 10 }
      ]
  },
   // 獲取數據
   getters: {
       newLists: (state) => {
           var newLists = state.lists.map(change => {
               return {
                   name: '**' + change.name + '**',
                   price: change.price / 2
              }
          });
           return newLists;
      }
  },
   // 出發事件時調用
   mutations: {
       reducePrice:(state) => {
           state.lists.forEach(element => {
               element.price -= 1;
          });
      }
  },
   // 異步操做和傳參
   actions: {
       // 傳參 payload
       reducePrice: (context, payload) => {
           // 異步
           setTimeout(function () {
               // 提交 mutations 中的方法
               context.commit("reducePrice", payload);
          }, 3000)
      }
  }
});

main.js中引入

import Vue from 'vue'
import App from './App.vue'
import {store} from './store/store'

new Vue({
 store:store,
 el: '#app',
 render: h => h(App)
})

組件一中使用state中的lists 數據

<template>
 <div id="productListOne">
   <h2>Product List One</h2>
   <ul>
     <li v-for="list in lists">
       <span class="name">{{ list.name }}</span>
       <span class="price">${{ list.price }}</span>
     </li>
   </ul>
 </div>
</template>

<script>
export default {
 computed: {
     lists(){
         return this.$store.state.lists;
    }
}
};
</script>

組件二中使用getters中的newLists函數

<template>
 <div id="productListOne">
   <h2>Product List One</h2>
   <ul>
     <li v-for="list in newlists">
       <span class="name">{{ list.name }}</span>
       <span class="price">${{ list.price }}</span>
     </li>
   </ul>
 </div>
</template>

<script>
export default {
 computed: {
     // 使用getters中的函數,改變store中的值
     newlists(){
         return this.$store.getters.newLists;
    }
}
};
</script>

組件三中使用mutations中的函數

<template>
 <div id="productListOne">
   <h2>Product List Two</h2>
   <ul>
     <li v-for="list in lists">
       <span class="name">{{ list.name }}</span>
       <span class="price">${{ list.price }}</span>
     </li>
   </ul>
<!-- 定義事件 -->
   <button v-on:click="reducePrice">商品降價</button>
 </div>
</template>

<script>
export default {
 computed: {
   lists() {
     return this.$store.state.lists;
  }
},
 methods: {
   reducePrice: function() {
     //   this.$store.state.lists.forEach(element => {
     //       element.price -= 1;
     //   });
     // 出發vuex中的事件  
     this.$store.commit("reducePrice");
  }
}
};
</script>

組件四中使用actions,功能相似與mutations

<template>
 <div id="productListOne">
   <h2>Product List Two</h2>
   <ul>
     <li v-for="list in lists">
       <span class="name">{{ list.name }}</span>
       <span class="price">${{ list.price }}</span>
     </li>
   </ul>
   <button v-on:click="reducePrice(3)">商品降價</button>
 </div>
</template>

<script>
export default {
 computed: {
   lists() {
     return this.$store.state.lists;
  }
},
 methods: {
   reducePrice: function(amount) {
      // 出發action且傳參
      this.$store.dispatch('reducePrice', amount);
  }
}
};
</script>

 

Vuex-Mapping Actions & Getters

安裝語法支持:$ npm install babel-preset-stage-2 --save-dev

// babelrc文件中設置 stage-2
import {mapGetters} from 'vuex'
import {mapActions} from 'vuex'
methods: {
   reducePrice: function(amount) {
     this.$store.dispatch("reducePrice", amount);
  },
   // 簡化
   ...mapActions(["reducePrice"])
}
computed: {
     newlists(){
         return this.$store.getters.newLists;
    },
     // 簡化
     ...mapGetters([
         'newLists'
    ])
}

 

Tips

谷歌插件Vue.js devtools
問題:[npm ERR! code ELIFECYCLE]
  • npm cache clean --force

  • delete node_modules folder

  • delete package-lock.json file

  • npm install

相關文章
相關標籤/搜索