借助node.js搭建vue项目

1 环境

1.1环境配置与搭建

引用 网址 ,完成node安装,以及使用vue-cli搭建vue项目。

1.2 创建项目时选项详解

vue init webpack my-project 选项详解

2 开发工具

2.1工具挑选

选用网友常用的开发工具vscode,具体安装方法引用网址,完成vscode和插件安装。

2.2开发工具调试

浏览器可在vue文件中,script代码块加断点调试。可通过vue-devtools监控vue各个页面的实时data。由于github下载过慢,找了gitee上的资源,打包编译,附上编译好的文件。链接:https://pan.baidu.com/s/1isxDBz6gTUWT6BtZZTYQZw
提取码:xuyl

3程序开发

3.1安装依赖+运行编译

进入项目,执行npm install/cnpm install,安装依赖包。如果需要引入新的组件,npm install vue-json-excel --save
在这里插入图片描述
npm run dev 运行项目。
npm run build 编译项目,在dist下面生成静态文件,可用于springboot部署。

3.2动态路由配置

后台JSON对象

private Integer id;
private String label;
private List<Menu> children;

前端router/index.js,将需要权限控制的路由放置addRouterMap 中

import Vue from 'vue'
import Router from 'vue-router'
import Layout from '../views/layout/Layout'
Vue.use(Router)

export const constantRouterMap = [
  {path: '/login', component: () => import('@/views/login'), hidden: true},
  {
    path: '',
    component: Layout,
    redirect: '/home',
    children: [{
      path: 'home',
      name: 'home',
      component: () => import('@/views/home/index'),
      meta: {title: '首页', icon: 'home'}
    }]
  } 
]
export const addRouterMap = [
{
  path: '/manage',
  name: 'manage',
  component: Layout,
  meta: {title: '系统管理', icon: 'system'},
  children: [{
    path: 'userlist',
    name: 'userlist',
    component: () => import('@/views/manage/user/index'),
    meta: {title: '用户管理', icon: 'user'},
    hidden:false
  },
  {
    path: 'useradd',
    name: 'useradd',
    component: () => import('@/views/manage/user/add'),
    hidden:true
  },
  {
    path: 'userupdate',
    name: 'userupdate',
    component: () => import('@/views/manage/user/update'),
    hidden:true
  },
  {
    path: 'orglist',
    name: 'orglist',
    component: () => import('@/views/manage/organization/index'),
    meta: {title: '机构管理', icon: 'org'},
    hidden:false
  },
  {
    path: 'rolelist',
    name: 'rolelist',
    component: () => import('@/views/manage/role/index'),
    meta: {title: '角色管理', icon: 'role'},
    hidden:false
  },
  {
    path: 'getPermission',
    name: 'getPermission',
    component: () => import('@/views/manage/role/getPermission'),
    meta: {title: '权限分配', icon: 'user'},
    hidden:true
  }]
},
{
  path: '/score',
  name: 'score',
  component: Layout,
  meta: {title: '部门考核', icon: 'score'},
  children: [{
    path: 'poslist',
    name: 'poslist',
    component: () => import('@/views/score/pos/index'),
    meta: {title: '职位管理', icon: 'pos'},
    hidden:false
  },
  {
    path: 'scorelist',
    name: 'scorelist',
    component: () => import('@/views/score/score/index'),
    meta: {title: '考核列表', icon: 'list'},
    hidden:false
  },
  {
    path: 'detaillist',
    name: 'detaillist',
    component: () => import('@/views/score/detail/index'),
    meta: {title: '我的评分', icon: 'detail'},
    hidden:false
  },
  {
    path: 'rpt',
    name: 'rpt',
    component: () => import('@/views/score/rpt/index'),
    meta: {title: '考核统计', icon: 'user'},
    hidden:false
  }]
},
  {path: '*', name:'404',component: () => import('@/views/404'), hidden: true}
]

export default new Router({
  // mode: 'history', //后端支持可开
  scrollBehavior: () => ({y: 0}),//使用前端路由,当切换到新路由时,想要页面滚到顶部,或者是保持原先的滚动位置,就像重新加载页面那样。
  routes: constantRouterMap
})

