Vue后台管理界面

Vue后台管理项目

一、自我总结后台管理界面项目里的知识点

单页应用
1. webapck 把很多的js,img,hmtl,css .... 打包成一个html文件以及相应的css和js
2. node可以操作本地文件
3. npm下载安装nodejs模块(插件)
4. 路由,单页应用通过改变路由来改变页面显示的内容
模板(使用下面技术)
1. vue 
2. elm-ui
3. webapck
4. 文档地址:  https://panjiachen.github.io/vue-element-admin-site/zh/guide/
5. 使用
* 下载项目源文件
* npm i 安装依赖的模块或者插件
* npm run dev 启动服务
接口:http://132.232.87.95:3000/ 
  • 单页应用 APS
单页应用
1. webapck 把很多的js,img,hmtl,css .... 打包成一个html文件以及相应的css和js
2. node可以操作本地文件
3. npm下载安装nodejs模块(插件)
4. 路由,单页应用通过改变路由来改变页面显示的内容

模板(使用下面技术)
1. vue 
2. elm-ui
3. webapck
4. 文档地址:  https://panjiachen.github.io/vue-element-admin-site/zh/guide/
5. 使用
* 下载项目源文件
* npm i 安装依赖的模块或者插件
* npm run dev 启动服务
这里的dev是根据package.json里scripts对象里的start来决定的

在文件夹shift+右击,调出对应文件夹的命令窗口
  • vue文件格式
<template>
  <div>
    // 只能有一个标签,html里的内容放在这里面
  </div>
</template>
<script>
import  from './'
// 到入 从某某文件里导出某某 ./用来选定当前文件夹 不能直接填否者会报错
export default {
    // 导出,vue js的代码放这里
    生命周期函数 了解可以看vue基础篇
};
</script>
<style scoped lang="less">
    // css代码放这里 scoped表示该样式只用于这个文件 lang="less"需安装less插件才可用 关于less请看我主页的文章
</style>
  • 组件使用流程
    组件->全局组件->局部组件->组件注册->组件使用->路由设置->路径相关->vue文件格式->组件导入、导出->eleme-ui引用->样式更改
全局组件:定义在Vue对象(main.js里)外,必须注册才能使用 注册之后 Vue对象都可以访问使用 
Vue.componet('组件名',{
    data:function(){
        // data必须是函数
        return:{
            // 返回想要的函数对象等
        }
    }
    template:`里面可以是标签也可以是其他的`
})

组件注册:script里加 component('组件名', {
  // ... 选项 ...
})

局部组件:定义在vue组件里面,只有在这个vue组件里才能使用
  • 配置路由
