腳手架是經過webpack搭建的開發環境php
使用ES6語法html
vue
項目文件在環境中編譯,而不是瀏覽器node
實現頁面自動刷新webpack
nodejs ≥ 6.9ios
npm ≥ 3.10web
$ npm install -g vue-cli
vue-router
$ vue --version
vuex
$ 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
// 一、模板: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規定:在定義組件的選項時,data 和 el選項必須使用函數。 另外,若是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>
<!-- Add "scoped" attribute to limit CSS to this component only -->
若是在 <sytle> 中不加 scoped 則後面的屬性覆蓋前面的,不然每一個組件各自用各自的樣式。
<style scoped>
...
</style>
父傳子
<!-- 給子組件傳值 -->
<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: 組件銷燬以後;
安裝:$ 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
}
}
},
安裝 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>
// 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 樣式位置
}
})
主要應用於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>
安裝語法支持:$ 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);
},
// 簡化
npm cache clean --force
delete node_modules
folder
delete package-lock.json
file