github github.com/guxiansheng…javascript
html, css, javascript關係 相似於人體: html爲骨架 css爲血肉和外貌 javascript是人的行爲css
html搭建起整個頁面的文檔結構,css爲文檔結構設置樣式,javascript作交互行爲.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>demo</title>
<style>
.box {
width: 200px;
height: 200px;
border: 1px solid #ccc;
}
.box1 {
font-size: 12px;
color: red;
}
.box2 .p1 {
font-size: 20px;
color: blue;
}
</style>
</head>
<body>
<div class="box box1">
<h1>一念起天涯咫尺</h1>
<h1>一念滅咫尺天涯</h1>
</div>
<div class="box box2">
<button onclick="changeText(event)">點擊修改dom元素</button>
<p class="p1" id="p1"></p>
</div>
</body>
<script>
function changeText(e) {
var p1 = document.getElementById('p1');
p1.innerText = Math.random();
}
</script>
</html>
複製代碼
前端目前主要存在如下幾個方向,每一個方向存在着不一樣的框架前端
(1) Vue.jsvue
(2) React.jsjava
(3) Angularnode
PWA(Progressive Web Apps),谷歌提出的一種基於瀏覽器的技術,使用web前端技術開發的,可是能夠將應用添加到桌面,能夠離線使用,能夠有推送通知等更加相似於APP的功能.webpack
微信小程序,QQ小程序,百度小程序等等ios
(1) React Native(Facebook)git
(2) Flutter(谷歌)
(3) Hbuilder(國內企業作的)
Electron
Node.js
Any application that can be written in JavaScript, will eventually be written in JavaScript.
任何可以用 JavaScript 實現的應用,最終都必將用 JavaScript 實現。
Node.js 是一個基於 Chrome V8 引擎的 JavaScript 運行環境。Node.js 使用了一個事件驅動、非阻塞式 I/O 的模型,使其輕量又高效。 官網: nodejs.cn
Node.js主要應用場景以下:
先後端分離開發:
以上打包命令都會被定義在項目根目錄下的package.json中的scripts中,不然沒法使用
Demo1.vue中 data中定義的 text屬性被綁定到h1標籤的內容上了.
srcText是一個圖片連接,被綁定到img標籤的src屬性中
v-on指令綁定了methods中的點擊事件clickMethod
Demo1.vue中根據data中show屬性是true/false,顯示或者隱藏標籤
經過toggle方法切換show的值,從而完成標籤的顯示和隱藏
v-show只會隱藏元素(修改元素的display屬性),可是不會從html文檔中刪除標籤,只是切換顯示或者隱藏,因此性能高,適合頻繁切換的場景
v-if false時會從html文檔中刪除標籤, 因此性能消耗大,不適合頻繁切換的場景
Demo1.vue中 data裏面的arr數組,經過v-for指令完成循環
Demo1.vue中 經過v-on綁定html標籤原生的相關事件,好比click,mouseover等等, 綁定的方法聲明在methods中.
component1.vue組件代碼段是一個.vue文件,跟一個普通組件同樣的.
Demo1.vue中, (1)引入component1.vue, (2)components中引用組件, (3)頁面中使用小寫使用組件,兩個大寫則小寫後用短橫槓分開
父組件向子組件傳遞數據, Demo1.vue中, text是傳入子組件的屬性,在子組件component1.vue中經過props接收.
子組件向父組件傳遞數據, component1.vue組件代碼段中經過emitMethod方法emit出去一個data1事件,並傳值爲 '嘿嘿嘿'; Demo1.vue中,在組件使用的地方接收 v-on:data1="accept",在accept的參數中就是接收到的 '嘿嘿嘿'.
Demo1.vue
<template>
// Demo1.vue
<div>
<h1>{{text}}</h1>
<img class="image1" v-bind:src="srcText" alt="">
<button v-on:click="clickMethod">點擊</button>
<!-- computed -->
<hr>
<button @click="changeRandowNumber">點擊生成隨機數</button>
<p>randomNumber:{{randomNumber}}</p>
<p>test1:{{test1}}</p>
<!-- watch -->
<hr>
<button @click="changeWatchParam">點擊生成watchParam</button>
<!-- 條件 -->
<hr>
<button @click="toggle">切換隱藏和顯示</button>
<p v-if="show">顯示{{show}}</p>
<p v-else>隱藏{{show}}</p>
<p v-show="show">v-show切換{{show}}</p>
<!-- 循環 -->
<hr>
<div v-for="(item, index) in arr" :key="index">{{item}}</div>
<!-- 組件 -->
<component1 :text="component1Text" v-on:data1="accept"></component1>
<!-- 子路由 -->
<router-view></router-view>
</div>
</template>
<script>
import Component1 from './component1'
export default {
data () {
return {
text: '驢媽媽',
srcText: 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1561442417122&di=e6fa319459f0ea95645b2bde6d2591a3&imgtype=0&src=http%3A%2F%2Ff.hiphotos.baidu.com%2Fimage%2Fpic%2Fitem%2F8d5494eef01f3a29f863534d9725bc315d607c8e.jpg',
randomNumber: 0,
watchParam: 0,
show: false,
arr: [1, 2, 3, 4, 5, 6],
component1Text: 234
}
},
components: {
Component1
},
// 計算屬性
computed: {
test1 () {
let res = 0
res = this.randomNumber * 1000
return res
}
},
//
watch: {
watchParam (newVal, oldVal) {
console.log('newVal', newVal)
console.log('oldVal', oldVal)
}
},
// 組件內路由守衛
beforeRouteEnter (to, from, next) {
next(vm => {
console.log('beforeRouteEnter');
});
},
// 此處不能獲取dom,還沒有掛載dom
created () {
},
// 此處自由使用
mounted () {
this.init();
console.log('demo1 this.$route', this.$route);
},
methods: {
clickMethod () {
alert('點擊事件')
},
init () {
console.log('init method run')
},
changeRandowNumber () {
this.randomNumber = Math.random()
},
changeWatchParam () {
this.watchParam = Math.random()
},
toggle () {
this.show = !this.show
},
accept (data1) {
console.log('data1', data1)
}
}
}
</script>
<style scoped>
.image1 {
width: 100px;
height: 100px;
}
</style>
複製代碼
component1.vue
// component1.vue組件
<template>
<div>
<h1>{{text}}</h1>
<button @click="emitMethod">子組件傳遞數據到父組件</button>
</div>
</template>
<script>
export default {
data () {
return {
}
},
props: {
text: {
type: Number,
default: 1
}
},
methods: {
emitMethod () {
this.$emit('data1', '嘿嘿嘿')
}
}
}
</script>
<style scoped>
</style>
複製代碼
單頁面開發依賴前端路由,分如下2種實現方式:
首先, Demo1.vue的template中,應該聲明用來匹配子路由
青蔥,router/index.js, /Demo1匹配Demo1組件; /Demo1/Demo1Child匹配到Demo1Child組件,此時Demo1Child會顯示在Demo1.vue的router-view中
router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import Demo1 from '@/views/demo1/Demo1'
import Demo1Child from '@/views/demo1/Demo1Child'
import Demo2 from '@/views/demo2/Demo2'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
},
{
path: '/Demo1',
name: 'Demo1',
component: Demo1,
children: [
{
path: 'Demo1Child',
name: 'Demo1Child',
component: Demo1Child
}
]
},
{
path: '/Demo2/:id',
name: 'Demo2',
component: Demo2
}
]
})
複製代碼
路由鉤子存在如下三種:
- 全局路由鉤子
- 組件內部路由鉤子
- 路由中的鉤子
Demo1.vue中beforeRouteEnter爲組件內部路由守衛,即進入路由以前觸發的鉤子函數
路由傳參數通常採用如下兩種(HelloWorld.vue中turn1和turn2方法分別對應2中不一樣的方式):
- query,即查詢字符串
- params, 即路由參數
HelloWorld.vue
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<h2>Essential Links</h2>
<button @click="turn1">頁面跳轉query</button>
<button @click="turn2">頁面跳轉params</button>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
},
methods: {
turn1 () {
// 能夠到Demo1Child.vue的mounted中打印查看this.$route中接收到的參數
this.$router.push({path: '/Demo1/Demo1Child', query: {param1: 123, param2: '哈哈哈'}});
},
turn2 () {
// 能夠到Demo2.vue的mounted中打印查看this.$route中接收到的參數
this.$router.push({path: '/Demo2/123'});
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
複製代碼
vuex是vue提供的狀態管理工具.主要包含如下幾項:
(1) state (狀態)
(2) getters (暴露狀態的訪問)
(3) mutations (提交同步修改state)
(4) actions (異步行爲)
能夠將一個項目的狀態樹,根據項目功能模塊,分模塊管理狀態樹,使得狀態管理結構清晰,使用方便. 具體使用能夠看項目代碼.
vuex目錄以下:
(1) src/store/index.js將store下的modules模塊和root模塊合併管理並導出
(2) src/main.js須要將src/store/index.js引入,並掛載到vue實例上 (3) Demo2.vue中使用如代碼所示,mapGetters應寫在computed下,並聲明模塊home,便可在頁面使用isLogin了; mapMutations和mapActions則應該在methods中聲明,使用如代碼所示,便可在組件內部使用.
src/store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
import root from './root';
import home from './modules/home';
Vue.use(Vuex);
const store = new Vuex.Store({
modules: {
root,
home
}
});
export default store;
複製代碼
src/store/root.js
const state = {};
const getters = {};
const mutations = {};
const actions = {};
export default {
namespaced: true,
state,
getters,
mutations,
actions
}
複製代碼
src/modules/home.js
import api from '../../api/index';
const state = {
isLogin: false
};
const getters = {
isLogin: state => state.isLogin
};
const mutations = {
changeLoginState (state, data) {
state.isLogin = data;
}
};
const actions = {
login (context, params) {
// 可作異步請求
// setTimeout(() => {
// // context.state.isLogin = true;
// context.commit('changeLoginState', true);
// }, 2000);
return new Promise((resolve, reject) => {
api.ajaxGetMethod(params).then(res => {
if (true) {
resolve(res);
} else {
reject(res);
}
});
});
}
};
export default {
namespaced: true,
state,
getters,
mutations,
actions
}
複製代碼
src/main.js
import store from './store'
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>'
})
複製代碼
src/views/demo2/Demo2.vue
<template>
<div>
<h1>Demo2</h1>
<p>{{isLogin}}</p>
<button @click="login()">登錄</button>
</div>
</template>
<script>
import { mapGetters, mapMutations, mapActions } from 'vuex';
export default {
data () {
return {}
},
computed: {
...mapGetters('home', ['isLogin'])
},
methods: {
...mapMutations('home', ['changeLoginState']),
...mapActions('home', ['login']),
// async, await異步調用
async loginMethod () {
try {
let res = await this.login({});
console.log('res', res);
} catch (error) {
console.error('error', error);
}
}
}
}
</script>
<style scoped>
</style>
複製代碼
(1) 建議將請求統一管理,避免項目內部散亂的寫
(2) 建議結合vuex使用,固然也能夠不結合. src/store/modules/home.js中的actions 下的login方法就是結合vuex使用的,能夠在獲得異步請求結果後直接修改狀態
(3) 也能夠將src/api/index.js引入任何組件,調用方法便可發送ajax請求
(4) 使用async,await(完全解決回調地獄問題). 首先src/store/modules/home.js中actions下的login方法返回new Primise; 其次在src/views/demo2/Demo2.vue中loginMethod方法前應寫標緻 async ,調用login前應寫await;最後應使用try...catch捕獲異常
src/api/index.js
import axios from 'axios';
export default {
ajaxGetMethod: params => axios.get('/xx', {params: params}).then(res => res.data),
ajaxPostMethod: body => axios.get('/yy', body).then(res => res.data)
}
複製代碼
src/store/modules/home.js
import api from '../../api/index';
const state = {
isLogin: false
};
const getters = {
isLogin: state => state.isLogin
};
const mutations = {
changeLoginState (state, data) {
state.isLogin = data;
}
};
const actions = {
login (context, params) {
// 可作異步請求
// setTimeout(() => {
// // context.state.isLogin = true;
// context.commit('changeLoginState', true);
// }, 2000);
return new Promise((resolve, reject) => {
api.ajaxGetMethod(params).then(res => {
if (true) {
resolve(res);
} else {
reject(res);
}
});
});
}
};
export default {
namespaced: true,
state,
getters,
mutations,
actions
}
複製代碼
src/views/demo2/Demo2.vue
async loginMethod () {
try {
let res = await this.login({});
console.log('res', res);
} catch (error) {
console.error('error', error);
}
}
複製代碼
2.x 版本: github.com/vuejs/vue-c…
3.x 版本: cli.vuejs.org/zh/
2.x 新建項目: vue init template-name project-name
3.x 新建項目: vue create xxx