用前端技术开发的商城整站
项目已部署上线,你可抢先体验: http://imooc.51purse.com/
收费项目介绍: http://coding.imooc.com/class/113.html
Model
和View
解耦Controller
控制DOM
MVC
模式Model
绑定View
Vue本身并不是一个框架,但结合周边生态构成一个灵活的、渐进式的框架 Vue核心思想:1.数据驱动 2.组件化
vue发展历程:
vue 0.11
、vue 1.0
、vue2.0
vue
数据双向绑定的原理,利用Object.defineProperty()
方法,这个方法是给对象添加属性,并且它自身包含get
和set
两个api
。通过keyup
事件,改变userName
属性的值去触发它的set
方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input type="text" id="userName">
<br>
<span id="uName"></span>
<script>
var obj = {
pwd:"123456"
};
Object.defineProperty(obj,"userName",{
get:function () {
console.log("log get init");
},
set:function (val) {
console.log("log set init");
document.getElementById("uName").innerText = val;
document.getElementById("userName").value = val;
}
});
document.getElementById("userName").addEventListener("keyup",function (envet) {
document.getElementById("uName").innerText = envet.target.value;
})
</script>
</body>
</html>
Webpack:代码模块化构建打包工具
Gulp:基于流的自动化构建工具
Grunt:Javascript
世界的构建工具
Babel:使用最新的规范来编写js
Vue:构建数据驱动的web
界面的渐进式框架
Express:基于Node.js
平台,快速,开放,极简的web
开发框架
npm install -g npm
npm list
node
文件名npm i vue --save
/usr/local/lib/node_modules
npm root -g
npm install -g cnpm --registry=https://registry.npm.taobao.org
最简单的Vue
实例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--在线引用Vuejs如下:-->
<!--<script src="https://vuejs.org/js/vue.js"></script>-->
<!--本地安装后引用Vuejs-->
<script src="node_modules/vue/dist/vue.min.js"></script>
</head>
<body>
<div id="app">
<span>{{message}}</span>
</div>
<script>
new Vue ({
el:"#app",
data:{
message:"hello, Vue!"
}
});
</script>
</body>
</html>
cnpm i vue-cli -g
利用 Vue 初始化一个简单的 webpack 项目 :
vue init webpack-simple demo5
注意: 项目名称必须小写
MingodeMacBook-Pro:vueMall Mingo$ vue init webpack-simple demo5
? Project name demo5
? Project description A Vue.js project
? Author 袁凤鸣 <yfmingo@163.com>
? Use sass? No
vue-cli · Generated "demo5".
To get started:
cd demo5
npm install
npm run dev.
MingodeMacBook-Pro:vueMall Mingo$
说明:其中生成的 .babelrc
文件是ES6
编译插件配置。
vue init webpack demo6
代码如下:
MingodeMacBook-Pro:demo6 Mingo$ vue init webpack demo6
? Project name demo6
? Project description A Vue.js project
? Author 袁凤鸣 <yfmingo@163.com>
? Vue build standalone
? Install vue-router? Yes
? Use ESLint to lint your code? No
? Setup unit tests with Karma + Mocha? No
? Setup e2e tests with Nightwatch? No
vue-cli · Generated "demo6".
To get started:
cd demo6
npm install
npm run dev
Documentation can be found at https://vuejs-templates.github.io/webpack
以上说明:
? Install vue-router?
:是否需要路由
? Use ESLint to lint your code?
是否需要 ESLint
(语法检查),刚开始入门建议不需要
? Setup unit tests with Karma + Mocha?
是否需要单元测试
? Setup e2e tests with Nightwatch?
是否需要端到端测试
通过vue init webpack-simple demo
创建项目:
src
是项目源码,.babelrc
编译ES6
插件的配置,readme.md
说明文件,webpack.config
配置。
要运行项目,首先cnpm i
下载依赖的插件,第二步cnpm run dev
build打包配置文件所在的文件夹,config是webpack
对应的配置,src是开发项目的源码,App.vue是入口组件,main.js项目入口文件,static资源文件件,babelrc是ES6
解析的配置,postcssrc是html
添加前缀的配置,dependencies是项目依赖库,devDependencies是开发依赖库,devDependencies在打包的时候需要,打包后就没有了
package.json
中的script
是shell
脚本命令,做spa
开发只需要关注几个页面:
build/webpack.base.conf.js打包核心配置 config/index.js其实可以和build/webpack.base.conf.j
s合并成一个,但是spa
想做一个清晰的架构,所以拆开了 以上两个核心关注,其他都是辅助关系 初学者都要有个初步认识
build/build.js构建生产版本,项目开发完成,使用这个打生产包
var config = require(‘../config’) require
一个文件夹,会默认加载里面的index.js
文件,这个写的时候是可以省略,也是相当于=require('../config/index.js')
。但如果是里面的非index.js
文件,require
时则不可省略。
https://www.npmjs.com/package 将npm安装的插件放在这个网址后面就可以看到插件的对应信息,例如 https://www.npmjs.com/package/vue
active
是类名,isActive
是true
或者false
v-bind:class=”[activeClass,errorClass]” 这里activeClass
,errorClass
是2个变量,具体的类名在data
中定义
v-cloak
可以进行隐.stop 阻止冒泡,.prevent 阻止默认事件,.self 只给本身绑定事件(如果有子元素,点击子元素没有作用),.once 只给事件绑定一次
this.$emit("incre")
自定义了一个incre
事件,在父组件中绑定@incre="increment"
,而increment
这个方法是写在父组件中的。也就是说父组件绑定了子组件的事件来控制父组件的方法来操作父组件的元素jquery
里面的trigger
)来执行父组件的函数,从而改变父组件数据。 如果想要子组件传值给父组件,通过 this.$emit(‘自定义事件名’,’想传的值’)传递给父组件,父组件的该自定义事件回调方法的入参,即为你想传递的值。props
必须为数组vue
的核心思想:数据驱动,组件开发。 在webpack.base.config
配置后,引入.vue
文件,可以省略.vue
this.$emit(‘chuandi’) 父组件可以监听到子组件的chuandi
事件 methods:{ incre(){} }dom
都没有,v-show 只是display:none
components
文件夹一般放复用的组件,同时可以新建一个 views
放单独的页面hash
,路由带#
号,改为history
后,可去掉#
号,表现为常见的路由形式router
文件夹下的index.js
修改路由 src
里的views
文件夹放页面,里面也是.vue结尾的文件,本质上一样的。 router
里面配置默认渲染的组件,可以修改让它加载其他页面,@
被配置成了一个别名,映射到了src
文件夹目录 {{$route.params.goodsId}}拿到路径path:'/goods/:goodsId'
,中的参数 {{$route.params.name}}path: '/goods/:goodsId/user/:name'
, 路由是对history
的封装 路由模式有mode:'history'
和 mode:'hash'
两种
演示代码:
index.js
:
import Vue from 'vue'
import Router from 'vue-router'
import GoodsList from './../views/GoodsList'
Vue.use(Router)
export default new Router({
mode:'history',
routes: [
{
path: '/goods/:goodsId/user/:name',
name: 'GoodsList',
component: GoodsList
}
]
})
GoodsList.vue :
<template>
<div>
这个商品列表页面
<span>{{$route.params.goodsId}}</span><br>
<span>{{$route.params.name}}</span>
</div>
</template>
<style >
</style>
<script >
export default {
data (){
return {
msg:'hello Vue!'
}
}
}
</script>
import Vue from 'vue'
是es6的语法,用来导入模块 webpach
里的别名配置:@
: resolve('src')
其中@
就代表了src
文件夹的绝对路径 用children:[{},{}]
的方式定义子组件演示代码:
GoodsList.vue
中代码:
<template>
<div>
这个商品列表页面
<span>{{$route.params.goodsId}}</span><br>
<span>{{$route.params.name}}</span>
<router-link to="/goods/Title">显示商品标题</router-link>
<router-link to="/goods/Img">显示商品图片</router-link>
<div>
<router-view> </router-view>
</div>
</div>
</template>
<style >
</style>
<script >
export default {
data (){
return {
msg:'hello Vue!'
}
}
}
</script> **特别注意:** `<router-link to="/goods/Title">`中的 to 地址不要写错了 。to 地址一定写绝对地址(就是子路由最终会映射到的地址)
其demo中 Title.vue
和 Image.vue
一样只是文字不同:
<template>
<div>
这里是商品标题子组件
</div>
</template>
<style >
</style>
<script >
export default {
data (){
return {
msg:'hello Vue!'
}
}
}
</script>
编程路由常用方式方法总结(附已知路由间切换的2个方式):
代码演示:
GoodsList.vue
中:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Title</title>
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="node_modules/vue/dist/vue.js"></script>
<script src="node_modules/vue-resource/dist/vue-resource.js"></script>
</head>
<body>
<div id="app" class="container">
<h1>vue-resource插件请求讲解</h1>
<a href="javascript:;" class="btn btn-primary" v-on:click="get">Get请求</a>
<a href="javascript:;" class="btn btn-primary">Post请求</a>
<a href="javascript:;" class="btn btn-primary">JSONP请求</a>
<div>
<span>{{msg}}</span>
</div>
</div>
<script>
new Vue ({
el:"#app",
data:{
msg:""
},
methods:{
get:function () {
this.$http.get("package1.json",{
params:{
userId:"101"
},
headers:{
token:"abcd"
}
}).then(res=>{
this.msg = res.data;
},error=>{
this.msg = error;
});
}
}
});
</script>
</body>
</html>
:
”这是会对等号后面的值先运算编译再赋值代码演示:
app.vue
中代码:
<template>
<div id="app">
<img src="./assets/logo.png">
<router-view class="main"></router-view>
<router-view class="left" name="title"></router-view>
<router-view class="right" name="img"></router-view>
</div>
</template>
<script>
export default {
name: 'app'
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
.left,.right {
float: left;
width: 49%;
border: 1px solid gray;
}
</style>
GoodsList.vue
中代码:
<template>
<div>
这个商品列表页面
<span>{{$route.params.goodsId}}</span><br>
<span>{{$route.params.name}}</span>
<router-link to="/goods/Title">显示商品标题</router-link>
<router-link to="/goods/Img">显示商品图片</router-link>
<div>
<router-view> </router-view>
</div>
<!-- 带参数的命名路由 -->
<router-link v-bind:to="{name:'cart',params:{cartId:123}}">跳转到购物车页面</router-link>
</div>
</template>
<style >
</style>
<script >
export default {
data (){
return {
msg:'hello Vue!'
}
},
methods:{
jump(){
// this.$router.push("/cart")
this.$router.push({path:'/cart?goodsId=123'})
// this.$router.go(-2) //后退两步
}
}
}
</script>
vue-resource.html
中代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Title</title>
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="node_modules/vue/dist/vue.js"></script>
<script src="node_modules/vue-resource/dist/vue-resource.js"></script>
</head>
<body>
<div id="app" class="container">
<h1>vue-resource插件请求讲解</h1>
<a href="javascript:;" class="btn btn-primary" v-on:click="get">Get请求</a>
<a href="javascript:;" class="btn btn-primary" v-on:click="post">Post请求</a>
<a href="javascript:;" class="btn btn-primary" v-on:click="jsonp">JSONP请求</a>
<a href="javascript:;" class="btn btn-primary" v-on:click="http">http配置参数请求</a>
<div>
<span>{{msg}}</span>
</div>
</div>
<script>
new Vue ({
el:"#app",
data:{
msg:""
},
mounted:function () {
// 全局拦截器处理。可以拦截请求前和请求后的事件。可用在请求前加loding HUD
Vue.http.interceptors.push(function (request,next) {
console.log("request init");
next(function (respose) {
console.log("respose init");
return respose;
});
});
},
http:{
// root:"这里面可以放主域名头地址"
},
methods:{
get:function () {
this.$http.get("package.json",{
params:{
userId:"101"
},
headers:{
token:"abcd"
}
}).then(res=>{
this.msg = res.data;
},error=>{
this.msg = error;s
});
},
post:function () {
this.$http.post("package.json",{
userId:"102"
},{
headers:{
access_token:"abd"
}
}).then(res=>{
this.msg = res.data;
},error=>{
this.msg = error;
})
},
jsonp:function () {
this.$http.jsonp("http://www.imooc.com/course/AjaxCourseMembers?ids=796").then(res=>{
this.msg = res.data;
})
},
http:function () {
this.$http({
url:"package.json",
method:"GET",
params:{
userId:"103"
},
headers:{
token:"abc123"
},
timeout:50,
before:function () {
console.log("before init")
}
}).then(function (res) {
this.msg = res.data;
});
}
}
});
</script>
</body>
</html>
Get调试结果:
Post调试结果:
JsonP调试结果:
http配置参数请求调试结果:
全局拦截器使用:可以拦截请求前后的事件。一般正在加载loading HUD 需要用。
演示代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Title</title>
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="node_modules/vue/dist/vue.js"></script>
<script src="node_modules/vue-resource/dist/vue-resource.js"></script>
</head>
<body>
<div id="app" class="container">
<h1>vue-resource插件请求讲解</h1>
<a href="javascript:;" class="btn btn-primary" v-on:click="get">Get请求</a>
<a href="javascript:;" class="btn btn-primary" v-on:click="post">Post请求</a>
<a href="javascript:;" class="btn btn-primary" v-on:click="jsonp">JSONP请求</a>
<div>
<span>{{msg}}</span>
</div>
</div>
<script>
new Vue ({
el:"#app",
data:{
msg:""
},
mounted:function () {
// 全局拦截器处理。可以拦截请求前和请求后的事件。可用在请求前加loding HUD
Vue.http.interceptors.push(function (request,next) {
console.log("request init");
next(function (respose) {
console.log("respose init");
return respose;
});
});
},
http:{
// root:"这里面可以放主域名头地址,做到提取接口主域名的作用"
},
methods:{
get:function () {
this.$http.get("package.json",{
params:{
userId:"101"
},
headers:{
token:"abcd"
}
}).then(res=>{
this.msg = res.data;
},error=>{
this.msg = error;s
});
},
post:function () {
this.$http.post("package.json",{
userId:"102"
},{
headers:{
access_token:"abd"
}
}).then(res=>{
this.msg = res.data;
},error=>{
this.msg = error;
})
},
jsonp:function () {
this.$http.jsonp("http://www.imooc.com/course/AjaxCourseMembers?ids=796").then(res=>{
this.msg = res.data;
})
}
}
});
</script>
</body>
</html>
结果调试:
提取接口主域名头:
(使用可见上面演示代码)
http:{
//root:"这里面可以放主域名头地址,做到提取接口主域名的作用"
}
axios.all
可一起调用和处理多个接口的返回是挂在
vue上的,而
axios没有挂在
vue`
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Title</title>
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="node_modules/vue/dist/vue.js"></script>
<script src="node_modules/axios/dist/axios.js"></script>
</head>
<body>
<div id="app" class="container">
<h1>axios插件请求讲解</h1>
<a href="javascript:;" class="btn btn-primary" v-on:click="get">Get请求</a>
<a href="javascript:;" class="btn btn-primary" v-on:click="post">Post请求</a>
<a href="javascript:;" class="btn btn-primary" v-on:click="http">http配置参数请求</a>
<div>
<span>{{msg}}</span>
</div>
</div>
<script>
new Vue ({
el:"#app",
data:{
msg:""
},
mounted:function () {
},
methods:{
get:function () {
axios.get("package.json",{
params:{
userId:"999"
},
headers:{
token:"Jack"
}
}).then(res=>{
this.msg = res.data;
}).catch(error=>{
console.log("error init"+error)
});
},
post:function () {
axios.post("package.json",{
userId:"666"
},{
headers:{
token:"www.yfming.cn"
}
}).then(res=>{
this.msg = res.data;
}).catch(error=>{
console.log("error init"+error)
});
},
http:function () {
axios({
url:"package.json",
method:"POST",
data:{
userId:"111"
},
// // 注意: POST请求时参数在data里面定义;GET请求时参数要在 params 中定义
// params:{
// userId:"222"
// },
headers:{
token:"eeeee"
}
}).then(res=>{
this.msg = res.data;
})
}
}
});
</script>
</body>
</html>
axios的GET调试:
axios的POST调试:
mounted:function () {
//全局拦截器:
//请求前拦截
axios.interceptors.request.use(function (config) {
console.log("可以在这里写加载HUD");
return config;
})
// 请求后拦截
axios.interceptors.response.use(function (response) {
console.log("response init ");
return response;
})
},
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
¥ 打赏博主上一篇 常用正则表达式和正则学法收集
下一篇 Vue2.0+Node.js+MongoDB全栈打造商城系统(5—6章)
两个鬼故事调动申请书鞋子商标起名字刚出生的男起名字免费个人网站模板寒冰王座颐指气使是什么意思疾风拂晓描写雪景超唯美的段落钢琴调音重返1977猪年宝宝小名怎么起科技公司怎么起名称大全烤翅一绝加盟店春节古诗大全50首润字起名大全智慧记引力常量如来神掌龙剑飞女孩以月字起名大全特种神医姓祝男孩子起名大型网游排行榜公司起名地坪微交易之家漫画滤镜道德经公司起名大地飞鹰茶楼起个名字一笙有喜倒霉熊第一部少年生前被连续抽血16次?多部门介入两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”淀粉肠小王子日销售额涨超10倍高中生被打伤下体休学 邯郸通报单亲妈妈陷入热恋 14岁儿子报警何赛飞追着代拍打雅江山火三名扑火人员牺牲系谣言张家界的山上“长”满了韩国人?男孩8年未见母亲被告知被遗忘中国拥有亿元资产的家庭达13.3万户19岁小伙救下5人后溺亡 多方发声315晚会后胖东来又人满为患了张立群任西安交通大学校长“重生之我在北大当嫡校长”男子被猫抓伤后确诊“猫抓病”测试车高速逃费 小米:已补缴周杰伦一审败诉网易网友洛杉矶偶遇贾玲今日春分倪萍分享减重40斤方法七年后宇文玥被薅头发捞上岸许家印被限制高消费萧美琴窜访捷克 外交部回应联合利华开始重组专访95后高颜值猪保姆胖东来员工每周单休无小长假男子被流浪猫绊倒 投喂者赔24万小米汽车超级工厂正式揭幕黑马情侣提车了西双版纳热带植物园回应蜉蝣大爆发当地回应沈阳致3死车祸车主疑毒驾恒大被罚41.75亿到底怎么缴妈妈回应孩子在校撞护栏坠楼外国人感慨凌晨的中国很安全杨倩无缘巴黎奥运校方回应护栏损坏小学生课间坠楼房客欠租失踪 房东直发愁专家建议不必谈骨泥色变王树国卸任西安交大校长 师生送别手机成瘾是影响睡眠质量重要因素国产伟哥去年销售近13亿阿根廷将发行1万与2万面值的纸币兔狲“狲大娘”因病死亡遭遇山火的松茸之乡“开封王婆”爆火:促成四五十对奥巴马现身唐宁街 黑色着装引猜测考生莫言也上北大硕士复试名单了德国打算提及普京时仅用姓名天水麻辣烫把捣辣椒大爷累坏了