Vue生命周期&脚手架工程&Element-UI

一 Vue2.x生命周期

每个vue实例再被创建时都要经过一系列的初始化过程:
创建实例
装载模板
渲染模板等等
vue为生命周期中的每个状态都设置了钩子函数(监听函数)。每个vue实例处于不同的生命周期时,对应的函数就会触发调用
https://www.cnblogs.com/L-xmin/p/13031773.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

<div id="app">
    <span id="num">{{num}}</span>
    <button @click="num++">点赞</button><br>
    {{name}},有{{num}}个点赞!
</div>

</head>
<body>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        let vm=new Vue({
            el:"#app",
            data:{
                name:"张三",
                num:1
            },
            methods:{
                show(){
                    return this.name
                }
            },
            // 第一个生命周期函数,组件的data,methods,DOM结构都还没有初始化
            beforeCreate() {
                console.log("=========beforeCreate=============");
                console.log("数据模型未加载: "+this.name,this.num); //undefined
                console.log("方法未加载: "+this.show());
                console.log("html模板未渲染: "+document.getElementById("num").innerText);
            },
            // 第二个生命周期函数,组件的data,methods已经可以访问到,但html模板尚未渲染,该函数中我们通常发送ajax请求
            created(){
                console.log("=========created=============");
                console.log("数据模型已加载: "+this.name,this.num); //undefined
                console.log("方法已加载: "+this.show());
                console.log("html模板已加载:" + document.getElementById("num"));
                console.log("html模板未渲染: "+document.getElementById("num").innerText);
            },
            // 第三个生命周期函数,模板结构已经在内存中编译完成,但还没有渲染到页面上,仍然无法获得模板中的内容,页面看到的还是一个插值表达式
            beforeMount() {
                console.log("=========beforeMount=============");
                console.log("html模板未渲染: "+document.getElementById("num").innerText);
            },
            // 组件创建阶段的最后一个生命周期函数,页面真正被渲染了,用户能看到真实页面数据
            mounted() {
                console.log("=========mounted=============");
                console.log("html模板已渲染: "+document.getElementById("num").innerText);
            },

            //更新部分的生命周期
            beforeUpdate() {
                console.log("=========beforeUpdate=============");
                console.log("数据模型已更新:"+this.num);
                console.log("html模板未更新:"+document.getElementById("num").innerText);
            },
            updated() {
                console.log("=========updated=============");
                console.log("数据模型已更新:"+this.num);
                console.log("html模板已更新:"+document.getElementById("num").innerText);
            },

        })
    </script>    
</body>
</html>

创建部分的生命周期

beforeCreate

此时,组件的data和methods以及页面DOM结构都还没有初始化

created

此时,组件的data和methods可用。但页面还没被渲染出来,在该函数中,我们经常会发起ajax请求

beforeMount

此时,模板结构已经在内存中编译完成,但还没有真正渲染到页面上。页面上看不到真实的数据,能看到的只是一个模板而已,仍然无法获得模板中的内容,仍然是一个插值表达式

mounted

组件创建阶段的最后一个生命周期。此时,页面已经真正渲染好了,用户可以看到真实页面数据。


以上执行完,组件就离开了创建阶段,进入运行阶段。如果用到了一些第三方UI插件,必须在mounted中来初始化插件。

运行中的生命周期函数,会根据data数据的变化有选择性的触发0次或n次

更新部分的生命周期

以后当每点一次赞,num就会变化,就会触发下面的两个钩子函数

beforeUpdate

此时数据是最新的,但页面上呈现的数据还是旧的

updated

页面已经完成了更新,此时data数据是最新的,同时页面上呈现的数据也是最新的

beforeDestroy

执行该函数的时候,组件即将被销毁但还没有真正销毁,此时组件(data、methods等数据或方法)还可以正常用。

destroyed

组件完成销毁,组件废了

二 使用Vue脚手架进行模块化开发

我们实际在使用vue开发项目的时候,大多使用其模块化的开发环境。我们去做一个后台管理系统,也是通过其模块化的开发环境搭建了一个单页应用,我们会发现项目中实际上只有一个html页面(index.html),其他所有的功能都是通过编写vue相关的组件(.vue结尾的文件),来完成最后的功能

