VUE_UI_2.组件跳转、传参、vuex

组件跳转、传参

  • 1 组件间跳转及传参
  • 2 vuex多组件共享数据
  • 3 示例

1 组件间跳转及传参

(1)标签方式跳转(优先选)

   
     .....
   
   示例:Home.vue -> NewsList.vue
   
    

(2)编程序方式跳转

   this.$router.push("组件路径");
   示例:
   
   jump(){
     this.$router.push("/NewsList");
   }
   示例:
   Exam01.vue -> NewsList.vue
   

跳转NewsList.vue 组件

jump(){ this.$router.push("/NewsList") }

(3)组件之间跳转传递参数

   Exam01.vue ->NewsList.vue
   ?nid=6
   -传递参数 Exam01.vue   
    this.$router.push("/NewsList?nid=6")
   -接收参数 NewsList.vue 
    var id = this.$route.query.nid;
    #通常情况接收参数 created()
  #$router  属性负责组件之间跳转 
  #$route   属性负责接收参数

2 vuex多组件共享数据

store.js 文件

import Vue from "vue"
import Vuex from "vuex"
Vue.use(vuex)

export default new Vuex.Store({
    state:{},
    mutations:{}
})

1)Vuex的使用
main.js文件导入vuex和store.js文件后,在new Vue实例对象中实例化,在组件中使用this.$store.commit(‘increment’),this.$store.state.count调用store.js中的state和mutations中的方法,this指向的是Vue实例对象

2)关于$store和store的区别
$store 是挂载在 Vue 实例上的(即Vue.prototype),而组件也其实是一个Vue实例,在组件中可使用 this 访问原型上的属性,template 拥有组件实例的上下文,可直接通过 { { $store.state.userName }} 访问,等价于 script 中的 this.$store.state.userName;
至于 { { store.state.userName }},script 中的 data 需声明过 store 才可访问。

3)mutations函数调用内部的其他函数,只需要this.commit(’’),this指向的是mutations;使用数据state,只需要函数参数传值state。
反思:为什么组件中方法访问data中的数据this.val,而Vuex.store传值state?
因为data是函数调用,返回数据对象,state通过参数方式传入变量

4)辅助函数mapState
当组件需要多个状态,为了减少生成computed属性重复和冗余,引入mapState辅助函数生成computed属性

computed: mapState([
  // 映射 this.count 为 store.state.count
  'count'
])

等价于

import { mapState } from 'vuex'

export default {
  // ...
  computed: mapState({
    // 箭头函数可使代码更简练
    count: state => state.count,

    // 传字符串参数 'count' 等同于 `state => state.count`
    countAlias: 'count',

    // 为了能够使用 `this` 获取局部状态,必须使用常规函数
    countPlusLocalState (state) {
      return state.count + this.localCount
    }
  })
}

由于mapState函数返回数组对象,所以如果需要与其他计算属性混合使用时需要打散

computed: {
  localComputed () { /* ... */ },
  // 使用对象展开运算符将此对象混入到外部对象中
  ...mapState({
    // ...
  })
}

5)getters
getters相当于store中的computed属性,属于state的衍生状态,根据依赖的值返回缓存并仅当依赖发生改变才重新计算
this.$store.getters.xxx
如果getter通过方法访问,则不缓存结果
使用mapGetters辅助函数将 store 中的 getter 映射到局部计算属性

import { mapGetters } from 'vuex'

export default {
  // ...
  computed: {
  // 使用对象展开运算符将 getter 混入 computed 对象中
    ...mapGetters([
      'doneTodosCount',
      'anotherGetter',
      // ...
    ])
  }
}

3 示例