将用户路由权限和导航栏展现形式通过VUEX存放。
在这里插入图片描述
src/store/modules/permssion.js,GenerateRoutes负责权限过滤。

import { addRouterMap, constantRouterMap } from '@/router/index';
import router from '@/router'

const permission = {
  state: {
    routers: constantRouterMap, //初始路由取router中的路由
    addRouters: []
  },
  mutations: {
    SET_ROUTERS: (state, routers) => {
      state.addRouters = routers;
      state.routers = constantRouterMap.concat(routers);
    }
  },
  actions: {
    GenerateRoutes({ commit }, data) {
      return new Promise(resolve => {
        const { getRouter } = data;//获取data 参数中的getRouter
          const accessedRouters = addRouterMap.filter(v => {
            //admin帐号直接返回所有菜单
            // if(username==='admin') return true;
            if (hasPermission(getRouter, v)) {
              if (v.children && v.children.length > 0) {
                v.children = v.children.filter(child => {
                  if (hasPermission(getRouter, child)) {
                    return child
                  }
                  return false;
                });
                return v
              } else {
                return v
              }
            }
            return false;
          })
        commit('SET_ROUTERS', accessedRouters);
        resolve();
      })
    }
  }
};
function hasPermission(menus,func)
{
  if(menus.indexOf(func.name) > -1)
  {
    return true;
  }
  return false;
}
export default permission;

