前端的主流框架 Vue.js,Angular.js,*React.js *
安装
npm install vue
使用
Hmtl文件
<!--导入包-->
<script src="./node_modules/vue/dist/vue.js"></script>
//vue 控制这个元素
<div id="app">
{{ message }}
</div>
JS文件
// <!--创建一个Vue的实例-->
//在浏览器的内存中 就会多一个vue的构造函数
var app = new Vue({
// el 表示,当前我们new的这个Vue实例,要控制页面上的那个区域/元素
el:"#app",
//存放的是el要用的数据
data:{
message:"这是一个vue的开始"
}
//通过Vue提供的指令,很方便就能把数据渲染到页面上,我们不在手动操作DOM元素了,
});
v-cloak
指令 插值表达式 和v-text
及 v-html
指令
<style>
[v-cl0ak]{
display: none;
}
</style>
<p v-cloak>++++++{{msg}}+++++</p>
<h4 v-text="title">======</h4>
<!--
区别:v-text默认没有闪烁问题
v-text会覆盖元素的原本的内容,但是 插值表达式 只会替换自己的这个占位符,不会把整个元素的内容清空
-->
<div v-html="msg2">
<!--{{msg2}} v-text="msg2" 转义成字符串-->
<!--v-html="msg2" 是在div里面添加一个子标签-->
</div>
var vm = new Vue({
el:"#vm",
data:{
msg:"v-clok的介绍",
title:"白哦提案",
msg2:"<h1>这是一个h1标签的嘛</h1>",
mytitle:"自定义额按钮1",
// show:function () {
// window.alert("试试");
// }
},
methods:{
//定义方法
show:function () {
alert("btn按钮的方发");
}
}
});
v-bind
指令
// 这里v-bind指令将title属性与mytitle的值绑定在一起
<input type="button" value="按钮" v-bind:title = "mytitle">
// v-bind可以简写为 :
<input type="button" value="按钮" :title = "mytitle">
<!--在绑定的时候,拼接绑定内容::title="btnTitle + ', 这是追加的内容'" -->
v-on
事件绑定
<!--Vue中 提供了v-on来绑定事件 缩写是@-->
input type="button" value="按钮" :title = "mytitle" @click="show">
案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
#app{
padding-top: 10px;
margin-left: 10px;
}
.box{
padding-top: 20px;
}
/*[v-cloak]{*/
/*display: none;*/
/*}*/
</style>
<script src="node_modules/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<input type="button" value="浪起来" @click="show">
<input type="button" value="低调" @click="stop">
<div class="box" v-cloak>
{{msg}}
</div>
</div>
</body>
</html>
<!-创建实例-->
<script>
var app = new Vue({
el:"#app",
data:{
msg:"开始,浪七类!!!!",
timer:null
},
methods:{
show:function () {
var that = this;
// 在Vue实例中 如果想要获取data的数据或者methods里面的方法,必须通过this进行方法,this是Vue的实例对象
// 注意this指向问题
//判断是否存在
if (this.timer != null) return;
//定时器
this.timer = setInterval(function () {
var startStr = that.msg.substring(0,1);
var endStr = that.msg.substring(1);
that.msg = endStr + startStr;
},500)
},
stop:function () {
//清空定时器
clearInterval(this.timer);
//置位 null
this.timer = null;
}
}
})
</script>
事件修饰符
-
.stop
阻止事件冒泡 防止div事件传递 -
.prevent
阻止默认行为 -
.capture
添加事件监听器时使用事件捕获模式 -
self
当前元素自身时触发处理函数 -
.once
点击事件将只会触发一次
<div id="app">
<div class="inner" @click.self="divHander">
<!--.stop阻止事件冒泡 防止div事件传递-->
<!--<input type="button" value="点击" @click.stop="btnHandle">-->
<!--.prevent 阻止默认行为-->
<!--<a href="http://www.baidu.com" @click.prevent = "linkClick"> 点击去百度问一下</a>-->
<!--.capture 添加事件监听器时使用事件捕获模式 -->
<!--<div @click.capture = "captureClick">-->
<!--<input type="button" value="点击" @click.stop="btnHandle">-->
<!--</div>-->
<!--self 当前元素自身时触发处理函数 -->
<!--<div @click.self="selfClick">-->
<!--<input type="button" value="点击" @click="btnHandle">-->
<!--</div>-->
<!--.once 点击事件将只会触发一次 -->
<a href="http://www.baidu.com" @click.once.prevent = "linkClick"> 点击去百度问一下</a>
</div>
</div>
new Vue({
el:"#app",
data:{
},
methods:{
divHander:function () {
console.log("这是DIV");
},
btnHandle:function () {
console.log("这是按钮Btn");
},
linkClick:function () {
console.log("加载")
},
captureClick:function () {
console.log("铺货事件");
},
selfClick:function () {
console.log("自己自身时触发 方法");
}
}
})
键盘 按键修饰符
.enter
.tab
.delete
.esc
.space
.up
.down
.left
.right
- ``
- ``
v-model
数据的双向绑定
<div id="app">
<h4>
{{msg}}
</h4>
<!-- v-bind只能绑定属性,获取值,不能随之修改-->
<!--<input type="text" :value = "msg" style="width:300px">-->
<!-- v-model可以实现 数据的双向绑定 随时更改 简写: -->
<input type="text" v-model= "msg" style="width:300px">
new Vue({
el:"#app",
data:{
msg:"这是一个开始v-model双向数据绑定"
},
methods:{
}
})
Class和Style样式
- class数组
<style>
.red{
color: red;
}
.thin{
font-weight: 200;
}
.italic{
font-style: italic;
}
.active{
/*字体间距 中文使用*/
letter-spacing: 0.5em;
}
</style>
<!--第一种使用方式 -->
<!--数组里面的 要有单引号-->
<h1 :class="['red','thin','active']">这是一个H1得到,来阿里阿莱阿里啊!!!</h1>
<!---->
<!--数组中使用 三元表达式-->
<h1 :class="['red','thin',isflag?'active':'']">这是一个H1得到,来阿里阿莱阿里啊!!!</h1>
<!-- 对象代替三元表达式-->
<h1 :class="['red',{'active':isflag}]">这是一个H1得到,来阿里阿莱阿里啊!!!</h1>
<!--直接使用对象-->
<h1 :class="{active:isflag}">这是一个H1得到,来阿里阿莱阿里啊!!!</h1>
new Vue({
el:"#box",
data:{
isflag:true
}
})
- style
<div id="app">
<!--对象就是无序键值对的集合-->
<!--如果属性中有符号 要加单引号-->
<!--<h1 :style="objct1">这是一个h1标签</h1>-->
<h1 :style=[objct1,obect2]>这是一个h1标签</h1>
</div>
new Vue({
el:"#app",
data:{
objct1:{color:'red','font-weight':800},
obect2:{'font-size': '80px', 'font-style': 'italic'}
},
methods:{}
})
v-for
循环指令
- 遍历数组
// 标准是 item in items 其中items是数据数组 item是数组元素
<div id="app">
<ul>
<li v-for="(item,index) in items">
{{item.msg}} 索引是:{{index}}
</li>
</ul>
</div>
new Vue({
el:"#app",
data:{
items:[
{msg:"这是西部建设11"},
{msg:"这是西部建设22"},
{msg:"这是西部建设33"},
{msg:"这是西部建设44"},
{msg:"这是西部建设55"},
{msg:"这是西部建设66"}
],
}
})
- 遍历对象
<ul id="v-for-object" class="demo">
//只遍历 Value
<li v-for="value in object">
{{ value }}
</li>
</ul>
// key-value
<ul id="v-for-object" class="demo">
//注意语法
<li v-for="(value,key) in object">
{{key}}:{{ value }}
</li>
</ul>
//对应结果
firstName:John
lastName:Doe
age:30
//index-key -value 有参数 索引
<ul id="v-for-object" class="demo">
<li v-for="(value,key,index) in object">
{{key}}:{{ value }}
</li>
</ul>
//对应的结果
0 ----- firstName:John
1 ----- lastName:Doe
2 ----- age:30
new Vue({
el:"#v-for-object",
data:{
object: {
firstName: 'John',
lastName: 'Doe',
age: 30
}
}
})
过滤器
- 一般在2中情况下使用
插件表达式{{}}
和v-bind
表达式 - 格式:
<过滤的格式 {{ name | 过滤器的名称}}
,过滤器中的function
第一个参数已经被规定死了,永远是过滤器 管道符|
前面传过来的数据
Vue.filter("过滤器名称",function(data){
})
<div id="app">
<p>{{msg | msgForamt("疯狂是不是")}}</p>
</div>
JS文件
Vue.filter('msgForamt',function (msg,arg) {
console.log(msg);
//replace 方法,第一个参数,除了可写一个字符串外,还可以定义一个正则
// msg.replace('一个','邪恶')
// msg.replace(/一个/g,'邪恶')
return msg + ",哈哈哈哈" + arg;
})
new Vue({
el:"#app",
data:{
msg:"曾经,我也有梦想,也想成为一个大作家,一个人旅行,坐在一个安静的地方,慢慢的品茶"
},
methods:{
}
})
- 定义私有过滤器
html文件
<div id="app2">
<p>{{dt | strForamt}}</p>
</div>
JS文件
//定义一个私有的过滤器
new Vue({
el:"#app2",
data:{
dt:"这是一个私有过滤器的开始"
},
methods:{
},
//私有过滤器
filters:{
strForamt:function (dt) {
console.log(dt + "哈哈哈");
return dt + ",添加一个和喜爱和精细化静安寺"
}
}
});
自定义指令
<label>
搜索关键字:
<input type="text" class="form-control" v-model="keywords" v-focus >
</label>
//定义全局指令 让文本获取焦点
//参数一:指令的 名称,在定义的时候,指令前面,不需要加 v- 前缀,但是在调用的时候,必须在指令前面前 加上 v-前缀
//参数二:对象,这个对象 身上有一些指令 相关的处理函数,这些函数可以在特定的阶段,执行相应的操作
Vue.directive("focus",{
//每当指令绑定到元素上的时候,会立即执行这个bind函数,只执行一次
bind:function (el) {
// 在元素 刚绑定指令的时候,还没有 插入到DOM中去,这个时候,调用focus方法没有作用
//因为,一个元素,只有插入到DOM中才可以获取到焦点
//这个一般使用在样式上
},
//元素插入到DOM中的时候,会执行 inserted函数
inserted: function (el) {
// 聚焦元素
el.focus()
},
//当VNode更新时候,会执行updated,可能会出发多次
update:function (el) {
}
//注意:在每一个函数中,第一个参数,永远是el,表示被绑定了指令的那个元素,这个el参数,是一个原生的JS对象,可以用来直接操作DOM
// 第二个参数:binding 是一个对象 包含了一下几个属性
// name: 定义指令的名称,不包括 v-前缀
// value:指定的绑定值
// expression:指令绑定的表达式
});
vue实例的生命周期
- 什么是生命周期:从Vue实例创建、运行、到销毁期间,总是伴随着各种各样的事件,这些事件,统称为生命周期!
- 生命周期钩子:就是生命周期事件的别名而已;
- 生命周期钩子 = 生命周期函数 = 生命周期事件
- 主要的生命周期函数分类:
- 创建期间的生命周期函数:
- beforeCreate:实例刚在内存中被创建出来,此时,还没有初始化好 data 和 methods 属性
- created:实例已经在内存中创建OK,此时 data 和 methods 已经创建OK,此时还没有开始 编译模板
- beforeMount:此时已经完成了模板的编译,但是还没有挂载到页面中
- mounted:此时,已经将编译好的模板,挂载到了页面指定的容器中显示
- 运行期间的生命周期函数:
- beforeUpdate:状态更新之前执行此函数, 此时 data 中的状态值是最新的,但是界面上显示的 数据还是旧的,因为此时还没有开始重新渲染DOM节点
- updated:实例更新完毕之后调用此函数,此时 data 中的状态值 和 界面上显示的数据,都已经完成了更新,界面已经被重新渲染好了!
- 销毁期间的生命周期函数:
- beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。
- destroyed:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
<script>
new Vue({
el:"#app",
data:{
msg:"111"
},
methods:{},
beforeCreate:function () {
console.log("这是第一个周期函数,表示实例创建完全被创建出来之前,会执行");
console.log(this.msg);
// beforeCreate生命周期函数执行的时候,data和methods中的数据 还没有初始化
},
created:function () {
console.log("实例创建加载到内存中");
console.log(this.msg);
// created 生命周期函数执行的时候,data和methods已经初始化完成
// 如果要调用methods中的方法或者操作data中的数据,最早,只能在这个方法中操作
},
beforeMount:function () {
console.log("beforeMount 模板已经渲染 页面还没有刷新" );
//开始渲染模板,把Vue代码中的那些指令进行执行,最终在内存中生成一个编译好的最终模板字符串,然后,把这个模板字符串,
// 渲染为内存中的DOM,此时,只是在内存中渲染好模板,并没有把模板挂在页面中
//在这个函数执行的时候,页面中的元素,还没有被真正的替换过来,只是之前写的一些模板字符串
},
mounted:function () {
//mounted是 实例创建期间的最后一个生命周期函数,当执行完mounted就表示,实例已经被完全创建好了,此时 如果没有其他操作
//的话这个实例,就一直存在内存中
//如果要操作DOM 节点,最早要在这个函数中进行
//执行到这个函数时,标明组件脱离了创建阶段,进入到了运行阶段
},
//运行期间的周期函数
beforeUpdate:function () {
//页面中显示的数据还是旧的。此时data数据是最新的,页面还没有被新的数据渲染
},
updated:function () {
//页面和data数据 已经保持同步了
},
//销毁期间的周期函数
beforeDestroy:function () {
},
destroyed:function () {
}
})
lifecycle.png
vue-resource 实现 get, post, jsonp请求
除了 vue-resource 之外,还可以使用 axios
的第三方包实现实现数据的请求
- 之前的学习中,如何发起数据请求?
- 常见的数据请求类型? get post jsonp
- 测试的URL请求资源地址:
- get请求地址: http://vue.studyit.io/api/getlunbo
- post请求地址:http://vue.studyit.io/api/post
- jsonp请求地址:http://vue.studyit.io/api/jsonp
- JSONP的实现原理
- 由于浏览器的安全性限制,不允许AJAX访问 协议不同、域名不同、端口号不同的 数据接口,浏览器认为这种访问不安全;
- 可以通过动态创建script标签的形式,把script标签的src属性,指向数据接口的地址,因为script标签不存在跨域限制,这种数据获取方式,称作JSONP(注意:根据JSONP的实现原理,知晓,JSONP只支持Get请求);
- 具体实现过程:
- 先在客户端定义一个回调方法,预定义对数据的操作;
- 再把这个回调方法的名称,通过URL传参的形式,提交到服务器的数据接口;
- 服务器数据接口组织好要发送给客户端的数据,再拿着客户端传递过来的回调方法名称,拼接出一个调用这个方法的字符串,发送给客户端去解析执行;
- 客户端拿到服务器返回的字符串之后,当作Script脚本去解析执行,这样就能够拿到JSONP的数据了;
- 带大家通过 Node.js ,来手动实现一个JSONP的请求例子;
const http = require('http');
// 导入解析 URL 地址的核心模块
const urlModule = require('url');
const server = http.createServer();
// 监听 服务器的 request 请求事件,处理每个请求
server.on('request', (req, res) => {
const url = req.url;
// 解析客户端请求的URL地址
var info = urlModule.parse(url, true);
// 如果请求的 URL 地址是 /getjsonp ,则表示要获取JSONP类型的数据
if (info.pathname === '/getjsonp') {
// 获取客户端指定的回调函数的名称
var cbName = info.query.callback;
// 手动拼接要返回给客户端的数据对象
var data = {
name: 'zs',
age: 22,
gender: '男',
hobby: ['吃饭', '睡觉', '运动']
}
// 拼接出一个方法的调用,在调用这个方法的时候,把要发送给客户端的数据,序列化为字符串,作为参数传递给这个调用的方法:
var result = `${cbName}(${JSON.stringify(data)})`;
// 将拼接好的方法的调用,返回给客户端去解析执行
res.end(result);
} else {
res.end('404');
}
});
server.listen(3000, () => {
console.log('server running at http://127.0.0.1:3000');
});
- vue-resource 的配置步骤:
- 直接在页面中,通过
script
标签,引入vue-resource
的脚本文件; - 注意:引用的先后顺序是:先引用
Vue
的脚本文件,再引用vue-resource
的脚本文件;
- 发送get请求:
getInfo() { // get 方式获取数据
this.$http.get('http://127.0.0.1:8899/api/getlunbo').then(res => {
console.log(res.body);
})
}
- 发送post请求:
postInfo() {
var url = 'http://127.0.0.1:8899/api/post';
// post 方法接收三个参数:
// 参数1: 要请求的URL地址
// 参数2: 要发送的数据对象
// 参数3: 指定post提交的编码类型为 application/x-www-form-urlencoded
this.$http.post(url, { name: 'zs' }, { emulateJSON: true }).then(res => {
console.log(res.body);
});
}
- 发送JSONP请求获取数据:
jsonpInfo() { // JSONP形式从服务器获取数据
var url = 'http://127.0.0.1:8899/api/jsonp';
this.$http.jsonp(url).then(res => {
console.log(res.body);
});
}
配置本地数据库和数据接口API
- 先解压安装
PHPStudy
; - 解压安装
Navicat
这个数据库可视化工具,并激活; - 打开
Navicat
工具,新建空白数据库,名为dtcmsdb4
; - 双击新建的数据库,连接上这个空白数据库,在新建的数据库上
右键
->运行SQL文件
,选择并执行dtcmsdb4.sql
这个数据库脚本文件;如果执行不报错,则数据库导入完成; - 进入文件夹
vuecms3_nodejsapi
内部,执行npm i
安装所有的依赖项; - 先确保本机安装了
nodemon
, 没有安装,则运行npm i nodemon -g
进行全局安装,安装完毕后,进入到vuecms3_nodejsapi
目录 ->src
目录 -> 双击运行start.bat
- 如果API启动失败,请检查 PHPStudy 是否正常开启,同时,检查
app.js
中第14行
中数据库连接配置字符串是否正确;PHPStudy 中默认的 用户名是root,默认的密码也是root
品牌管理改造
展示品牌列表
添加品牌数据
删除品牌数据
Vue中的动画
为什么要有动画:动画能够提高用户的体验,帮助用户更好的理解页面中的功能;
使用过渡类名
- HTML结构:
<div id="app">
<input type="button" value="动起来" @click="myAnimate">
<!-- 使用 transition 将需要过渡的元素包裹起来 -->
<transition name="fade">
<div v-show="isshow">动画哦</div>
</transition>
</div>
- VM 实例:
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
isshow: false
},
methods: {
myAnimate() {
this.isshow = !this.isshow;
}
}
});
- 定义两组类样式:
/* 定义进入和离开时候的过渡状态 */
.fade-enter-active,
.fade-leave-active {
transition: all 0.2s ease;
position: absolute;
}
/* 定义进入过渡的开始状态 和 离开过渡的结束状态 */
.fade-enter,
.fade-leave-to {
opacity: 0;
transform: translateX(100px);
}
使用第三方 CSS 动画库
- 导入动画类库:
<link rel="stylesheet" type="text/css" href="./lib/animate.css">
- 定义 transition 及属性:
<transition
enter-active-class="fadeInRight"
leave-active-class="fadeOutRight"
:duration="{ enter: 500, leave: 800 }">
<div class="animated" v-show="isshow">动画哦</div>
</transition>
使用动画钩子函数
- 定义 transition 组件以及三个钩子函数:
<div id="app">
<input type="button" value="切换动画" @click="isshow = !isshow">
<transition
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter">
<div v-if="isshow" class="show">OK</div>
</transition>
</div>
- 定义三个 methods 钩子方法:
methods: {
beforeEnter(el) { // 动画进入之前的回调
el.style.transform = 'translateX(500px)';
},
enter(el, done) { // 动画进入完成时候的回调
el.offsetWidth;
el.style.transform = 'translateX(0px)';
done();
},
afterEnter(el) { // 动画进入完成之后的回调
this.isshow = !this.isshow;
}
}
- 定义动画过渡时长和样式:
.show{
transition: all 0.4s ease;
}
v-for 的列表过渡
- 定义过渡样式:
<style>
.list-enter,
.list-leave-to {
opacity: 0;
transform: translateY(10px);
}
.list-enter-active,
.list-leave-active {
transition: all 0.3s ease;
}
</style>
- 定义DOM结构,其中,需要使用 transition-group 组件把v-for循环的列表包裹起来:
<div id="app">
<input type="text" v-model="txt" @keyup.enter="add">
<transition-group tag="ul" name="list">
<li v-for="(item, i) in list" :key="i">{{item}}</li>
</transition-group>
</div>
- 定义 VM中的结构:
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
txt: '',
list: [1, 2, 3, 4]
},
methods: {
add() {
this.list.push(this.txt);
this.txt = '';
}
}
});
列表的排序过渡
<transition-group>
组件还有一个特殊之处。不仅可以进入和离开动画,还可以改变定位。要使用这个新功能只需了解新增的 v-move
特性,它会在元素的改变定位的过程中应用。
-
v-move
和v-leave-active
结合使用,能够让列表的过渡更加平缓柔和:
.v-move{
transition: all 0.8s ease;
}
.v-leave-active{
position: absolute;
}
网友评论