路由设置:router文件夹是路由设置的文件夹,对应里面的router.js 是配置路径的地方
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
export const constantRouterMap=[
  {
    path: './文件对应的文件夹',
    component: () => import('@/views/对应的文件夹)
    children: [  // 上面文件夹下的文件夹,简称子文件
      {
        path: 'index 文件名一般固定为index',
        name: '和父文件里path对应',
        component: () => import('@/views/index对应的文件夹/index'), // 如果有几个子文件时默认显示的文件
        meta: { title: '随意命名', icon: '图标名' }
      }
    ]
  }
]
export default new Router({
  routes: constantRouterMap
})

然后在main.js函数里面导入
import Vue from 'vue'
import router from './router'
new Vue({
  el: '#app',
  router,
  render: h => h(App)
})
  • 父子组件通信
    假设a为父组件,b为子组件
    a引用b时需要引入,import b from 'b'
    a使用b时需要在a里面注册b,
    components:{
        b
    }
    a使用b组件:<b></b>  后续一切动作的源头(如果没有引用二者之间毫无关系)
    a使用b相当于使用标签,但是标签一般都有属性
    b可以自定义属性 b里面使用 props 数组定义数组 注意是数组后接 :[ ] 属性填在里面
    父组件传数据给子组件:
    a使用b里声明好的属性,然后给属性赋值,也就是所谓的父组件传数据给子组件
    给属性赋值可以是字符串也可以是变量,但是变量之前要加:
    子组件传数据给父组件:
    a在b里声明了自定义的事件,以及函数
    在b里面触发a的自定义事件来传数据 this.$emit("自定义事件名",数据data)
  • 简单的数据结构
栈:存放基本数据类型(数字,字符串,布尔,undef,null)
堆:存放对象
栈像一个杯子,内部的东西都是从外放进来的,而且是先进后出
堆像一个仓库,内部存放对象,对象里包含很多信息,一个变量对应一个对象,当两个变量对应的对象是相同的话
  只要有一方更改,对象里面的数据都会发生更改,类似于通过一个变量绑定相同的对象然后实现双向绑定
栈堆:先进后出 数组的两个方法可以解释 push pop  
数列:先进先出 数组的两个方法可以解释 push shift
  • 组件的使用和引用
步骤:1.引入elme组件,形成静态页面
    需要注意标签内绑定的事件函数、属性和变量,更改或者对应的在下面创建好不然不会显示
    2.把相同部分做成一个小组件
    创建小组件,然后把相同部分的代码放在组件里面,注意里面的变量属性和函数要对应存在否者不显示
    3.引用刚才创建的小组件
    首先得导入,import  from '' 路径要填对 同一个文件夹的话只需要./后接组件名
    然后在导出export default下面 注册组件 components:{ 组件名 }
    4.使用组件,放在之前对应的地方,使用直接是<标签名/>
    5.在组件里面定义属性然后传需要的数据过去
    在组件的导出下面使用props:[属性名] 定义属性名 然后在引用的组件标签
    里面添加属性并传入需要的属性,是变量的时候前面需要加:
    6.然后组件实现的功能都是在组件里面编辑的,到引用的上面直接就是有功能的了
  • 三目运算符
三目运算符
三元表达式
if()else() => *?*:*
意思相近,?为if,如果前面的true则打印?后面的,如果为false则打印:后面的

sc 快速生成vue组件的框架

二、实际应用

一、 vue里页面之间传参通过router-link

获取页面传过来的参数
this.$route.params.参数名;
第一步: <router-link :to="`/cinema/edit/${scope.row.cinemaId}`">编辑</router-link>
通过router-link跳转到对呀路由(/cinema/edit)下,后面接/然后就是参数。模板字符串``里用${参数}来传
第二步:{
        path: 'edit/:id',
        component: () => import('@/views/cinema/edit'),
        meta: {
          title: '编辑影院',
          icon: 'form'
        }
      }
router里面在路径对应的后面加/:id,用id来接受参数,当然参数是自定义的
第三步: 在跳转后的页面获取参数this.$route.params.id   id对应我们在路由里定义的储存参数的变量上

二、vue里获取接口数据

 created() {
        let id = this.$route.params.id;
        this.findList(id);
    },
    methods: {
        findList(id){
            const url = process.env.BASE_API + '/cinema/findById'
          //  封装后的使用
            axios.get(url,{
                params:{
              // 参数
                    cinemaId:id
                }
            }).then( res => {
                this.list=res.data.data.cinema;
            }).catch( error => {
                console.log(error)
            })
        }
    },

和js原生对比不然发现有不同的地方,这里是对接口进行了一些封装


image.png

image.png

image.png

image.png
  • 由图片可以看出,这个是经过了一些列封装然后使得用的时候方便
    创建文件夹utils用来放封装函数->request.js对获取后台数据的axios进行封装->然后使用的时候在config文件夹下的dev-env.js里更改BASE_API为我们接口的各个部分即可

三、 结合数组函数map实现二级联动

<template>
    <!-- 联动选择组件 -->
    <div>
        <el-select @change="changeCity" v-model="film.cityId" filterable placeholder="请选择城市">
      <el-option  v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option>
    </el-select>
    <el-select v-model="film.districtId" style="margin-left: 20px;" placeholder="请选择区域">
      <el-option v-for="item in district" :key="item.value" :label="item.label" :value="item.value"></el-option>
    </el-select>
    </div>
</template>

<script>
import axios from 'axios'
export default {
    props:[
        'film'
    ],
    data() {
        return {
            options:[],
            district:[]
        }
    },
    created() {
        this.getlist();
    },
    methods: {
        getlist(){
            const url = process.env.BASE_API +'/city/getList';
            axios.get(url,{
                params:{}
            }).then(res=>{
                const cities = res.data.cities;
                const arr = cities.map(item=>{
                    return{
                        value:item.cityId,
                        label:item.name
                    }
                })
                this.options = arr;
            }).catch(error=>{
                console.log(error)
            })
        },
        changeCity(cityId){ 
            this.getDistrId(cityId)
            this.film.districtId=''
        },
        getDistrId(cityId){
            const url = process.env.BASE_API +'/district/findByCityId';
            axios.get(url,{
                params:{
                    cityId
                }
            }).then(res=>{
                const distr = res.data.districts;
                const arr = distr.map(item=>{
                    return{
                        value:item.objectId,
                        label:item.name
                    }
                })
                this.district = arr;
            }).catch(error=>{
                console.log(error)
            })
        }
    },
}
</script>
<style>
</style>
  • @ v-on的缩写 : v-bind缩写 @绑定事件 :变为变量

四、 结合数组函数push、indexOf、splice增删输入框

<template>
<!-- 增删输入框组件 -->
  <div class="sb">
    <el-form-item class="input" label="剧照">
      <el-input placeholder="请输入内容" v-model="film.pics">
      </el-input>
      <el-button @click="addDomain" class="button" type="info">新增</el-button>
    </el-form-item>
    <el-form-item class="input" label='剧照' v-for="(domain) in photos.domains" :key="domain.key">
     <div>
        <el-input placeholder="请输入内容" v-model="film.pics">
      </el-input>
      <el-button @click.prevent="removeDomain(domain)" class="button" type="info">删除</el-button>
     </div>
    </el-form-item>
  </div>
</template>

<script>
export default {
    props:[
        "film"
    ],
  data() {
    return {
      photos: {
        domains: []
      }
    };
  },
  created() {
  },
  methods: {
    addDomain() {
        this.photos.domains.push({
        value: "",
      });
    },
    removeDomain(item) {
      var index = this.photos.domains.indexOf(item);
      if (index !== -1) {
        this.photos.domains.splice(index, 1);
      }
    }
  }
};
</script>
<style>
.input {
  position: relative;
  right: 80px;
}
.button {
  position: relative;
  float: right;
  top: -40px;
  left: 75px;
}
.ab {
  clear: both;
}
</style>
  • 可见input类型标签使用v-model和数据双向绑定更改值
    以及遍历使用v-for((item,index) in list) :key="index"
  • v-for key 实现输入框的增加、删除
<template>
  <div>
    <h3>v-for key 实现输入框的增加、删除</h3>
    <div
      :v-model="lists[index].value"
      :class="'input'+index"
      v-for="(list,index) in lists"
      :key="list.id"
    >
      <input type="text" placeholder="请输入">
      <button v-if="panduan(index)" @click="add">+</button>
      <button v-else @click="del(index)">-</button>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      lists: [{}]
    };
  },
  created() {},
  methods: {
    add() {
      this.lists.push({
        value: ""
      });
    },
    del() {
      this.lists.pop();
    },
    panduan(index) {
      return this.lists.length - 1 === index;
    }
  }
};
</script>
<style>
button {
  width: 25px;
  height: 25px;
}
</style>
// key 指定一个属性为区别两个数据,一般是id,类似于数据库里的主键

