资讯专栏INFORMATION COLUMN

vue 项目开发要点总结

Drummor / 3000人阅读

摘要:提交是更改状态的唯一方法,并且这个过程是同步的。对于大型应用,我们会希望把相关代码分割到模块中。

vue-cli 脚手架工具的使用

vue-cli 的依赖

vue-cli 的使用流程

node 的安装
node 是通过js 操作系统接口的语言; npm 是node的包管理工具;所以,安装了node 就可以直接使用npm 下载我们需要的包;
node 可以直接去node官网下载对应系统的安装包,安装提示完成;
然后在 命令行中 通过 npm -v 查看npm 版本,如果有出来代表安装成功;

npm 代理 到cnpm
你直接通过添加 npm 参数 alias 一个新命令:

alias cnpm="npm --registry=https://registry.npm.taobao.org 
--cache=$HOME/.npm/.cache/cnpm 
--disturl=https://npm.taobao.org/dist 
--userconfig=$HOME/.cnpmrc"

然后运行

cnpm  install xx -g  //全局安装xx

使用 vue-cli

vue init webpack demoName //生成 webpack 为模板的vue项目

运行热更新页面

npm run dev

生成项目可以直接通过 http://localhost:8080/?#/ 访问

如果你是拉别人的项目运行的,要先运行下面的命令,安装依赖包

npm install 
//或者
npm i

生成一个 静态项目文件(直接打开的静态页面)

npm run build
大多数情况 ,生成的页面是不可以直接打开的;提示只能部署到 服务器上才能正常访问;
如果需要直接本地打开;到项目目录下的config文件夹里的index.js文件中,将build对象下的assetsPublicPath中的“/”,改为“./”即可


生成的文件都是经过压缩的,带md5的文件

es6 的引入与输出
export default{} ,  module.exports = {},  exports { }

在node 的模块中,exports 是 module.exports 的引用;但是在vue 中 不能写成

exports = {
    porps:["text"]
}

// 提示 text 未定义;

exports default {} 定义的输出;可以通过 import xx 直接使用(标准ES6);写法是:

exports default {a:123}    

import a; 

module.exports = {} 与 exports default 是等价的

但是如果 同一个js 同时出现 module.exports ={} 和 import 就会报错

module.exports = {a:123} //定义和导出

import a;  //引入

//上面两个关键词 不能同时出现在同一个js 中

报错原因如下:

webpack可以使用require和export ,但是不能混合使用import 和module.exports ,不然会报错Cannot
assign to read only property "exports" of object "#"
ES6 统一的写法 是 import 和 exports default
如果你要import 组件 ;建议 统一使用 exports default {} 编写组件

vue-router 路由插件安装

安装

cnpm install vue-router 

引入为全局插件

配置路由表

可以通过router-link 组件 链接到 对应组件;它会解析成类似a 标签

forms  //注意书写格式一定要正确
father

注意到 生成的url 中前面自动加了个 “#”;可以通过添加 mode:"history", 去掉

原理:https://router.vuejs.org/zh-c...

路由配置中,path 可以设置 url 带参;

带参path定义

表示 apple 后面跟的是参数,不是路径;

带参路径

获取参数

使用路由要注意的地方

所有的路由都是定义在 routes 生成的页面中的;不能在子组件中重新定义;例子如下:

var router = new VueRouter()

import browseMode from "./components/browse-mode.vue"
import blogList from "./components/blog-list.vue"
import blogArticle from "./components/blog-article.vue"
import writePanel from "./components/write-panel.vue"

router.map({
    "/": {
      component: browseMode,
      subRoutes: {
        "/": {
          component: blogList
        },
        "/details/:artId": {
          component: blogArticle
        }
      }
    },
    "/edit/:mode": {
      component: writePanel
    },
    "/search/tag/:tag": {
      component: browseMode,
      subRoutes: {
        "/": {
          component: blogList
        }
      }
    },
    "/search/time/:time": {
      component: browseMode,
      subRoutes: {
        "/": {
          component: blogList
        }
      }
    },
    "/search/title/:title": {
      component: browseMode,
      subRoutes: {
        "/": {
          component: blogList
        }
      }
    },
})
router.start(App, "app")

路由不是最适合做tab切换的;最适合做tab的是 components 内置组件 ;通过is 控制切换;



var vm = new Vue({
  el: "#example",
  data: {
    currentView: "home" //改变这个值就会切换内容;
  },
  components: {
    home: { /* ... */ },
    posts: { /* ... */ },
    archive: { /* ... */ }
  }
})

定义带参路由 的时候 注意格式是 path:"/box1/:text", 不是path:"/box1:text",(可以理解为/: 后面是参数 ,/后面是路径;)

定义好路由后, router-link 是可以放在任何地方的;它就是一个a标签;点击会切换第一个父级的router-view 中的页面;还要注意格式和传参

 
  • box1
  • // to的 值是一个对象 ,key 固定是path ,value 是 一个字符串; // 后面的666 是参数;它的前面不是 “ ?或者 & ” 而是 “ / ”;

    获取参数的时候,直接去到参数的值是 this.$route.params.text (text是你定义路由时的 :text )

    因为$route 是一个全局变量,你还可以直接在html 中使用它的url参数

    {{$route.params.text}}

    定义一个多参数 路由的 url

    使用时的url可能是这样:

    http://localhost:8080/#/apple/red/detail/fool
    //后面的detail 是固定的。

    获取的方法是一样的;

    var a = $route.params;
    
    //结果
    a={
        color:red,
        type:fool
    }
    子路由的定义
    {
      path:"/box1",
      component:box1,
      children:[
        {
          // 当 /box1/box1a匹配成功,
          // box1a会被渲染在 box1的  中
          path:"box1a", //这里不加 “ / ”
          component:box1a
        },
        {
          path:"box1b",
          component:box1b
        }
      ]
    },
    // 要注意,以 / 开头的嵌套路径会被当作根路径。 这让你充分的使用嵌套组件而无须设置嵌套的路径。
    
    
    
    //在box1 中定义一行 
    
    
    
    //子组件 box1a 会自动渲染 到页面中;
    
    //如果添加两个 router-link 组件 就可以做tab切换(不建议用路由做tab)
    //router-link 只会切换 第一个父级的 router-view 中的内容,所以不会刷新整个 box1 ;
    
    
    • box1a
    • box1b
    //path 写成 /box1/box1a 是用了根路径(绝对路径)的形式; //如果写成 {path:"box1a"} 则是相对路径;这样写点击 浏览器的url会写成 http://localhost:8080/box1a //因为顶级路由中是没有定义 box1a 组件的;所以页面空白;
    带参子路由
    //路由定义
    {
      path:"/box1/:text",
      component:box1,
      children:[
        {
          path:"box1a",
          component:box1a
        },
        {
          path:"box1b",
          component:box1b
        }
      ]
    },
    
    
    //跳转到 box1 的写法
     
  • box1
  • //box1 中渲染 box1a/b 的写法
    • box1a
    • box1b
    //初始化的时候生成url mounted: function () { this.parms = this.$route.params.text; this.url1 = "/box1/"+this.parms+"/box1a" this.url2 = "/box1/"+this.parms+"/box1b" },

    router-link 中的to 属性,如果只是简单的跳转可以直接写成 to=“box1”;

    如果加上:绑定属性;后面的属性可以是简短的 表达式,因此上面的例子可以简化为:

    //路由定义
    {
      path:"/box1/:text",
      component:box1,
      children:[
        {
          path:"box1a",
          component:box1a
        },
        {
          path:"box1b",
          component:box1b
        }
      ]
    },
    
    
    //跳转到 box1 的写法
     
  • box1
  • //box1 中渲染 box1a/ b 的写法 //to 属性会自动 运算出来;
    • box1a
    • box1b
    //初始化的时候生成url mounted: function () { this.parms = this.$route.params.text; },
    具名路由

    router-link 还可以通过 name 指定跳转(具名路由);通过例如 tag="li" 指定包裹标签为a以为的tag;

     children:[
            {
              path:"box1a",
              name:"nameBox",
              component:box1a
            }
            ]
            
     nameBox       
            
    //结果:会生成li, 点击router-view 会渲染出 box1a ;注意,path是不可缺少的
            
    用具名路由布局(代替iframe的方式)
    export default new Router({
      mode:"history",
      routes: [
        {
          path:"/index",
          components:{   //注意这里是有 “ s ” 的
            default:vuexIndex,  //对应 
            left:vuexLeft,    // 对应
            right:vuexRight  //对应
          }
        }
      ]
    })
    
    
    
    
    //注意访问的路径 是在components 中定义的path ;
    
    在某个页面中定义具名路由
    {
      path:"/layout",
      name:"layout",
      component:layout,
      children: [
        {
          path: "/",
          components:{
            default:main,
            leftView:leftView,
            topBar:topBar
          },
        }
      ]
    }
    
    
    
    
    
    路由的重定向
     routes: [
        { path:"/", redirect:"/box" //路径不存在就跳转到box
        },
        { path: "/a", redirect: "/b" } //访问a的路径,都跳转到b
    ]
    vuex 状态管理插件安装

    当vue项目中 组件过多并设计到功能某些数据的时候,管理数据变得复杂,VUEX 就是通过自身的一套数据管理流程帮助你管理 项目数据(状态);

    安装

    cnpm install vuex --save

    实例化

    //在main.js 中
    
    import Vuex from "vuex"
    
    Vue.use(Vuex);
    let store = new Vuex.Store({  //Store 是vuex 方法
      state:{ //存放变量的地方
        total:0,
        appleTotal:0,
        bananaTotal:0,
      },
      mutations:{     //定义同步变量的方法
        aSetValue(state,value){
          state.appleTotal = value
          state.total = state.appleTotal + state.bananaTotal;
        },
        bSetValue(state,value){
          state.bananaTotal = value
          state.total = state.appleTotal + state.bananaTotal;
        }
      }
    })
    
    
    new Vue({
      el: "#app",
      store,   //在实例中 引入
      router,
      components: { App },
      template: ""
    })
    

    获取值

    vuex 的变量store 全局以后可以通过以下语句获取

    this.$Store.state.total 
    
    //组件中
     

    总价:{{$store.state.total}}

    还可以通过设置getter函数 暴露对应的值

     getters:{
        getTotal(state){
          return state.total
        }
      },
    
    //组件中
    
    

    总价:{{$store.getters.getTotal}}

    改变vuex变量的值

    通过在组件中调用以下特定语句改变

     methods:{
          add(){
            this.cnt += 1;
            //bSetValue 是在vuex实例的mutations中定义的方法
            //通过 bSetValue方法 去改变实例的值
            this.$store.commit("bSetValue",this.cnt*5) 
          },
          minus(){
            this.cnt-=1;
            this.$store.commit("bSetValue",this.cnt*5)
          }
        },
        
     // 在vuex 中只有 commit 方法可以改变数据;这里是不建议直接在组件中调用 cmmit 的
     // 因为cmmit中只能是同步操作;但是交互往往需要同步数据库
     // 更加好的方法是在 actions的方法 中触发 commit;actions 方法支持异步操作;
     // 所有涉及 后端API 的接口都是放在actions 中进行   

    actions 属性

    mutations:{
            aSetValue(state,value){
              state.appleTotal = value
              state.total = state.appleTotal + state.bananaTotal;
            },
            bSetValue(state,value){
              state.bananaTotal = value
              state.total = state.appleTotal + state.bananaTotal;
            }
      },
    actions:{ 
             // 定义doAfn 方法,间接触发 aSetValue;
             // 在doAfn 方法是可以用ajax 的
            doAfn(context,price){
              context.commit("aSetValue",price)
            },
            doBfn(context,price){
              context.commit("bSetValue",price)
            }
      }
    

    组件中的触发方式 通过 dispatch 触发doAfn;

    this.$store.dispatch("doAfn",val*10)
    vuex 的 modules

    Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:

    官方文档代码

    const moduleA = {
      state: { ... },
      mutations: { ... },
      actions: { ... },
      getters: { ... }
    }
    
    const moduleB = {
      state: { ... },
      mutations: { ... },
      actions: { ... }
    }
    
    const store = new Vuex.Store({
      modules: {
        a: moduleA,
        b: moduleB
      }
    })
    
    store.state.a // -> moduleA 的状态
    store.state.b // -> moduleB 的状态

    官方的文档组织建议:

    应用层级的状态应该集中到单个 store 对象中。

    提交 mutation 是更改状态的唯一方法,并且这个过程是同步的。

    异步逻辑都应该封装到 action 里面。

    对于大型应用,我们会希望把 Vuex 相关代码分割到模块中。下面是项目结构示例:

    ├── index.html
    ├── main.js
    ├── api
    │   └── ... # 抽取出API请求
    ├── components
    │   ├── App.vue
    │   └── ...
    └── store
        ├── index.js          # 我们组装模块并导出 store 的地方
        ├── actions.js        # 根级别的 action
        ├── mutations.js      # 根级别的 mutation
        └── modules
            ├── cart.js       # 购物车模块
            └── products.js   # 产品模块

    https://vuex.vuejs.org/zh-cn/...

    一个 vuex 小例子

    父组件
    
    
    
    
    apple 组件
    
    
    
    
    banana 组件
    
    
    
    
    main.js
    // The Vue build version to load with the `import` command
    // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
    import Vue from "vue"
    import Vuex from "vuex"
    import App from "./App"
    import router from "./router"
    
    
    Vue.config.productionTip = false
    
    Vue.use(Vuex);
    let store = new Vuex.Store({
      state:{
        total:0,
        appleTotal:0,
        bananaTotal:0,
      },
      getters:{
        getTotal(state){
          return state.total
        }
      },
      mutations:{
        aSetValue(state,value){
          state.appleTotal = value
          state.total = state.appleTotal + state.bananaTotal;
        },
        bSetValue(state,value){
          state.bananaTotal = value
          state.total = state.appleTotal + state.bananaTotal;
        }
      },
      actions:{
        doAfn(context,price){
          context.commit("aSetValue",price)
        },
        doBfn(context,price){
          context.commit("bSetValue",price)
        }
      }
    })
    
    
    
    /* eslint-disable no-new */
    new Vue({
      el: "#app",
      store,
      router,
      components: { App },
      template: ""
    })
    

    文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

    转载请注明本文地址:https://www.ucloud.cn/yun/92520.html

    相关文章

    • vue 项目要点总结(二)

      摘要:静态图片怎么引入对重复元素的遍历产品数据统计数据预测流量分析广告发布在重复的部分用如果某个重复的部分比较分散可用循环,循环是从标签本身就开始的既是的载体,也是与同一个标签的灵活使用遍历的时候可以接受几种赋值方式直接绑定的属性 静态logo图片怎么引入 showImg(https://segmentfault.com/img/bV2iRj?w=350&h=163); 对重复元素...

      liuhh 评论0 收藏0
    • 记一次前端项目重构要点总结

      摘要:重构总共耗时个工作日。第一个重构原因就是没有引入静态类型,导致查看一个对象结构需要翻来覆去在多个文件中查找。第三是各个状态模块耦合度高,加大了代码维护难度。但如果耦合度过高,往往是因为模块没有细分到位。这个项目也不列外。 showImg(https://segmentfault.com/img/remote/1460000019660483); 不知不觉已是2019年的7月,恍惚之间已...

      frolc 评论0 收藏0
    • Vue下滚动到页面底部无限加载数据Demo

      摘要:下滚动到页面底部无限加载数据看到一篇觉得挺实用的就看了下顺便简单翻译了一下给需要的人参考从这个项目中可以加深对的生命周期的理解何时开始请求如何结合使用原生来写事件等等我这里主要是对原文的重点提取和补充本文技术要点生命周期简单用法格式化日期图 Vue下滚动到页面底部无限加载数据Demo 看到一篇Implementing an Infinite Scroll with Vue.js, 觉得...

      elarity 评论0 收藏0
    • 重学前端学习笔记(一)--前端发展史以及学习痛点

      摘要:笔记说明重学前端是程劭非前手机淘宝前端负责人在极客时间开的一个专栏,每天分钟,重构你的前端知识体系,笔者主要整理学习过程的一些要点笔记以及感悟,完整的可以加入的专栏学习原文有的语音,如有侵权请联系我,邮箱。 笔记说明 重学前端是程劭非(winter)【前手机淘宝前端负责人】在极客时间开的一个专栏,每天10分钟,重构你的前端知识体系,笔者主要整理学习过程的一些要点笔记以及感悟,完整的可以...

      hlcfan 评论0 收藏0
    • 重学前端学习笔记(一)--前端发展史以及学习痛点

      摘要:笔记说明重学前端是程劭非前手机淘宝前端负责人在极客时间开的一个专栏,每天分钟,重构你的前端知识体系,笔者主要整理学习过程的一些要点笔记以及感悟,完整的可以加入的专栏学习原文有的语音,如有侵权请联系我,邮箱。 笔记说明 重学前端是程劭非(winter)【前手机淘宝前端负责人】在极客时间开的一个专栏,每天10分钟,重构你的前端知识体系,笔者主要整理学习过程的一些要点笔记以及感悟,完整的可以...

      wayneli 评论0 收藏0

    发表评论

    0条评论

    最新活动
    阅读需要支付1元查看
    <