服务器如果需要请求多次数据库查询并返回相应结果,可以通过定义全局变量记录,只有当所有请求结束时才向客户端发送结果

  1. 新闻列表/新闻详细
    -创建空组件 src/components/home/NewsInfo.vue
    -添加组件访问路径 /NewsInfo
    -检查 NewsList.vue 新闻列表
    标签跳转

    
    
    

    编程方式 ?nid=变量
    -创建ajax 请求获取新闻详细信息
    -node.js /findNewsInfo
    参数:id
    验证参数是否合法: /^\d{1,}$/
    sql: SELECT id,title,content,ctime,img_url FROM xz_news WHERE id=?
    json:{code:1,data:[]}
    -保存当前 data:{info:{}}

  2. 新闻评论
    -创建表 xz_comment[id;content;ctime;nid]
    -创建服务器程序 /getComment
    参数:nid 新闻id
    sql:SELECT id,content,ctime,nid FROM xz_comment WHERE nid=?
    json:{code:1,data:[]}
    -创建空子组件 src/components/sub/comment.vue
    -在新闻组件中添加评论子组件
    (1)在父组件引入子组件
    import comment from “…/sub/comment.vue”
    (2)在父组件注册子组件并且指定子组件标签名称
    components:{
    “子组件名称”: comment
    }
    (3)在父组件中调用子组件
    <子组件名称>

  3. 发表评论
    用户点击新闻列表某一条新闻,看到新闻详细发表评论
    -用户输入评论内容
    -发表评论 [将用户评论内容保存数据库xz_comment[id,content,ctime,nid]

    创建程序接收评论内容添加
    (1)用户请求方式 POST app.post("/addcomment")
    (2)请求参数 content,nid
    2.1:post获取参数 下载安装第三方模块 body-parser
    2.2:post获取参数 配置模块
    2.3:post 获取参数 req.body.nid req.body.content
    (3)SQL INSERT INTO xz_comment VALUES(null,?,now(),?)
    (4)JSON {code:1,msg:“发表成功”}

    -引入第三方模板 qs
    1.1:下载npm i qs 模块
    1.2:在main.js 引入qs模块 import qs from ‘qs’;
    1.3:在main.js Vue对象属性 Vue.prototype.qs = qs;
    1.4 comment.vue
    var postData = this.qs.stringify({
    nid:9,
    content:"…"
    })
    this.axios.post(“127…”, postData).then(result=>{
    })//也可以直接将post第二个参数写成字符串形式nid=9&content=…
    -在comment.vue 添加mint-ui Toast
    由Toast只有在comment.vue 等少数组件中使用
    (1)在当前组件引入 import {Toast} from “mint-ui”
    (2)立即调用 Toast(“评论内容不能为空”);

  4. 商品详情
    1-创建空组件 src/components/goods/GoodInfo.vue
    2-添加访问路径 /GoodInfo
    3-添加 card.html 卡片布局
    4-创建 src/components/sub/swiperBox.vue 子组件
    5*-swiperBox.vue 当父组件调用子组件时传递数组
    GoodInfo.vue 商品名称; 价格;数量 1

  5. 添加购物车
    *-获取当前商品编号
    GoodList.vue -> GoodInfo.vue 参数pid
    (1)为商品列表中每一张图片绑定点击事件
    跳转GoodInfo.vue 组件
    参数 ?pid=2
    #通用参数从模板传递事件处理函数

    jumpInfo(e){
    var pid = e.target.dataset.lid;
    this.$router.push("/GoodInfo?pid="+pid)
    }
    -发送ajax 获取商品名称 价格
    node.js
    参数:pid
    sql: SELECT lname,price FROM xz_laptop WHERE lid = ?
    json {code:1,data:[]}
    GoodInfo.vue
    -data:{info:{}}
    -methods:{findGood} result.data.data[0]
    -created()

  6. 用户登录
    (1)数据库 xz_login 用户登录表[id;uname;upwd]
    id INT
    uname VARCHAR(25)
    upwd VARCHAR(32) 加密处理
    xz_login
    1 tom 123
    2 jerry 123
    知识扩展:加密通过复杂算法将明文加密转换密文保存
    原来密码 123(明文) 加密 219ds98kjkjds9832wiu32(密文)
    知识扩展:单向加密 md5 加密
    在mysql数据库有一个函数md5(‘123’)
    知识扩展:如何提高安全性 让用户密码8位以上
    大写小写数字特殊符号 ABcOO0_9
    操作: upwd VARCHAR(32)
    (2)node.js(技巧)
    -请求方法 get 请求地址 /login
    -参数 用户名密码
    -sql SELECT id FROM xz_login
    WHERE uname = ? AND upwd = md5(?)
    技巧:用户输入密码加密后与数据库密文比较
    pool.quey(sql,[uname,upwd],(err,result)=>{
    if(result.length==0) 用户名或密码错误
    })
    -json {code:1,msg:“登录成功”}
    {code:-1,msg:“用户名或密码错误”}
    (3)脚手架表单
    *-创建组件 src/components/home/Login.vue
    *-组件分配路径 /Login
    *-创建卡片 mui
    *-在卡片创建表单
    #不要添加action属性
    #登录按钮
    -为 button绑定点击事件发送 ajax
    (4)如果用户登录成将用户编号 id保存服务器端对象
    session

  7. 购物车
    购物车保存用户想购买商品的临时对象,可以保存在数据库或者cookie
    数据库
    xz_cart 购物车表 id count price pid uid
    id 编号;count 购买数量;price 购买时价格;pid 购物商品编号;uid 登录用户编号
    1)将商品添加至购物车-node.js(重点 非阻塞)
    请求方式 GET 请求路径 /addcart
    参数:pid/count/uid/price
    sql:
    -查询当前用户是否己经将商品添加至购物车
    SELECT id FROM xz_cart WHERE pid = ? AND uid = ?
    -更新数量
    UPDATE xz_cart SET count=count+ num WHERE pid=? AND uid=?
    -将商品信息添加购物车
    INSERT INTO …
    json
    {code:1,msg:“商品添加成功”}
    2)商品添加至购物车-脚手架
    (1)GoodInfo.vue
    (2)有一个按钮 "加入购物车 "
    (3)绑定点击事件
    (4)pid uid=1 price
    3)购物车列表/全选/清空/批量删除/删除/…
    (1)库xz_cart[id/count/price/pid/uid]
    (2)node.js查询购物车所有数据

    • 参数 uid
    • sql SELECT id,count,price,pid,uid,lname
      xz_cart/xz_laptop
      -json {code:1,data:[]}
      (3)脚手架对应组件显示购物车
      *-创建空组件 src/components/home/ShopCart.vue
      *-为组件分配路径 /ShopCart
      *-mui组件库 card组件
      *-中间循环显示购物车中商品内容
      [ ] 商品名称 价格 数量 (删除)
  8. 购物车删除多个商品
    (1)node.js
    -参数 ids “3,4”
    #参数需要选中购物id列表 多个商品格式: 3,8,9,4
    -sql DELETE FROM xz_cart WHERE id IN (3,8)
    -json {code:1,msg:“删除成功”}
    (2)脚手架
    [全选]
    list:[{id;pid;price}]
    list:[{id;pid;price;cb:false}]
    -将原先数据list中商品对象添加属性 cb:false 表示复选框状态

      data(){list:[....]}
      var rows = result.data.data;  //原有数组里所有属性双向绑定
      for(var item of rows){
         item.cb = false;        //后新添加属性不会双向绑定
       }
      this.list = rows;            //双向绑定  ok
    

    -完善购物全选按钮
    (1)为全选复选框绑定变量

    data(){ allcb=false}
    (2) selectAll(e){
    var cb = e.target.checked;
    this.allcb = cb;//修改双向绑定
    }
    (3)商品复选框前添加点击事件
    累加购物车列表中选中商品数量 3 allcb=true
    小于 3 allcb=false
    清除某个商品
    [*] @click=“modifyItem” :data-index=“i”/>

  9. 用户登录
    -在脚手架登录陆组件表单,让用户输入用户名和密码
    点击登录按钮后在服务器验证,如果验证成功
    登录自动跳转Home组件,在服务器记录用户登录成功
    -session 对象生存周期
    当用户登录成功后,创建session对象保存当前用户.
    登录成功后将uid保存session对象
    当我们查询购物车,获取session对象uid

    当我们关闭浏览器 session对象消失

    实现session存储uid并且其它功能使用uid功能
    node.js
    (1)验证跨域配置正常

    const cors = require("cors");
    app.use(cors({
     origin:["http://127.0.0.1:8080",
      "http://localhost:8080"],
      credentials:true
    }));
    

    (2)下载第三方模块 express-session并且对其配置

    const session = require("express-session");
    app.use(session({
      secret:"128位随机字符",  //自定义安全字符串
      resave:false,              //每次请求都需要更新session
      saveUninitialized:true,      //初始化是否保存数据
      cookie:{
         maxAge:1000*60*60*8  //依靠cookie保存8小时
       }
     }))
    

    (3)下面操作顺序
    3.1:先完成用户登录 req.session.uid = 2
    3.2:再完成其它功能 “购物车列表”… var uid = req.session.uid;
    #所有uid 参数不需从脚手架发送,服务器端己经保存uid
    3.3:添加购物车 req.session.uid
    脚手架
    main.js 配置跨域访问保存session即可
    axios.defaults.withCredentials=true;

  10. 购物清单数量
    2.1
    -购物车数量完成 vuex
    -刷新数据丢失解决sessionStorage保存数据
    2.2:Vuex 是一个仓库,Vuex核心对象store就是容器
    此容器存储所有组件共享数据
    当某一个组件修改共享数据,Vuex 知所有使用数据组件更新数据
    保证所有组件使用数据状态统一
    2.3:Vuex 使用方式
    -在main.js 下载引入并且创建配置vuex对象
    (0)npm i vuex
    (1)import Vuex from “vuex” //将vuex引入当前项目中
    (2)Vue.use(Vuex) //将vuex注册Vue实例中
    (3)

      var store = new Vuex.Store({  //创建Vuex实例对象
         state:{},
         mutations:{}
         getter:{}
       });
       state:     存储全局共享数据
       mutations: 修改全局共享数据方法 
       getter:     获取全局共享数据方法
    

    (3.1)new Vue({store })
    (4)其它组件操作全局共享数据
    修改全局共享数据: js this.$store.commit(“修改数据方法名”)
    获取全局共享数据: