之前学过vue,上一个项目做小程序,发现跟vue差不多,于是给一个星期的时间自己重拾vue,但是发现高估了自己,并发现自己已变成一个小白...看了几天vue文档之后,再也不想说小程序与vue相似,小程序简单太多了,看完文档就可以做出来了,但是vue不一样。。。个人觉得vue的文档很散,讲的都是小零件,所以很难想着拼起来。在学习过程中做一下笔记吧...忘了可以看...
创建实例
new Vue({
el: "#app",
data:{},
methods: {},
filters: {},
directives: {},
computed:{},
router: vueRouter
})
过滤器
过滤器可以用在两个地方:mustache 插值和 v-bind 表达式。
- 全局过滤器(自定义)
Vue.filter("dateFmt",function (param,fmtStr) {
let year = param.getFullYear();
let month = param.getMonth() + 1;
let day = param.getDate();
let hour = param.getHours();
let minute = param.getMinutes();
let second = param.getSeconds();
if(fmtStr == "yyyy-mm-dd"){
return year + "-" + month + "-" + day;
}else if(fmtStr == "yyyy-mm-dd hh:mm:ss"){
return year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second;
}
});
- 局部过滤器(自定义)
filters:{
dateFmt(param,fmtStr){
let year = param.getFullYear();
let month = param.getMonth() + 1;
let day = param.getDate();
let hour = param.getHours();
let minute = param.getMinutes();
let second = param.getSeconds();
if(fmtStr == "yyyy-mm-dd"){
return year + "-" + month + "-" + day;
}else if(fmtStr == "yyyy-mm-dd hh:mm:ss"){
return year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second;
}
},
}
- 使用过滤器(管道符后跟着过滤器名(参数))
<td>{{item.time | dateFmt("yyyy-mm-dd hh:mm:ss")}}</td>
自定义指令(这指令的钩子函数,看不太懂...)
钩子函数
- bind: 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作
- inserted: 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。
钩子函数参数
- binding: 一个对象,包含以下属性:
value: 指令的绑定值, 例如:v-my-directive="1 + 1"
, value 的值是 2,又如:v-color="{colorname:'red',colorname2:'green'}"
,value.colorname的值是red,value.colorname2的值是green
我想,暂时这两个够用了...毕竟其他还不会...
- 全局指令
// 定义一个全局自定义属性指令
Vue.directive('focus', {
// 当绑定元素插入到 DOM 中时调用(父节点存在即可调用,不必存在于 document 中)
inserted: function (el) {
// 聚焦元素
el.focus();
console.log(el);
}
});
- 局部指令
directives: {
focus:{
inserted(el){
el.focus();
}
},
"color":{
bind: function (el,binding) {
console.log(binding.value.colorname);
el.style.color = binding.value.colorname;
},
inserted: function (el,binding) {
console.log(binding.value.colorname);
}
}
}
- 使用指令
<label>学号:<input class="add" type="text" v-model="newNo" v-focus v-color="{colorname:'red'}"></label>
计算属性(局部)
vue.js v1的系统过滤器filterBy换成计算属性了
computed: {
searchQuery: function () {
var self = this;
return self.studentsList.filter(function (user) {
return (user["name"].indexOf(self.searchValue) !== -1 || user["no"].indexOf(self.searchValue) !== -1 || user["gender"].indexOf(self.searchValue) !== -1);
})
}
}
vue-resource
响应.then()内的成功回调中的参数是响应报文体
这相当于jq的ajax
- get
this.$http.get('/someUrl').then(successCallback, errorCallback);
- post
需要加上emulateJSON:true,其本质是在请求报文头上增加了Content-Type:application/x-www-form-urlencode,由此,服务器中才可以获取{no:1,sex:1}属性值
this.$http.post('/someUrl',{no:1,sex:1(请求报文体)},{emulateJSON:true}).then(successCallback, errorCallback);
- jsonp
原理:jsonp不是一个ajax请求,采取的是浏览器的同源策略来实现跨域,在请求的时候会在url后带上callback=生成的函数名称 一起提交给服务器,在服务器中利用callback传入的值当做一个方法来将要响应回去的数据当做参数传入。
// jsonp是设置回调的属性名,有些是cb=jqxxxx,有些是callback=jqxxxx,默认是callback
this.$http.post('/someUrl',{jsonp: "cb"}).then(successCallback, errorCallback);
生命周期
<div id="app">
<span ref="span">hello vue</span>
</div>
new Vue({
el: "#app",
data: {
msg:"hello"
},
// 在实例初始化之后,data和event/watcher 事件配置之前
// 还不能取到this.data、事件
beforeCreate(){
console.log("1---beforeCreate",this.msg,this.$refs.span);
},
// 实例已完成以下的配置:data,属性和方法的运算, watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。
// >>>>想要显示页面的时候就有数据的话,就在这个函数里请求数据
created(){
console.log("2---created",this.msg,this.$refs.span);
},
// 在挂载开始之前被调用:相关的 render 函数首次被调用。(可以理解为渲染前)
beforeMount(){
console.log("3---beforeMount",this.msg,this.$refs.span);
},
// el 被新创建的 vm.$el 替换(如{{}}差值表达式、v-show="isShow"等替换值),并挂载到实例上去之后调用该钩子。(可以理解为渲染后不知道这个vm.$el怎么用...)
mounted(){
console.log("4---mounted",this.msg,this.$refs.span);
}
})
过渡
感觉这个过渡真的好鬼复杂!官网最简答的例子是点击按钮触发,但是我不想要这种,我要一打开网页就有动画,怎么实现?于是我就开始尝试用过渡的CSS类名和过渡钩子。
- 过渡CSS类名实现
↓ 这个CSS其实我也不懂为什么要这样写,真的不懂,但是按照这个格式.XXXX-enter-active, .XXXX-leave-active { } .XXXX-enter, .XXXX-leave-active { }
就可以有过渡的效果。
// CSS
<style>
.box { position: absolute; left: 0; top: 100px; width: 50px; height: 50px; background: skyblue;}
.box1-enter-active, .box1-leave-active {
transition: all .5s;
transform: translateX(0px);
}
.box1-enter, .box1-leave-active {
transform: translateX(200px)
}
</style>
↓ 一开始是用按钮触发isMove
,后来被我注释了。
// html
<div id="app">
<!--<button @click="isMove=!isMove">移动</button>-->
<transition name="box1">
<div v-if="isMove" class="box"></div>
</transition>
</div>
看代码就知道一开始我在created
钩子控制isMove
,后来发现不行就换成mounted
钩子,为什么mounted
钩子就行,我是在过渡钩子发现的。
// JS
new Vue({
el: "#app",
data: {
isMove: false
},
// created(){
// this.isMove = true;
// },
mounted(){
this.isMove = true;
}
})
- 过渡钩子实现
↓ 一定要给过渡元素加上类名,而且要有过渡(transition)属性。
// CSS
<style>
.box { width: 50px; height: 50px; background: skyblue; transition: all 3s linear;}
</style>
↓ @before-enter @enter @after-enter
都是固定的,函数名随你,v-show
很重要哦,就是要靠他触发
// html
<div id="app">
<transition name="moveBox"
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter">
<div v-show="isShow" class="box"></div>
</transition>
</div>
↓ 一开始我在created
控制isShow
,失败之后我想应该在哪个钩子控制变量呢,(错误思想:我看着过渡钩子,看到了el
,哦!恍然大悟!mounted
钩子不是跟el
有关系的吗?写!搞定~)问了朋友关于生命周期mounted
的问题后,得出答案:过渡元素还没有渲染完,元素渲染完在改变isShow
,所以放在mounted
执行
// JS
new Vue({
el: "#app",
data: {
isShow: false
},
methods: {
beforeEnter: function (el) {
// 控制动画的准备进入
el.style.transform = 'translateX(0px)';
},
enter: function (el, done) {
// 控制动画的最终状态
let a = el.offsetLeft;
this.$nextTick(()=>{
el.style.transform = 'translateX(300px)';
});
done();
},
afterEnter: function (el) {
// 动画完以后的一些逻辑处理
}
},
// created(){
// this.isShow = true;
// console.log(this.isShow);
// },
mounted(){
this.isShow = true;
}
})
组件
不说废话直接上码
- 基础组件
- html 分成3块看
↓ 这#app
就是根组件,www
是父组件
↓ 这就是父组件<div id="app"> <www></www> </div>
www
的模板,这个模板里面有两个<a>
,点击登录
变量which = login
,点击注册
变量which = register
,还有子组件,这个是动态组件,<component>
的元素属性is = which
决定渲染哪个子组件,而which
由点击哪个a
标签决定。(keep-alive此时我还不知道有什么用,随意加上去的)
↓ 父组件模板的子组件模板<template id="account"> <div> <h3>{{msg}}</h3> <a href="#" @click="which='login'">登录</a> <a href="#" @click="which='register'">注册</a> <!--动态组件--> <keep-alive> <component :is="which"></component> </keep-alive> </div> </template>
<template id="login"> <div> <h4>登录组件内容</h4> </div> </template> <template id="register"> <div> <h4>注册组件内容</h4> </div> </template>
- JS
↓ 全局注册父组件,父组件中注册子组件
↓ 还可以局部注册父组件Vue.component('www',{ // www 为组件元素名 template:'#account', // template元素的id data: function () { return{ msg: "账户组件内容:", which: "login" } }, // 父组件中注册子组件 components:{ "login":{ // 组件元素名 template: "#login" }, "register":{ // 组件元素名 template: "#register" } } }); new Vue({ el:'#app' });
new Vue({ el:'#app', components: { "www":{ template:'#account', // template元素的id data: function () { return{ msg: "账户组件内容:", which: "login" } }, // 父组件中注册子组件 components:{ "login":{ // 组件元素名 template: "#login" }, "register":{ // 组件元素名 template: "#register" } } } } });
- html 分成3块看
- 父组件传值子组件
在上面的例子基础上动工!- html
↓ 在父组件模板中加了一个<input>
,输入登录人名称,在动态子组件中赋值给user
属性,实现传值,要注意的是给组件属性赋值必须是父组件的已知值,不能是子组件的值。
↓ 在登录子组件模板中加了<span>{{user}},欢迎登陆!</span>
,子组件通过属性user
取得登录人名称存放到props
中,再用{{ }}
取出。<template id="account"> <div> <h3>{{info}}</h3> <a href="#" @click="which='login'">登录</a> <a href="#" @click="which='register'">注册</a> <br> <label>登录的人是 <input type="text" v-model="msg"></label> <!--动态组件--> <keep-alive> <component :user="msg" :is="which"></component> </keep-alive> </div> </template> <template id="login"> <div> <h4>登录组件内容</h4> <span>{{user}},欢迎登陆!</span> </div> </template> <template id="register"> <div> <h4>注册组件内容</h4> </div> </template> <div id="app"> <www></www> </div>
- JS
↑ 解释的很清楚了,这里不说了。Vue.component('www',{ template:'#account', data: function () { return{ info: "账户组件内容:", which: "login", msg: "" } }, components:{ "login":{ template: "#login", props:["user"] }, "register":{ template: "#register" } } }); new Vue({ el:'#app' });
- html
- 子组件传值父组件
这个栗子是点击登录以后,出现登录组件,在该组件中输入一句话,这句话在父组件中出现。- html
↓ 在父组件模板中加了<span>登陆之后,{{msg}}说:</span><span>{{userSay}}</span>
用来显示子组件输入的话。在动态子组件中绑定自定义事件get-child-say
(这个必须是羊肉串命名,不可以驼峰),事件处理程序就是sayWhat
。
↓ 在登录子组件模板中增加<label>我说: <input type="text" v-model="childSay" @keyup.enter="sendToFoo"></label>
,当输入一句话后按回车键就会触发事件sendToFoo
<template id="account"> <div> <h3>{{info}}</h3> <a href="#" @click="which='login'">登录</a> <a href="#" @click="which='register'">注册</a> <br> <label>登录的人是 <input type="text" v-model="msg"></label> <div> <span>登陆之后,{{msg}}说:</span><span>{{userSay}}</span> </div> <!--动态组件--> <keep-alive> <component v-on:get-child-say="sayWhat" :user="msg" :is="which"></component><!-- 这个自定义事件get-child-say不能用驼峰命名,只能用羊肉串 --> </keep-alive> <!--打开vue tool观察:加了这个keep-alive,不显示的子组件一直在父组件中保存着,不加的话父组件下只有正在显示的子组件--> </div> </template> <template id="login"> <div style="border: 1px solid red;"> <h4>登录组件内容</h4> <span>{{user}},欢迎登陆!</span> <br> <label>我说: <input type="text" v-model="childSay" @keyup.enter="sendToFoo"></label> </div> </template> <template id="register"> <div> <h4>注册组件内容</h4> </div> </template> <div id="app"> <www></www> </div>
- JS
↓ 在login
组件有一个sendToFoo()
,当该方法触发时,就会触发get-child-say
事件,并且会带上参数this.childSay
,就是输入的一句话,而这个事件在父组件中绑定的,故而执行sayWhat(value)
获取参数渲染到父组件中。Vue.component('www',{ template:'#account', data: function () { return { info: "账户组件内容:", which: "login", msg: "", userSay: "" } }, methods: { sayWhat(value){ this.userSay = value; } }, components:{ "login":{ template: "#login", props:["user"], data:function () { return { childSay: "" } }, methods: { sendToFoo(){ this.$emit("get-child-say",this.childSay); } } }, "register":{ template: "#register" } } }); new Vue({ el:'#app' });
- html
- keep-alive
在开始写基础组件的时候就有疑问了:动态组件中被keep-alive包着有什么用?终于搞完 子组件传值父组件 之后大概知道了一点了。-
用
keep-alive
包裹动态组件:运行基础组件,打开Vue.js devtools,然后看↓默认显示登录组件
点击注册组件后
.
-
没有用
keep-alive
包裹动态组件:运行基础组件,打开Vue.js devtools,然后看↓默认显示登录组件
点击注册组件后
-
<keep-alive> 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。为此可以添加一个 keep-alive 指令参数。在API 参考查看更多
<keep-alive>
的细节。
- 路由参数实现url传值
下面的这个栗子是:在根组件输入数据作为路由参数(同时修改路由),然后通过路由传去组件。
// html
<div id="app">
<label>传值:<input type="text" v-model="msg"></label>
<br>
<router-link :to="'/sub1/' + msg">sub1</router-link>
<router-link to="/sub2">sub2</router-link>
<!-- 组件的显示占位区域 -->
<router-view></router-view>
</div>
<!-- 第一个子组件模板 -->
<template id="sub1">
<div>
<h3>这是第一个子路由</h3>
<div>传来的值是:{{txt}}</div>
</div>
</template>
<!-- 第二个子组件模板 -->
<template id="sub2">
<div>
<h3>这是第2个子路由</h3>
</div>
</template>
// JS
// 定义第一个子组件
let sub1 = Vue.extend({
template: "#sub1",
data: function () {
return {
txt: ""
}
},
// 导航完成后,在组件的 created 钩子中获取数据
// 还可以在数据获取期间展示一个 loading 状态
created: function () {
this.txt = this.$route.params.id;
}
});
// 定义第二个子组件
let sub2 = Vue.extend({
template: "#sub2"
});
// 定义路由对象并且注册路由规则
let vueRouter = new VueRouter({
routes: [
{path: '/',redirect: '/sub2'}, // 默认路由
{path: '/sub1/:id',component: sub1},
{path: '/sub2', component: sub2}
]
});
// 使vueRouter生效
new Vue({
el: "#app",
data: {
msg: ""
},
router: vueRouter
})
网友评论