工做也有一段时间了,平时忙于业务代码的编写中,发现身边的一些人以及本身,对一些基本概念理解有所误差,可能闹出笑话,会问出下面这些常识性错误的奇怪问题:javascript
2333,怎么都是关于Vue的问题。。。我真没黑Vue开发者,不过也能够看出,Vue的小白受众的确比较多。css
博客文章原文html
如今基于Vue,React的SPA单页应用开发,都倾向于采用webpack的模块化构建方案。可能大多数人,开发一个项目,会使用脚手架工具(vue-cli, create-react-app) 咱们本地开发时,运行命令行npm run dev
,而后就开始编写业务逻辑了,对于其中发生了什么,大多数人可能不太关心。其实运行了该命令,就是运行了webpack-dev-server
前端
webpack-dev-server是webpack官方提供的一个小型Express服务器,正是由于webpack-dev-server本身开启了一个服务器,咱们才可以先后端分离开发(咱们不须要关心后端的代码)。前端启动的这个服务器,是用来构建和渲染页面,并提供了自动刷新和热替换功能。vue
简单来讲: webpack只是构建(npm run build
)java
webpack-dev-server除了构建,还提供web服务(npm run dev
)python
什么是路由? 简单来讲:/about/deepred
/home/
这些就是路由react
在web开发中,路由分为前端路由和后台路由 其实在单页应用尚未流行前,路由基本指的是后台路由。若是你熟悉传统的后台web开发,可能对下面的代码很熟悉:webpack
app.get('/about', function (req, res) {
res.render('about', { title: 'Hey', message: 'Hello there!'});
});
app.get('/', function (req, res) {
res.render('index');
});
复制代码
传统的web网站,全部的路由都是由后台定义的。当咱们想访问一个页面http://anata.me/about/
,首先向后台发送一个请求,后台根据定义好的路由,决定渲染哪一个页面。web
然而单页应用的出现,改变了这个模式。若是你是前端开发,应该对这段代码更加熟悉:
routes: [
{
path: '/user/:userId',
name: 'user',
component: User
},
{
path: '/about/',
name: 'about',
component: About
}
]
复制代码
前端路由是将页面的渲染权交给了js控制,不经过请求服务器来判断渲染页面。前端通常利用histroy和hash来控制,达到不刷新页面可使显示内容发生变化,这样速度更快,用户体验更好。前端路由解放了服务端,专心提供接口数据服务。
脚手架生成的项目,通常运行npm run build
以后,会在项目根目录生成一个dist目录,这就是咱们打包好后的静态资源文件。 注意的是:
npm run dev
启动项目。npm run dev
启动的服务器只是为了开发而使用的,真正线上的服务器,是由后台提供的(好比PHP,Java, python, Node...)部署的方式有不少,好比能够把dist文件和后台代码放在一块儿,后台把dist文件当作静态资源读取便可。不过由于采用了前端路由的方案,后台还须要配置一下,以Express举例:
// 访问静态资源文件 这里是访问全部dist目录下的静态资源文件
app.use(express.static(path.resolve(__dirname, '../dist')))
// 由于是单页应用 全部请求都走/dist/index.html
// 这一句要放在全部其余路由的后面
app.get('*', function(req, res) {
const html = fs.readFileSync(path.resolve(__dirname, '../dist/index.html'), 'utf-8')
res.send(html)
})
复制代码
也能够把dist静态文件和后台代码分开,经过Nginx部署
server {
listen 80;
server_name 127.0.0.1;
location / {
root /data/deered/dist; #前端打包后的dist文件位置
try_files $uri $uri/ /index.html; #防止页面刷新404
index index.html;
}
}
复制代码
由于webpack-dev-server启动了一个服务器,因此在开发时,前端去请求真正的后台接口,是存在跨域问题的。webpack提供了跨域的解决方案,原理就是让服务器反向代理请求真正的接口
vue-cli配置跨域
proxyTable: {
'/api': {
target: 'http://localhost:8089/api/',
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
},
复制代码
前端请求/api/xxxx
时,webpack-dev-server启动的服务器会帮咱们请求http://localhost:8089/api/xxxx
,同时返回数据。
有些人就会有疑惑,那打包后的文件,是否是也能跨域。前面咱们说了,线上部署就不是运行npm run dev
,因此,前端是否是跨域要看你怎么部署了。
若是你把打包后的dist文件和后端代码放在一块儿,那么根本就不存在跨域问题! 若是前端静态文件和后端不在一块儿,那么能够用Nginx作转发
server {
listen 80;
server_name 127.0.0.1;
location / {
root /data/deered/dist; #前端打包后的dist文件位置
index index.html;
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://127.0.0.1:8089 #后台地址
}
}
复制代码
Vue的指令和模板语言让开发者能够很简洁的完成一个复杂的功能,而React的JSX语法,则让开发者拥有更多的自主权。 从Vue转向React的开发者,一开始可能会很是不适应,毕竟v-for
v-if
v-model
这些最基本的功能,React居然全都要咱们本身去实现。
咱们其实能够从本质上来看:
一个Vue的组件:
<template>
<div class="hello" @click="say">
<h1>{{ msg }}</h1>
<h2 v-if="show">show me</h2>
</div>
</template>
<script>
export default {
name: 'Hello World',
data () {
return {
msg: 'Welcome to Your Vue.js App',
show: false
}
}
methods: {
say() {
console.log('hi')
}
}
}
</script>
<style scoped>
h1, h2 {
font-weight: normal;
}
</style>
复制代码
一个React的组件
const styles = {
fontWeight: 'normal'
}
export default class Hello extends Component {
constructor(props) {
super(props);
this.state = {
msg: 'Welcome to Your React App',
show: false
};
}
say() {
console.log('hi')
}
render() {
return (
<div class="hello" onClick={this.say}> <h1 className={styles}>{this.state.msg}</h1> {this.state.show ? <h2>show me</h2> : null} </div>
)
}
}
复制代码
从两个组件对比就能看见: React组件彻底就是一个Class类,你一直在写各类类方法,甚至你的css也是个对象,因此React要求开发者有较好的ES6基础,由于你无时无刻不在写JS
而Vue就不同了,Vue组件其实就是个普通的对象,你只是在修改这个对象的属性:name
data
methods
components
,说的通俗点,你根本就是在配置对象,例如:你配置了这个对象的components
属性,因而就能够在模板中使用自定义组件
所以,React本质上是不可能给你提供相似v-for
的API,由于JS已经有了for循环,数组也有map方法,你写React就是在写JS,为啥还须要额外的遍历方法呢?而Vue就不一样了,它提供的指令,其实就是在内部帮你写JS,因此从React转向Vue的开发者,一开始会以为,Vue的代码更简洁了。不过,这是靠牺牲自由度换来的,毕竟在React里,怎么实现遍历,彻底由你本身决定