(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 属性负责接收参数
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',
// ...
])
}
}
服务器如果需要请求多次数据库查询并返回相应结果,可以通过定义全局变量记录,只有当所有请求结束时才向客户端发送结果
新闻列表/新闻详细
-创建空组件 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:{}}
新闻评论
-创建表 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)在父组件中调用子组件
<子组件名称>子组件名称>
发表评论
用户点击新闻列表某一条新闻,看到新闻详细发表评论
-用户输入评论内容
-发表评论 [将用户评论内容保存数据库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(“评论内容不能为空”);
商品详情
1-创建空组件 src/components/goods/GoodInfo.vue
2-添加访问路径 /GoodInfo
3-添加 card.html 卡片布局
4-创建 src/components/sub/swiperBox.vue 子组件
5*-swiperBox.vue 当父组件调用子组件时传递数组
GoodInfo.vue 商品名称; 价格;数量 1
添加购物车
*-获取当前商品编号
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()
用户登录
(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
购物车
购物车保存用户想购买商品的临时对象,可以保存在数据库或者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查询购物车所有数据
购物车删除多个商品
(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”/>
用户登录
-在脚手架登录陆组件表单,让用户输入用户名和密码
点击登录按钮后在服务器验证,如果验证成功
登录自动跳转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;
购物清单数量
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(“修改数据方法名”)
获取全局共享数据: { {$store.getter.获取数据方法名}}
示例:将购物车中数据添加全局共享数据中
state:{cartCount:0}
mutations:{
increment(state){
state.cartCount++;
}
},
getters:{
getCartCount(state){
return state.cartCount;
}
}
this.$store.commit("increment");
App.vue {
{$store.getters. getCartCount}}
#依据购物车中商品数据修改全局共享数据值
#(1)当用户查询购物车 更新全局共享数据值
2:时机不正确,登录成功立即更新购物数据
3:刷新全局丢失
2.1:vuex共享数据刷新状态丢失
原因:vuex刷新vuex认为刷新加载全局数据
提供解决方法:
使用sessionStorage 辅助保存vuex全局数据,依赖vuex通知
其它组件更新数据
state:{
cartCount:sessionStorage.getItem("cartCount")||0
},
mutations:{
sub(state,count){state.cartCount=count;
sessionStorage.setItem("cartCount",count)
}
},
2.2:登录成功修改共享数据
登录成功 ajax /login
再次发送ajax获取购物车商品数据
更新数量
修改在购物车列表修改全局购物车商品数量
商城搜索
select lid,lname from xz_laptop where lname like ? limit ?,?
pool.query(sql, [’%’+key+’%’, offset, pageSize], (err,result)=>{})
获取form表单提交的值
e.detail.value.name