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