src/permission.js,前端权限控制模块`

import router from './router'
import NProgress from 'nprogress' // Progress 进度条
import 'nprogress/nprogress.css'// Progress 进度条样式
import Layout from '@/views/layout/Layout' //Layout 是架构组件,不在后台返回,在文件里单独引入 */
import {getObjArr } from '@/utils/support'
import { addRouterMap, constantRouterMap } from '@/router/index';
import store from './store'

var getRouter

const whiteList = ['/login']  // 不重定向白名单
  router.beforeEach((to, from, next) => {
      NProgress.start()
      if (getRouter||whiteList.indexOf(to.path) !== -1) { //路由直接往下走
         if (to.meta.title) {
             document.title = to.meta.title
          }
        next()
      }
      else
      {
        var userInfo=getObjArr('userInfo')//从sessionStorage拿到用户信息
        if(!userInfo) //session过期
        {
          console.log('session已过期')
          next('/login')
          NProgress.done()
        }
        else{ 
            getRouter =userInfo.frontNames//拿到路由,格式
            getRouter.push("404")
             store.dispatch('GenerateRoutes', {getRouter}).then(() => { // 生成可访问的路由表
              router.addRoutes(store.getters.addRouters); // 动态添加可访问路由表
              next({ ...to, replace: true })
            })  
        } 
      }
    })

router.afterEach(() => {
  NProgress.done() // 结束Progress
})

参考mall教程编写菜单栏控件。

3.3vue文件整体学习

3.3.1script

1.export default 的用法:相当于提供一个接口给外界,让其他文件通过 import 来引入使用。
而对于export default 和export的区别:
在JavaScript ES6中,export与export default均可用于导出常量、函数、文件、模块等,你可以在其它文件或模块中通过import+(常量 | 函数 | 文件 | 模块)名的方式,将其导入,以便能够对其进行使用,但在一个文件或模块中,export、import可以有多个,export default仅有一个。

//demo.js 声明部分
export const str = 'hello world'

export function f(b){
    return b+1
}

//demo1.js 导出部分
import { str, f } from 'demo' //也可以分开写两次,导入的时候带花括号

而对于 new Vue({})部分, 只是创建一个Vue的实例 就是相当于创建一个根组件,main.js中

new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})

app.vue组件中,路由页面嵌套

2.vue js中各选项
(1)data:Vue 将会递归将 data 的属性转换为 getter/setter,从而让 data 的属性能够响应数据变化。对象必须是纯粹的对象 (含有零个或多个的 key/value 对)
可以写成:

data () {
return {
dataForm: {
xxx: ‘’,
xxx: 数字 //这里的数字会固定XXX的选项
},
xxx: [],
xxx: false,
xxx: 数字
}
}

(2)methods

new Vue({
  data:{
    a:1,
    b:[]
  },
  methods:{
    doSomething:function(){
      console.log(this.a)
    }
  }
})

methods就是方法,这个方法里面打印了a
(3)watch

new Vue({
  data:{
    a:1,
    b:[]
  },
  methods:{
    doSomething:function(){
      this.a++
    }
  },
  watch:{
    'a':function(val, oldVal){
      console.log(val,oldVal)
    }
  }
})

watch字母上理解就是一个监听,这里面我们监听了a,这个a就是数据里面的a,比如doSomething里面进行了+1的变化,watch里面对应的监听方法就会自动的去执行,这里打印了新的值和旧的值,如果+1后,val就是2,oldVal就是1
(4)生命周期钩子
比如 created 钩子可以用来在一个实例被创建之后执行代码:

new Vue({
data: {
a: 1
},
created: function () {
// this 指向 vm 实例
console.log('a is: ’ + this.a)
}
})
// => “a is: 1”
下图展示各函数在生命周期的位置(el:页面中el表达式)

在页面首次加载执行顺序有如下:
beforeCreate //在实例初始化之后、创建之前执行
created //实例创建后执行
beforeMounted //在挂载开始之前调用
filters //挂载前加载过滤器
computed //计算属性
directives-bind //只调用一次,在指令第一次绑定到元素时调用
directives-inserted //被绑定元素插入父节点时调用
activated //keek-alive组件被激活时调用,则在keep-alive包裹的嵌套的子组件中触发
mounted //挂载完成后调用
{{}} //mustache表达式渲染页面

修改页面input时,被自动调用的选项顺序如下:
watch //首先先监听到了改变事件
filters //过滤器没有添加在该input元素上,但是也被调用了
beforeUpdate //数据更新时调用,发生在虚拟dom打补丁前
directived-update //指令所在的组件的vNode更新时调用,但可能发生在其子vNode更新前
directives-componentUpdated//指令所在的组件的vNode及其子组件的vNode全部更新后调用
updated //组件dom已经更新

组件销毁时,执行顺序如下
beforeDestroy //实例销毁之前调用
directives-unbind //指令与元素解绑时调用,只调用一次
deactivated //keep-alive组件停用时调用
destroyed //实例销毁之后调用

(5)mixins

export default {
....
import ResizeMixin from './mixin/ResizeHandler'
mixins: [ResizeMixin]
.....
}

相当于将resizemixin中所有的内容加载至当前script中,组件内容会合并。

(6)computed
1.computed用来监控自己定义的变量,该变量不在data里面声明,直接在computed里面定义,然后就可以在页面上进行双向数据绑定展示出结果或者用作其他处理;
2.computed比较适合对多个变量或者对象进行处理后返回一个结果值,也就是数多个变量中的某一个值发生了变化则我们监控的这个值也就会发生变化,举例:购物车里面的商品列表和总金额之间的关系,只要商品列表里面的商品数量发生变化,或减少或增多或删除商品,总金额都应该发生变化。这里的这个总金额使用computed属性来进行计算是最好的选择

3.3.2模板指令(html)

模板指令是写在html里面的,比如最常用的就是
数据渲染:v-text,v-html,{{}}

new Vue({
  data:{
    a:1,
    b:[]
  }
})
<p>{{ a }}</p>
<p v-text='a'></p>
<p v-html='a'></p>

这三个其实不能说是等价的,因为v-text是格式处理了html,v-html保存了html结构,但是无论如何这个a都是对应到数据源里面的a,当这个a通过doSomething这个方法进行自增的话,模板上的a会自动进行更新,所以这其实是运用模板的一个优势。

控制模板隐藏:v-if,v-show

new Vue({
  data:{
    isShow:true,
    age:12
  }
})
 <span v-if="age<20">小孩</span>
    <span v-else-if="age<30">青年</span>
    <span v-else-if="age<40">中年</span>
    <span v-else>老年</span>
<p v-show='isShow'></p>

v-if,v-show就是控制这个元素的显示和隐藏,他们的差别是v-if直接不渲染这个dom元素,而v-show是通过css的display来进行隐藏,在代码里是可以看到这个dom元素的

渲染循环列表:v-for
复制代码

new Vue({
  items:[
    {
      label:'apple'
    },{
      label:'banana'
    }
  ]
})

<ul>
  <li v-for='item in items'>
    <p v-text='item.label'></p>
  </li>
</ul>

我们使用其他的框架大多都有列表多渲染方法,就是循环渲染,我们的数据源是上面的一个数组

事件绑定:v-on

new Vue({
  methods:{
    doThis:function(sth){
    }
  }
})
<button v-on:click='doThis'></button>
<button @click='doThis'></button>

时间绑定是很常用的一个东西,@click是v-on:click的简写模式,点击的时候去执行doThis这个方法,这个doThis是选项methods里面的东西,而不是data里面的,data主要一些固定的数据,操作数据的这个概念,method是页面中会使用到的一些方法

属性绑定: v-bind

<img v-bind:src='imageSrc'>
<div :class='{red:isRed}'></div>
<div :class='[classA,classB]'></div>
<div :class='[classA,{classB:isB,classC:isC}]'></div>

v-bind是只对dom元素属性的一些操作,v-bind:src指的是src属性,给赋值imageSrc,v-bind最常用的是:class,:class是v-bind:class的简写方式,

3.3.3 组件 components

组件的注册有两种方式:
1.全局注册
示例代码:

Vue.component('my-component',{
     // 选项
})

my-component就是注册的组件的自定义标签名称,之后就可以使用<my-component></my-component>来使用组件了。
2.局部注册
通过components局部注册组件

<div id='app'>
    <siderbar-item></siderbar-item>
</div>
<script>
	import SidebarItem from './SidebarItem'
    var app = new Vue({
        el:"#app",
        components: { 
        SidebarItem,
        'siderbar-item': SidebarItem //或以此方法引入
        } 
    })
</script>

3.使用props传递数据

Vue.component("v-com",{ //注册带参数的自建
            props:["message"],
            template:'<div>{{message}}</div>'
        })
        
<v-com message = "来自父组件的数据"></v-com>
<v-com v-bind:message = "parentData"></v-com>
var app = new Vue({
            el:"#app",
            data:{
                parentData:'123'
            }
        })

3.4 常用组件

3.4.1 svg-icon

svg-icon

3.4.2 element-ui

文档链接:https://pan.baidu.com/s/1HfKMYe_ZChgOD-QQhmOdDQ
提取码:v5n5

1、表单 el-form
在这里插入图片描述
高级基础表格
template(模版) 在这里属于一个固定用法:
通过 Scoped slot 可以获取到 row, column, $index 和 store(table 内部的状态管理)的数据

表单中嵌套规则校验(rules),亲测博文中第二种方法有效。https://www.cnblogs.com/beileixinqing/p/10969828.html

<div v-for="(item,index) in dataFields.list :key="index">
    <el-form-item label="name" :prop="`list[${index}].name`" :rules="{ required: true, message: 'Required', trigger: 'blur' }">
       <el-input placeholder="name" v-model="item.name"></el-input>
   </el-form-item>
</div>

2.el-select
filterable,可模糊查询;clearable,有清楚按钮;mutiple,多选

    <el-select v-model="listQuery.orgId" placeholder="请选择"   filterable  class="input-width">
       <el-option :key="0" label="请选择" value=""  ></el-option>
      <el-option v-for="item in orgList"
                 :key="item.orgId"
                 :label="item.orgName"
                 :value="item.orgId">
      </el-option>
    </el-select>

3.4.3 vue excel导出

https://blog.csdn.net/qq_42221334/article/details/99566915

3.5 打包发布

打包

3.6 开发过程中遇到的问题

3.5.1 vue每次请求后台jsessionid改变

在axios配置中,加上service.defaults.withCredentials = true;

3.7vue和原生JS

//JS/JQuery:

Jquery只是对原生JS的API选择器等等进行了封装,便于操作DOM,本质还是操作DOM实现逻辑,数据和界面还是连接在一起的。
适用于需要操作DOM的业务:动画,交互效果,页面特效。

//Vue.js:
在这里插入图片描述
MVVM模型,将数据层和视图层完全分离开,不仅对API进行封装, 还提供了一系列的解决方案。这是一个思想的转变。数据驱动的机制,主要操作的是数据而不是频繁操作DOM(导致页面频繁重绘)。
适用的业务:数据相关的处理以及操作

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 使用VueNode.js实现个人博客系统,可以让开发者快速搭建一个高效、灵活、易于维护的博客系统。Vue作为前端框架,可以提供良好的用户体验和交互效果,而Node.js则可以提供高效的后端支持,使得博客系统具有更好的性能和可扩展性。此外,VueNode.js都有着丰富的社区资源和插件库,可以帮助开发者快速解决问题和实现功能。 ### 回答2: 使用VueNode.js实现个人博客系统有以下几个原因: 1. 前后端分离:Vue是一款流行的前端框架,它提供了一种简单、高效的方式来构建用户界面。通过使用Vue,可以实现前后端分离,将前端和后端的开发过程分离,提高了开发效率。 2. Vue的组件化开发:Vue采用了组件化开发的思想,使得代码的复用性更高,开发更加模块化。通过将博客系统的各个功能模块拆分成独立的组件,可以方便地进行管理和维护。 3. Node.js的高效性能:Node.js是一种基于事件驱动、非阻塞I/O模型的服务器端JavaScript运行环境。相比传统的后端开发语言,Node.js具有更高的性能和并发能力,能够处理大量的并发请求,适合实现高负载的博客系统。 4. 可扩展性:VueNode.js都具有良好的可扩展性,可以根据博客系统的需求进行定制开发。Vue提供了丰富的插件和组件库,可以方便地进行功能扩展;而Node.js通过使用npm包管理器,可以引入各种第三方模块,快速构建博客系统。 5. 生态系统完善:VueNode.js都拥有庞大的开发者社区和活跃的生态系统。这意味着许多优秀的第三方库和工具已经被开发出来,并得到了长期维护和更新。这为博客系统的开发提供了更多的选择和支持。 综上所述,使用VueNode.js实现个人博客系统,既可以提高开发效率,又能够实现更高的性能和可扩展性,同时还能够借助强大的开发者社区和生态系统,为博客的开发提供更多的资源和支持。 ### 回答3: 使用VueNode.js实现个人博客系统有以下几个原因: 首先,Vue是一款轻量级的JavaScript框架,具有良好的响应式性能和组件化开发思想。Vue的虚拟DOM机制可以提高页面渲染性能,而且Vue的组件化开发可以使得代码更加模块化,便于维护和扩展。在个人博客系统中,我们可以将不同的功能模块封装成Vue组件,使得代码结构清晰,更易于开发和维护。 其次,Node.js是一个基于JavaScript的运行时环境,具有事件驱动和非阻塞I/O的特性。Node.js的高性能使得它非常适合处理实时性要求较高的应用,比如个人博客系统。在个人博客系统中,用户可以实时发布、编辑、删除文章,Node.js的事件驱动和非阻塞I/O特性使得这些操作可以高效地处理并及时地更新到页面上。 另外,VueNode.js都具有活跃的社区和丰富的生态系统。Vue社区有大量的插件和组件可供使用,可以方便地实现各种功能需求,比如路由管理、表单验证、数据可视化等。而Node.js的包管理工具npm也提供了大量的模块可供使用,可以加速开发过程,提高开发效率。 最后,VueNode.js都具有良好的文档和学习资源。Vue官方提供了详细的文档和教程,社区中也有很多优秀的博客和视频教程可供学习。而Node.js的官方文档和npm的官方网站也提供了很多的学习资源和示例代码,便于开发者快速上手和解决问题。 综上所述,使用VueNode.js实现个人博客系统能够方便地开发、维护和扩展系统,同时享受到活跃的社区和丰富的学习资源,提高开发效率和用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值