• Vuejs 渲染页面的过程和原理
    • 渲染过程1. js入口文件
    • 渲染过程2. 静态的HTML页面: index.html
    • 渲染过程3. main.js 中的 Vue定义
    • 原理
    • 不使用router的技术:QQ邮箱

    Vuejs 渲染页面的过程和原理

    只有知道了一个页面是如何被渲染出来的,我们才可以更好的理解框架和调试代码。 下面我们就来仔细看一下这个过程。

    渲染过程1. js入口文件

    最初的最初,我们要知道 ./build/webpack.base.conf.js 这个文件,是webpack打包的主要配置文件. 一个典型的代码如下:

    1. var path = require('path')
    2. var utils = require('./utils')
    3. var config = require('../config')
    4. var vueLoaderConfig = require('./vue-loader.conf')
    5. function resolve (dir) {
    6. return path.join(__dirname, '..', dir)
    7. }
    8. module.exports = {
    9. entry: {
    10. app: './src/main.js'
    11. },
    12. output: {
    13. path: config.build.assetsRoot,
    14. filename: '[name].js',
    15. publicPath: process.env.NODE_ENV === 'production'
    16. ? config.build.assetsPublicPath
    17. : config.dev.assetsPublicPath
    18. },
    19. resolve: {
    20. extensions: ['.js', '.vue', '.json'],
    21. alias: {
    22. 'vue$': 'vue/dist/vue.esm.js',
    23. '@': resolve('src')
    24. }
    25. },
    26. module: {
    27. rules: [
    28. {
    29. test: /\.vue$/,
    30. loader: 'vue-loader',
    31. options: vueLoaderConfig
    32. },
    33. {
    34. test: /\.js$/,
    35. loader: 'babel-loader',
    36. include: [resolve('src'), resolve('test')]
    37. },
    38. {
    39. test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
    40. loader: 'url-loader',
    41. options: {
    42. limit: 10000,
    43. name: utils.assetsPath('img/[name].[hash:7].[ext]')
    44. }
    45. },
    46. {
    47. test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
    48. loader: 'url-loader',
    49. options: {
    50. limit: 10000,
    51. name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
    52. }
    53. }
    54. ]
    55. }
    56. }

    在上面的代码中,

    1. module.exports = {
    2. entry : {
    3. app: './src/main.js' // 这里就定义了Vuejs的入口文件
    4. }
    5. }

    很重要, 其中的 app: './src/main.js' 就定义了Vuejs的入口文件

    知道了这个打包文件,我们就可以知道接下来的事儿了。

    渲染过程2. 静态的HTML页面: index.html

    因为我们每次打开的都是 ‘http://localhost/#/‘, 实际上打开的文件是 ‘http://localhost/#/index.html‘

    所以找到index.html ,可以看到它的内容如下;

    1. <!DOCTYPE html>
    2. <html>
    3. <head>
    4. <meta charset="utf-8">
    5. <title>演示Vue的demo</title>
    6. </head>
    7. <body>
    8. <div id="app"></div>
    9. </body>
    10. </html>

    这里的 <div id="app"></div>, 就是将来会动态变化的内容。特别类似于 Rails的 layout(模板文件).

    这个index.html 文件是最外层的 模板。

    渲染过程3. main.js 中的 Vue定义

    我们回头看 src/main.js, 它的内容如下;

    1. import Vue from 'vue'
    2. import App from './App'
    3. import router from './router'
    4. import VueResource from 'vue-resource';
    5. Vue.use(VueResource);
    6. Vue.config.productionTip = false
    7. Vue.http.options.emulateJSON = true;
    8. new Vue({
    9. el: '#app', // 这里, #app 对应着 <div id=app></div>
    10. router,
    11. template: '<App/>',
    12. components: { App } // 这里, App就是 ./src/App.vue
    13. })

    熟悉 jquery, css selector的同学可以看到, el: '#app' 就是 index.html 中的 <div id= app>

    注意上面的 App.vue, 它会被 main.js 加载, App.vue的内容如下:

    1. <template>
    2. <div id="app">
    3. <router-view class="view"></router-view>
    4. </div>
    5. </template>
    6. <script>
    7. </script>
    8. <style>
    9. </style>

    上面代码中的 <template/>, 这个就是第二层的模板。 可以认为该页面的内容,就是在这个位置被渲染出来的。

    上面的代码中,还有个 <div id = 'app'>...</div>, 这个元素跟index.html中的是同一个元素(暂且这么理解)

    所有的 <router-view>中的内容,都会被自动替换。

    <script> 中的代码则是脚本代码。 至此,整个过程就出来了。

    原理

    Vuejs 就是最典型的Ajax 工作方式: 只渲染部分页面.

    浏览器的页面从来不会整体刷新. 所有的页面变化都限定在 index.html 中的<div id="app"></div>代码中,如下图所示:

    1. <!DOCTYPE html>
    2. <html>
    3. <head>
    4. <meta charset="utf-8">
    5. <title>演示Vue的demo</title>
    6. </head>
    7. <body>
    8. <div id="app"></div> <!-- 都在这一行 -->
    9. </body>
    10. </html>

    所有的动作,可以靠 url来触发, 例如:

    • /#/books_list 对应 某个列表页

    • /#/books/3 对应某个详情页

    这个技术,就是靠 vuejs 的核心组件 vue-router 来实现的。

    不使用router的技术:QQ邮箱

    QQ邮箱是属于: url无法跟某个页面一一对应的项目.

    所有页面的跳转,都无法根据url 来判断

    最大的特点: 无法保存页面的状态, 难以调试, 无法根据url直接进入某个页面。