2.1 搭建模块化环境测试

  1. 全局安装webpack,webpack是一个项目打包工具。-g是指全局安装
    npm install webpack -g
  2. 全局安装vue脚手架
    npm install -g @vue/cli-init
  3. 初始化vue项目。vue脚手架使用webpack模块初始化一个appname项目
    vue init webpack appname
    桌面创建项目文件夹名称,如vue-demo,然后进入该文件夹,在文件路径地址上输入cmd,回车就可以在当前目录中打开cmd窗口,在当前目录执行上面的命令
    初始化的时候有几项配置
    项目名称,项目描述,作者,vue构建版本(使用standalone),安装vue-router,不适用eslint,不使用单元测试,不安装e2e tests,选择npm为包管理工具

如果出现vue不是内部或者外部命令等错误,使用cnpm或者配置npm路径环境变量

npm config list

然后打开上面的地址,查看是否有vue.cmd

如果一直处于downloading template然后最后超时报错如下:

是因为github被墙了,无法访问,解决方法:https://www.cnblogs.com/liufqiang/p/13697531.html,按照要求更改后可以正常初始化

  1. 启动vue项目

上一步构建完后,再cd进入下一层目录(vue-demo目录下还有一层vue-demo,需要进入第二层实际项目路径),执行如下的命令来运行脚手架工程
npm run dev
项目的package.json中有scripts,代表我们能运行的命令

2.2 vue脚手架工程目录介绍

在 vscode中打开vue-demo项目,可以看到如下目录

目录/文件 作用 图片
build 与打包工具webpack有关的代码
config 主要是一些配置信息,如项目访问端口号
node_modules 使用npm install 给项目安装的所有依赖
src 这里是我们要开发的目录,基本上要做的事情都在这个目录里
static 静态资源文件,如图片,字体
index.html 首页内容,只有一个id为app的div
package.json npm安装的依赖包的信息,我们每安装一个依赖,在package.json中都会有devDependencies依赖声明,包括它在哪里下载,它的版本号是多少,都有

src里面包含了几个目录及文件:

  • assets: 放置一些图片,如logo等
  • components: 目录里面放了一个组件文件,可以不用
  • App.vue: 项目入口文件,我们也可以直接将组件写这里,而不使用 components 目录
  • main.js: 项目的核心文件

总结:一句话,开发期间关注src里面的代码以及src里面编写相应的功能

2.3 vue脚手架项目运行流程

  • index.html
    声明简单的id为 app 的div给 vue 挂载
  • src下的main.js主程序
    主程序中引入了 vue、App 和 router 模块, 创建了一个 Vue实例,并把 App.vue 模板的内容挂载到 index.html 的 id 为 app 的 div 标签下, 并绑定了一个路由配置
  • App.vue
    上面 main.js 把 App.vue 模板的内容,放置在了 index.html 的 div 标签下面。查看 App.vue 的内容我们看到,这个页面的内容由一个 logo 和一个待放置内容的 router-view,router-view 的内容将由 router 配置决定
  • router下的index.js
    查看 route 目录下的 index.js,我们发现这里配置了一个路由, 在访问路径 / 的时候, 会把 HelloWorld 模板的内容放置到上面的 router-view中

如果我们自定义了一个Hello路由,那么我们访问/hello的时候,会把Hello 模板的内容放置到上面的router-view中,即:如果不需要首页a标签跳转,只是输入地址访问的话,直接改路由即可