五、渲染列表

<template>
<!-- 父子通信组件 -->
<div>    
    <el-form-item label="电影名称">
    <el-input v-model="film.name"></el-input>
  </el-form-item>
  <el-form-item label="海报地址">
    <el-input v-model="film.poster"></el-input>
  </el-form-item>
  <el-form-item label="演员">
    <el-input v-model="film.actors"></el-input>
  </el-form-item>
  <el-form-item label="导演">
    <el-input v-model="film.director"></el-input>
  </el-form-item>
  <el-form-item label="产地">
    <el-input v-model="film.nation"></el-input>
  </el-form-item>
</div>
</template>

<script>
import Xuan from './Xuan'
export default {
    props:[
        'film'
    ],
    data() {
        return {
        }
    },
    components:{
      Xuan
    }
}
</script>
<style>
</style>

列表里大部分用的都是input标签,然后渲染方式就是绑定v-model双向绑定更改数据
六、父子通信

// 父组件
<template>
    <div>
        <Form></Form>
        <Form title="添加电影"></Form>
        <!-- 通过字符串添加 -->
        <Form :title="title"></Form>
        <!-- 通过变量以及组件里的属性添加 -->

        <!-- 通过自定义事件把子组件的数据传到父组件 -->
        <Form id="app" @aaa="test">自定义事件</Form>

        <!-- 二级联动 -->
        <demo class="demo"></demo>

        <!-- 增删输入框 -->
        <xinzeng></xinzeng>
    </div>
</template>
<script>
// 加载Form 组件
import xinzeng from './components/xinzeng';
import demo from './components/demo';
import Form from './components/Form'
export default {
    data() {
        return {
            title:'这是通过组件的属性添加的'
        }
    },
    created() {
        // emit 触发自定义事件
        // this.$emit('aaa');
    },
    mounted() {
    },
    methods: {
        test(data){
            alert(data);
        }
    },
    // 注册组件
    components:{
        Form,
        demo,
        xinzeng
    }
}
</script>
<style>
.demo{
    margin-top: 20px;
    margin-left: 20px;
}
</style>
// 子组件
<template>
    <div>
        <h3>{{title}}</h3>
        <span>用户名:</span>
        <input v-model="user" type="text">
        <button @click="submit">传数据</button>
        
    </div>
</template>

<script>
export default {
    props    //  属性   如果把组件当成标签
    :[
        "title",
    ],
    data() {
        return {
            user:''
        }
    },
    // 避免修改从父组件传下来的属性,修改会给后期维护带来不利
    created() {
        console.log(this.title);
        // 可以通过this访问title
    },
    methods: {
        submit(){
            // 触发父组件的自定义aaa事件
            this.$emit("aaa",this.user)
        }
    },
}
</script>
<style>
    button{
        width: 100px;
    }
</style>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • 这篇笔记主要包含 Vue 2 不同于 Vue 1 或者特有的内容,还有我对于 Vue 1.0 印象不深的内容。关于...
    云之外阅读 5,044评论 0 29
  • 前言 您将在本文当中了解到,往网页中添加数据,从传统的dom操作过渡到数据层操作,实现同一个目标,两种不同的方式....
    itclanCoder阅读 25,738评论 1 12
  • ## 框架和库的区别?> 框架(framework):一套完整的软件设计架构和**解决方案**。> > 库(lib...
    Rui_bdad阅读 2,889评论 1 4
  • 一:什么是闭包?闭包的用处? (1)闭包就是能够读取其他函数内部变量的函数。在本质上,闭包就 是将函数内部和函数外...
    xuguibin阅读 9,519评论 1 52
  • 每个人心里都有一个地方,住着一个人,那里春风秋月、冬暖夏凉。 你微微笑着,不问我说什么话, 而我觉得,为了这个,我...
    喜欢诗词的女孩阅读 596评论 0 0