zoukankan      html  css  js  c++  java
  • vue- Vue-Cli脚手架工具安装 -创建项目-页面开发流程-组件生命周期-03

    本博客环境

    如果这些环境过时了,那就不用浪费时间看这博客了

    Vue-Cli 项目环境搭建

    npm (就类似于手机的应用商城,python 中的 pip 也一样)

    与 python 基础环境对比

    1. node ~ python 解释器

      • node 是 js 的解释器,用 c++ 写的
    2. npm ~ pip python 的库管理工具(第三方模块下载的应用商店)

      • npm 就类似于 pip ,也要换源(常用淘宝源 cnpm),下载才快
    3. vue ~ django

      • 类似于 django 是一个大框架

    环境搭建

    • 安装 node
    node 官网下载安装包,傻瓜式安装:https://nodejs.org/zh-cn/
    

    下面的命令都是在 命令行中 执行-g 参数代表全局(global),会自动配置环境变量)

    • 安装 cnpm (使用淘宝镜像源)

      npm 是 node 自带的包管理器,cnpm 是淘宝镜像源(可以看做是 npm 的国内版本),下载第三模块会比 npm(国外仓库去下)快很多,几乎所有用 npm 的地方都可以用 cnpm 替代

    npm install -g cnpm --registry=https://registry.npm.taobao.org
    
    • 安装脚手架工具 vue/cli
    cnpm install -g @vue/cli
    
    • 清空缓存处理(前两步出错了再执行这个(把那些下载错误的文件删除掉))
    npm cache clean --force
    

    创建启动 vue 项目

    一定要注意当前命令行的目录位置

    可以用 webstorm 来编写 vue 代码, 专门用来开发前端的,pycharm 的提示及便捷性不如它(自行了解)

    命令创建项目(步骤小多)

    先进入到存放项目的目录下

    cd /d E:PyCharm 2019.1.3ProjectFileday010day066 (项目将会放在 day66 这个文件夹下)

    创建项目

    vue create v-proj(项目名) ,输入完后会进入到下面的界面

    界面操作方式:键盘 上下(↑↓)箭头 选择要用那个模板,回车选中(进入下面的界面同样用 上下箭头 移动光标,按空格选取,回车确认)

    我们选择下面这个 Manually select features

    来到下面这个页面,来看看这些选项都啥意思

    各选项

    • Babel
      • 把 ES6 语法转换成 ES5 让浏览器可以解析
    • TypeScript
      • 是 JavaScript 的超集(学起来会比 JavaScript 难一些)
    • Progressive Web App (PWA) Support
      • 有很多优化前台项目的组件(后期再用到)
    • Router
      • vue 前台的路由管理
    • Vuex
      • 相当于一个全局 单例,页面未刷新有效,一刷新就没了
    • CSS Pre-processors
      • less、sass --> 预编译语言,写的也是 css,但它可以写逻辑,必须浏览器解析成原生 css 才有用,相对来说 less 会好学一点,两个小时左右就能学会了
    • Linter / Formatter
      • 限制(团队)代码风格(缩进空格个数之类的) ESLint 更严格
    • Unit Testing
      • 测试用的
    • E2E Testing
      • 测试用的

    我们选择下面的这几个(空格选取)

    回车下一步(再一路选大写的就行)

    history 让 vue 的当页面应用可以至此跳转(其他的暂时默认即可)

    默认配置如下

    然后就会自动进行安装

    至此,vue 项目创建完成

    启动 vue 项目(命令行方式)

    在命令行下,进入项目根目录,执行 npm run serve 启动项目

    等待加载后,出现下面的页面即可在浏览器上输入 localhost:8080 访问(vue 项目默认端口是 8080)

    在浏览器上访问

    启动 vue 项目(pycharm 方式)

    命令行方式启动有着诸多不便,所以我们还是选择采用 pycharm 来启动吧(其实 webstorm 对 vue 的支持会更好,但不是这里的重点),下面是 pycharm 启动需要做的一些配置

    先右键项目文件夹,用 pycharm 打开

    配置 pycharm 启动

    用 pycharm 的绿色的启动按钮启动 vue 项目

    页面效果(至此,pycharm 即可启动项目)

    Vue 项目目录结构分析

    ├── v-proj
    |	├── node_modules  	// 当前项目所有依赖,一般不可以移植给其他电脑环境(版本控制、备份代码 等等,这个文件一般都排除在外),在新环境下执行 cnpm install 即可重新安装下载这个文件里的内容
    |	├── public			
    |	|	├── favicon.ico	// 浏览器标签页图标(public/index.html 中的 <link rel="icon" href="<%= BASE_URL %>favicon.ico">)
    |	|	└── index.html	// 当前项目唯一的页面
    |	├── src
    |	|	├── assets		// 用来存放静态资源,如:img、css、js
    |	|	├── components	// 存放小组件(再老一些的版本 components 和 views 是一个文件夹)
    |	|	├── views		// 存放页面组件(一般是路由跳转的组件)
    |	|	├── App.vue		// 根组件
    |	|	├── main.js		// 全局脚本文件(项目的入口)
    |	|	├── router.js	// 路由脚本文件(配置路由 url链接 与 页面组件的映射关系)
    |	|	└── store.js	// 仓库脚本文件(vuex插件的配置文件,数据仓库)
    |	├── README.md
    └	└── **配置文件...
    
    // "├" 输入法 "v9" 可以找到这个符号
    

    pycharm 支持 vue 语法

    安装 vue 插件

    双击 App.vue 可以看到,没有任何语法高亮,.vue 文件被识别成了普通文件,那么我们可以通过安装 vue 插件来解决这个问题

    可以点图中的 install plugins 来安装 vue 插件(按提示安装即可)

    也可以在 pycharm 的 settings 里下载,下载完成重启 pycharm 即可

    重启 pycharm 后, pycharm 就能识别 .vue 文件了,并且能够为我们提供语法高亮(眼前又瞬间充满了色彩)

    部分 vue 文件剖析

    自定义组件并渲染到页面上

    组件文件放在 components 下面,通常首字母大写

    组件通常由以下三部分组成

    1. template
      • 里面有且只有一个根标签
    2. script
      • 必须将 {} 导出(导出了外界才能导入) export default
      • 外界导入时,将 {} 赋值给前面的变量(进行关联)
    3. style
      • style 标签必须明确 scoped 属性,代表该样式只在组件内部起作用(样式的组件化)

    组件的导入与导出

    写代码的时候有些地方红色波浪线可能是 ESLint 报错,某个变量未被使用就会这样,接着写下去就好,不要太紧张

    将组件导出(暴露出来)

    组件需要将 实例?(内容丰富了长得很像 vue 实例)导出,外界才能使用

    src/components/Test.vue

    <template>
    <!--    template 里只能有一个根标签(作为一个组件)-->
        <div class="test">
            <p>Test 组件</p>
        </div>
    </template>
    
    <script>
        // 需要将其导出,外界才能导入,这个括号相当于一个 vue 实例
        export default {
            name: "Test"
        }
    </script>
    
    <style scoped>
        /* style 里面的这个 scoped 可以用来限制样式的控制范围(仅对这个组件生效)(让样式局部化,避免造成 css 冲突)*/
        p {
            color: red
        }
    </style>
    

    父级组件导入(暴露出来的)组件

    src/views/TestViews.vue

    <template>
        <div class="home">
            <!-- 3. 直接在页面上渲染自定义标签(在 .vue 结尾的文件中标签可以区分大小写(不像 html 文件,不能区分标签的大小写))-->
            <T></T>  <!-- 到时候子组件会直接把这个替换掉 -->
        </div>
    </template>
    
    <script>
        // 1. 将组件导入,并赋值给 T (把子组件 export default 那个实例? 跟 变量T ? 关联起来,在本(父)组件中就可以直接用 T 来当 Test 组件操作了)
        import T from '@/components/Test'
        // 这个 @ 就等价于 src 文件夹的绝对路径
    
        export default {
            // 2.注册组件
            components: {
                T, // 注册 T 组件
            }
        }
    </script>
    

    在 routers.js 里配置路由

    src/router.js

    没有 history 地址栏就会有 # 标识(localhost:8080/#/路由

    import Vue from 'vue'
    import Router from 'vue-router'
    import Home from './views/Home.vue'
    // ****** 1. 先导入 ******
    import Test from './views/TestViews'
    
    Vue.use(Router)
    
    export default new Router({
      mode: 'history',  // 让 vue 这种单页面应用也支持 浏览器的前进后退(← →) (可以展开搜索下)
      base: process.env.BASE_URL,
      routes: [
        {
          path: '/',
          name: 'home',
          component: Home
        },
        {
          path: '/about',
          name: 'about',
          // route level code-splitting
          // this generates a separate chunk (about.[hash].js) for this route
          // which is lazy-loaded when the route is visited.
          component: () => import(/* webpackChunkName: "about" */ './views/About.vue')
        },
        // ****** 2. 注册一条路由 ******
        {
          path: '/test',  // ****** 3. 一会儿直接访问这个路由即可 localhost:8080/test ******
          name: 'test',
          component: Test
        }
      ]
    })
    
    

    浏览器访问

    localhost:8080/test

    为什么页面上会有 Home | About 呢?我们刚刚又没写

    为什么页面上会有 Home | About 呢? - 其实是根组件 App.vue 里面写了

    src/App.vue (看里面的 Home、| 、 About)

    <template>
      <div id="app">
        <div id="nav">
          <router-link to="/">Home</router-link> |
          <router-link to="/about">About</router-link>
        </div>
        <router-view/>
      </div>
    </template>
    
    <style>
    #app {
      font-family: 'Avenir', Helvetica, Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      text-align: center;
      color: #2c3e50;
    }
    #nav {
      padding: 30px;
    }
    
    #nav a {
      font-weight: bold;
      color: #2c3e50;
    }
    
    #nav a.router-link-exact-active {
      color: #42b983;
    }
    </style>
    
    

    全局脚本文件 main.js 解析(项目入口)

    一般导入的时候会省略后缀,所以 同一文件夹下面尽量不要重名(导入可以忽略后缀)

    默认写法(创建 vue 项目自动生成的)

    import Vue from 'vue'
    import App from './App.vue'
    import router from './router'
    import store from './store'
    
    // 新手教程的 使用提示 (要点 next next 的动画)
    Vue.config.productionTip = false
    
    new Vue({
        router,
        store,
        render: h => h(App)
    }).$mount('#app')  // 等同于 el 挂载
    
    

    解释性写法 我们比较能理解的写法(只是相当于对上面的解释)

    import Vue from 'vue'  // 加载vue环境
    import App from './App.vue'  // 加载根组件
    import router from './router'  // 加载路由环境
    import store from './store'  // 加载数据仓库环境
    
    Vue.config.productionTip = false
    
    new Vue({
        el: '#app',
        router,
        store,
        render: function (readFn) {
            return readFn(App);
        },
    });
    
    

    vue 项目启动生命周期

    加载 mian.js 启动项目

    • import Vue from 'vue' 为项目加载vue环境
    • import App from './App.vue' 加载根组件用于渲染替换挂载点
    • import router from './router' 加载路由脚本文件,进入路由相关配置

    加载 router.js 文件

    为项目提供路由服务,并加载已配置的路由(链接与页面组件的映射关系)

    注:不管当前渲染的是什么路由,页面渲染的一定是根组件,链接匹配到的页面组件只是替换根组件中的 <router-view></router-view>

    监测路由变化来做处理

    vue 发生页面跳转的原理

    如果请求链接改变(路由改变),router 里匹配到了,会把路由对应的 组件 拿出来,然后把根组件里的 <router-view></router-view> 标签替换成 该组件

    • 每次路由跳转都会走一次组件的生命周期

    参与文件

    main.js 入口文件

    该文件内容不变

    import Vue from 'vue'
    import App from './App.vue'
    import router from './router'
    import store from './store'
    
    Vue.config.productionTip = false
    
    new Vue({
        router,
        store,
        render: h => h(App)
    }).$mount('#app')
    
    

    App.vue 项目根组件

    常见项目的根组件( App.vue)都只写下面这几行代码

    <template>
        <div id="app">
            <!-- url路径会加载不同的页面组件
                eg:/red => RegPage  | /blue => BluePage
             来替换router-view标签,完成页面的切换
             -->
            <router-view></router-view>
        </div>
    </template>
    

    views/RedPage.vue 自定义页面组件

    <template>
        <div class="red-page">
            
        </div>
    </template>
    <script>
        
        export default {
            name: "RedPage",
            components: {
                
            },
        }
    </script>
    <style scoped>
        .red-page {
             100vw;
            height: 100vh;
            background-color: red;
        }
    </style>
    

    views/BluePage.vue

    <template>
        <div class="blue-page">
            
        </div>
    </template>
    <script>
        
        export default {
            name: "BluePage",
            components: {
                
            }
        }
    </script>
    <style scoped>
        .blue-page {
             100vw;
            height: 100vh;
            background-color: blue;
        }
    </style>
    

    router.js 路由文件

    import Vue from 'vue'
    import Router from 'vue-router'
    import Home from './views/Home.vue'
    import RedPage from "./views/RedPage";
    import BluePage from "./views/BluePage";
    
    Vue.use(Router);
    
    export default new Router({
        mode: 'history',
        base: process.env.BASE_URL,
        routes: [
            {
                path: '/',
                name: 'home',
                component: Home
            },
            {
                path: '/red',
                name: 'red',
                component: RedPage
            },
            {
                path: '/blue',
                name: 'blue',
                component: BluePage
            }
        ]
    })
    
    

    全局样式文件配置与应用

    jQuery、BootStrap 这些外部环境,都需要在 main.js 里配

    后期可能把路径配置这些写成一个配置文件

    assets/css/global.css

    /*html, body, h1, h2, ul, p {*/
    *{
        margin: 0;
        padding: 0;
    }
    ul {
        list-style: none;
    }
    a {
        color: black;
        text-decoration: none;
    }
    

    main.js 中导入,让它生效

    import Vue from 'vue'
    import App from './App.vue'
    import router from './router'
    import store from './store'
    
    Vue.config.productionTip = false;
    
    // ********* 配置全局样式 *********
    import '@/assets/css/global.css'
    
    
    // new Vue({
    //     router,
    //     store,
    //     render: h => h(App)
    // }).$mount("#app");
    
    new Vue({
        el: '#app',
        router,
        store,
        render: function (readFn) {
            return readFn(App);
        },
    });
    
    

    小案例 - 封装 Nav 导航栏组件

    components/Nav.vue 新建子组件

    采用 a 标签会发生页面跳转刷新,重新加载了一次项目界面

    --> 而 vue 是单页面应用,通常采用 <router-link to="/路由"> </router-link> 处理跳转

    • 每次路由跳转都会走一次组件的生命周期
    <template>
        <div class="nav">
            <!--采用 vue-router 完成页面跳转,不能采用 a 标签(会发生页面刷新,本质就是重新加载了一次项目界面)-->
            <ul>
                <li>
                    <!--<a href="/">主页</a>-->
                    <router-link to="/">主页</router-link>
                </li>
                <li>
                    <router-link to="/red">红页</router-link>
                </li>
                <li>
                    <router-link to="/blue">蓝页</router-link>
                </li>
            </ul>
        </div>
    </template>
    
    <script>
        export default {
            name: "Nav",
        }
    </script>
    
    <style scoped>
        .nav {
             100%;
            height: 60px;
            background-color: orange;
        }
        .nav li {
            float: left;
            font: normal 20px/60px '微软雅黑';
            padding: 0 30px;
        }
        .nav li:hover {
            cursor: pointer;
            background-color: aquamarine;
        }
        .nav li.active {
            cursor: pointer;
            background-color: aquamarine;
        }
    </style>
    

    views/HomePage.vue 新建视图页面

    RedPage.vue与BluePage都是添加下方三个步骤代码

    <template>
        <div class="home">
            <!-- 3)使用Nav组件 -->
            <Nav></Nav>
        </div>
    </template>
    
    <script>
        // 1)导入Nav组件
        import Nav from '@/components/Nav'
        export default {
            // 2)注册Nav组件
            components: {
                Nav,
            }
        }
    </script>
    
    

    新增页面三步骤

    1. 在views文件夹中创建视图组件(.vue 文件)
    2. 在router.js文件中配置路由
    3. 设置路由跳转,在指定路由下渲染该页面组件(替换根组件中的router-view标签)
      • 渲染谁,(router-view)就替换成谁

    案例

    增加一个 tan 页面 案例代码

    views/TanPage.vue

    <template>
        <div class="tan-page">
            <Nav></Nav>
        </div>
    </template>
    
    <script>
        import Nav from '@/components/Nav'
        export default {
            name: "TanPage",
            components: {
                Nav
            }
        }
    </script>
    
    <style scoped>
        .tan-page {
             100vw;
            height: 100vh;
            background-color: tan;
        }
    </style>
    

    router.js

    // ...
    import TanPage from "./views/TanPage";
    export default new Router({
        mode: 'history',
        base: process.env.BASE_URL,
        routes: [
            // ...
            {
                path: '/tan',
                name: 'tan',
                component: TanPage
            }
        ]
    })
    

    components/Nav.vue

    ...
    <li>
        <router-link to="/tan">土页</router-link>
    </li>
    ...
    

    组件生命周期(钩子函数剖析)*****

    基本概念

    详细的可以看 vue 官方 API (推荐好好看看官方文档这块的介绍)

    组件的生命周期:一个组件从创建到销毁的过程,就称之为组件的生命周期

    组件创建到销毁的过程中,会出现众多关键的时间节点,如:

    • 组件要创建了
    • 组件创建完毕了
    • 组件数据渲染完毕了
    • 组件要被销毁了
    • 组件销毁完毕了
    • ...等等 时间节点

    每一个时间节点,vue 都为其提供了一个回调函数(在该组件到达该时间节点时,就会触发对应的回调函数,在函数中就可以完成该节点需要完成的业务逻辑

    生命周期钩子函数也是 vue 的实例成员

    生命周期钩子函数

    vue 官方提供的生命周期钩子函数

    beforeCreate
    created
    beforeMount
    mounted
    beforeUpdate
    updated
    activated
    deactivated
    beforeDestroy
    destroyed
    errorCaptured
    

    在 vue 组件的 script 的 export default 导出字典中直接写钩子函数

    重点钩子函数:created(其他函数根据需求来用)

    一般该组件请求后台的数据,都是在该钩子中完成

    1. 请求来的数据可以给页面变量进行赋值(此时实例成员已经加载了)
    2. 该节点还只停留在虚拟 DOM 范畴,如果数据还需要做二次修改再渲染到页面
    3. 可以在 beforeMount、mounted 钩子中添加逻辑处理
    export default {
        // ...
        beforeCreate() {
            console.log('组件创建了,但数据和方法还未提供');
            // console.log(this.$data);
            // console.log(this.$options.methods);
            console.log(this.title);
            console.log(this.alterTitle);
        },
        // 该钩子需要掌握,一般该组件请求后台的数据,都是在该钩子中完成
        // 1)请求来的数据可以给页面变量进行赋值
        // 2)该节点还只停留在虚拟 DOM 范畴,如果数据还需要做二次修改再渲染到页面,
        //  可以在beforeMount、mounted钩子中添加逻辑处理
        created() {
            console.log('组件创建了,数据和方法已提供');
            // console.log(this.$data);
            // console.log(this.$options.methods);
            console.log(this.title);
            console.log(this.alterTitle);
            console.log(this.$options.name);
        },
        destroyed() {
            console.log('组件销毁完毕')
        }
    }
    
    • this.$options 可以拿到所有实例成员,包括自定义成员(好像会让 vue 提前加载实例成员这些),一堆的属性这些都在里面(可以用它来取自定义属性)

    • vue 实例可以直接 this.属性/方法 取到 实例成员 data、methods 的内容(做了封装,可以直接拿到)

    • vue 没有 this.$method 这个成员属性

    根据请求路径高亮路由标签案例

    <router-link to="/">主页</router-link>

    • router-link 最终会被解析为 a 标签,用 to 完成指定路径跳转,但是不能添加系统事件(因为是组件标签)
    • 在 js 方法中可以用 this.$router.push('路径') 完成 逻辑跳转
    • 在 js 方法中可以用 this.$route.path 拿到当前请求的页面路由

    components/Nav.vue

    this.$route、this.$router 可以好好了解一下(搜一下),一个管理路由数据,一个管理路由跳转

    <template>
        <div class="nav">
            <!--采用vue-router完成页面跳转,不能采用a标签(会发生页面刷新,本质就是重新加载了一次项目界面)-->
            <ul>
                <li @click="changePage('/')" :class="{active: currentPage === '/'}">
                    <!--<a href="/">主页</a>-->
                    <!--<router-link to="/">主页</router-link>-->
                    主页
                </li>
                <li @click="changePage('/red')" :class="{active: currentPage === '/red'}">
                    <!--<router-link to="/red">红页</router-link>-->
                    红页
                </li>
                <li @click="changePage('/blue')" :class="{active: currentPage === '/blue'}">
                    <!--<router-link to="/blue">蓝页</router-link>-->
                    蓝页
                </li>
                <li @click="changePage('/tan')" :class="{active: currentPage === '/tan'}">
                    <!--<router-link to="/tan">土页</router-link>-->
                    土页
                </li>
            </ul>
        </div>
    </template>
    
    <script>
        export default {
            name: "Nav",
            data() {
                return {
                    // 每渲染一个页面,都会出现加载 Nav 组件,currentPage 就会被重置,
                    // 1)在点击跳转事件中,将跳转的页面用 数据库 保存,在钩子函数中对 currentPage 进行数据更新
                    // currentPage: localStorage.currentPage ? localStorage.currentPage: ''
                    // 2)直接在 created 钩子函数中,获取当前的 url 路径,根据路径更新 currentPage
                    currentPage: ''
                }
            },
            methods: {
                changePage(page) {
                    // console.log(page);
                    // 当 Nav 出现渲染,该语句就无意义,因为在 data 中将 currentPage 重置为空
                    // this.currentPage = page;
    
                    // 有 bug,用户不通过点击,直接修改请求路径完成页面跳转,数据库就不会更新数据
                    // localStorage.currentPage = page;
    
                    // 任何一个标签的事件中,都可以通过 router 完成逻辑条件
                    // console.log(this.$route);  // 管理路由数据
                    // console.log(this.$router);  // 管理路由跳转
                    this.$router.push(page);  // 路由的逻辑跳转
                }
            },
            // 当前组件加载成功,要根据当前实际所在的路径,判断单选激活标签
            created() {
                // console.log(this.$route.path);
                this.currentPage = this.$route.path;
            }
        }
    </script>
    
    <style scoped>
        .nav {
             100%;
            height: 60px;
            background-color: orange;
        }
        .nav li {
            float: left;
            font: normal 20px/60px '微软雅黑';
            padding: 0 30px;
        }
        .nav li:hover {
            cursor: pointer;
            background-color: aquamarine;
        }
        .nav li.active {
            cursor: pointer;
            background-color: aquamarine;
        }
    </style>
    

    vue 官方提供的组件生命周期图

  • 相关阅读:
    MVC把表格导出到Excel
    MVC借助Masonry实现图文瀑布流
    MVC Ajax Helper或jQuery异步方式加载部分视图
    MVC使用Entity Framework Code First,用漂亮表格显示1对多关系
    MVC使用jQuery从视图向控制器传递Model的2种方法
    MVC使用AdditionalMetadata为Model属性添加额外信息
    MVC日期格式化的2种方式
    MVC使用百度开源文本编辑器UEditor实现图文并茂,字数限制,上传图片或涂鸦
    MVC使用StructureMap实现依赖注入Dependency Injection
    通过扩展jQuery UI Widget Factory实现手动调整Accordion高度
  • 原文地址:https://www.cnblogs.com/suwanbin/p/11651567.html
Copyright © 2011-2022 走看看