关于APP.vue文件:可以发现内容分为3个部分,

  • template(模板,页面要显示成什么),
  • script(vue实例的methods,data等),
  • style(当前template的样式)。这是一个标准的vue单文件组件
    https://cn.vuejs.org/v2/guide/single-file-components.html
    模块化开发的时候,我们会写大量的.vue的单模块组件,格式就是上面的3个部分

    上面的router-view是路由视图的意思,意思是当前页面上面显示的是图片,下面显示什么,要根据我们访问路径动态决定。默认是/*/(url哈希的访问方式) ,所以这个是一个动态的视图,* 后的/是默认要显示的视图

访问/的定义在route目录的index.js中,访问/,会使用我们名称为HelloWorld的组件,而Helloworld组件从哪来,我们从下图可以看到也是从外面导入的

导入Helloworld的from后面有个@符号,@符号代表当前src整个目录的根目录,然后从src下面的components下找HelloWorld.vue

如果我们想自己编写一个Hello.vue组件,来访问,我们同样在components目录下编写Hello.vue,编写3要素,template,script,style

<template>
    <div>
        <h1>你好啊,hello,{{name}}</h1>
    </div>
</template>
<script>
// 导出vue实例,推荐data写函数的方式,return 一个对象,对象有个name值
export default {
    data(){
        return {
            name:"周杰伦"
        }
    }
}
</script>
<style></style>

组件写好以后,要想使用,而且是路径/hello使用,那么接下来我们需要编写路由,在main.js中,我们可以看到导入的路由都在router目录下,因此我们在router目录下的index.js中添加一个路由path指向访问地址,name是访问path的地址,要展示哪个组件,使用之前都得先导入

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import Hello from '@/components/Hello'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    },
    {
      path:'/hello', 
      name:'Hello',
      component:Hello
    }
  ]
})

然后保存,我们访问/hello路径

然后我们再访问/,会发现又变回了helloworld组件,而我们可以发现上面的图片不变,原因就是因为访问不同的组件只会改变路由视图的部分,不会改变路由视图上面的图片

我们如果想点击一个超链接就去我们的hello组件,那么需要在App.vue中修改如下

app.vue只有路由视图可以变,上面的图片是不会变的

三 使用Vue整合element-ui

element-ui是一个使用比较广泛的vue组件库,帮我们抽取了常用的如单选框,输入框,按钮之类的各种组件,可以简化我们的开发

3.1 npm安装与引入

  1. 安装elementUI:i是install的简写 npm i element-ui
  2. 安装完后,在我们vue-demo项目的package.json中的依赖列表会列出刚刚安装的element-ui,可以看到是2.15.6版本

然后,我们在main.js主程序中将element-ui组件以及它的css样式导入
因为我们引入了,所以我们可以直接导入,类似于java中pom文件添加完依赖,就可以直接import进去
最后我们需要让vue使用我们的element-ui组件,添加一行代码Vue.use

未来我们需要用到其他组件库,也是在main.js中采用上述方法导入使用

3.2 使用element-ui组件

3.2.1 简单引入

我们在我们之前编写的Hello.vue组件中使用Elementui,添加一个单选框,单选框组件代码复制下面链接的文档 https://element.eleme.cn/#/zh-CN/component/installation

el-radio其实本质上就是elementUI抽取的组件,之前不是学过组件化么,等于以前我们要自己做很多设定,现在elementUI帮我们做好了

要使用 Radio 组件,只需要设置v-model绑定变量,选中意味着变量的值为相应 Radio label属性的值,label可以是String、Number或Boolean。

如上文档所示,我们修改Hello.vue组件内容,添加单选框,label就是单选框的value值,通过data中设置radio值来默认让某个选中

// 0. 如果使用模块化机制编程,导入 Vue 和 VueRouter,要调用 Vue.use(VueRouter)

// 1. 定义(路由)组件。
// 可以从其他文件 import 进来
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }

// 2. 定义路由
// 每个路由应该映射一个组件。 其中"component" 可以是
// 通过 Vue.extend() 创建的组件构造器,
// 或者,只是一个组件配置对象。
// 我们晚点再讨论嵌套路由。
const routes = [
    { path: '/foo', component: Foo },
    { path: '/bar', component: Bar }
]

// 3. 创建 router 实例,然后传 `routes` 配置
// 你还可以传别的配置参数, 不过先这么简单着吧。
const router = new VueRouter({
    routes // (缩写)相当于 routes: routes
})

// 4. 创建和挂载根实例。
// 记得要通过 router 配置参数注入路由,
// 从而让整个应用都有路由功能
const app = new Vue({
    router
}).$mount('#app')

// 现在,应用已经启动了!

3.2 简单后台管理界面

https://element.eleme.cn/#/zh-CN/component/container
在elementui官方文档的基本组件中选择container布局容器,elementui帮我们写好了常见的几个页面布局,我们使用如下的布局,分左右上三部分

复制template部分代码到App.vue里面,因为页面一进来就是index.html页面,是一个id为app的div,在main.js中配置了在这个div里面加载App.vue组件,相当于一进来就展示的是App.vue的template部分,因此我们将App.vue的template部分完全替换

然后将scripts部分的代码和style部分的代码复制并覆盖之前的App.vue的script和style中的代码

data就是v-bind:data的缩写,也就是它绑定了一个自定义属性data,这个data的值关联export default {data}中的data,这个data函数,返回了一个对象,对象中有个属性tableData数组
然后每一列el-table-column使用prop指定取出数组中每一个对象的哪个元素的值作为显示,label就是表头显示的字

当el-table元素中注入data对象数组后,在el-table-column中用prop属性来对应对象中的键名即可填入数据,用label属性来定义表格的列名。可以使用width属性来定义列宽

修改完后,再次访问,发现效果如下:

我们下面去实现点击左侧的选项1,右边显示默认给的用户列表,点击选项2,右边显示hello组件的内容

通过修改el-main标签,el-main就是右边的内容区,是需要根据路径的不同显示不同的内容,因此我们需要将它抽取出来。首先注释掉表格部分内容,然后改为如下

然后将表格部分内容抽取为一个组件,叫做MyTable组件,MyTable.vue文件

后来我们要经常编写vue组件,自己每次都写template,script,style这3部分太麻烦了,可以快捷的让vscode给我们生成这样一个模板

很简单:创建vue对应的代码片段,可以帮我们快速的生成vue模板
vue.json
文件–首选项–用户代码片段–新建代码片段–取名vue.json

// https://www.cnblogs.com/songjilong/p/12635448.html
{
    "Print to console": {
        "prefix": "vue",
        "body": [
            "<!-- $1 -->",
            "<template>",
            "<div class='$2'>$5</div>",
            "</template>",
            "",
            "<script>",
            "//这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)",
            "//例如:import 《组件名称》 from '《组件路径》';",
            "",
            "export default {",
            "//import引入的组件需要注入到对象中才能使用",
            "components: {},",
            "data() {",
            "//这里存放数据",
            "return {",
            "",
            "};",
            "},",
            "//监听属性 类似于data概念",
            "computed: {},",
            "//监控data中的数据变化",
            "watch: {},",
            "//方法集合",
            "methods: {",
            "",
            "},",
            "//生命周期 - 创建完成(可以访问当前this实例)",
            "created() {",
            "",
            "},",
            "//生命周期 - 挂载完成(可以访问DOM元素)",
            "mounted() {",
            "",
            "},",
            "beforeCreate() {}, //生命周期 - 创建之前",
            "beforeMount() {}, //生命周期 - 挂载之前",
            "beforeUpdate() {}, //生命周期 - 更新之前",
            "updated() {}, //生命周期 - 更新之后",
            "beforeDestroy() {}, //生命周期 - 销毁之前",
            "destroyed() {}, //生命周期 - 销毁完成",
            "activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发",
            "}",
            "</script>",
            "<style scoped>",
       (这一行复制的时候需要删掉)     "//@import url($3); 引入公共css类",
            "$4",
            "</style>"
        ],
        "description": "生成vue模板"
    },
    "http-get请求": {
    "prefix": "httpget",
    "body": [
        "this.\\$http({",
        "url: this.\\$http.adornUrl(''),",
        "method: 'get',",
        "params: this.\\$http.adornParams({})",
        "}).then(({ data }) => {",
        "})"
    ],
    "description": "httpGET请求"
    },
    "http-post请求": {
    "prefix": "httppost",
    "body": [
        "this.\\$http({",
        "url: this.\\$http.adornUrl(''),",
        "method: 'post',",
        "data: this.\\$http.adornData(data, false)",
        "}).then(({ data }) => { });" 
    ],
    "description": "httpPOST请求"
    }
}

然后以后我们写一个vue,就会快捷的帮我们提示生成全部的3部分内容

<template>
    <div>
        <el-table :data="tableData">
        <el-table-column prop="date" label="日期" width="140">
        </el-table-column>
        <el-table-column prop="name" label="姓名" width="120">
        </el-table-column>
        <el-table-column prop="address" label="地址">
        </el-table-column>
      </el-table>
    </div>
</template>

<script>
 export default {
    data() {
      const item = {
        date: '2016-05-02',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1518 弄'
      };
      return {
        tableData: Array(20).fill(item)
      }
    }
  };
</script>

然后修改路由,通过点击左侧连接,右边内容页显示具体内容。
左边点击选项1,发送table请求,点击选项2,发送hello请求

修改router目录下的index.js文件,增加路由:

import MyTable from '@/components/MyTable'
    {
      path: '/table',
      name: 'MyTable',
      component: MyTable
    }

然后修改导航一种分组一的选项1和选项2的index并且开发menu的属性router为true

然后再次点击左侧导航1的分组一的选项1和选项2可以看到正确的跳转了

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,393评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,790评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,391评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,703评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,613评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,003评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,507评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,158评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,300评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,256评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,274评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,984评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,569评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,662评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,899评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,268评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,840评论 2 339