Vue动画
单元素动画
- 用transition把需要动画的元素包起来
- 给transition一个name属性,指定动画效果
- 所以要写样式
.xxx-enter-active{
/* 设置进入时的transition属性 */
}
.xxx-leave-active{
/* 设置离开时的transition属性 */
}
.xxx-enter {
/* 设置以什么状态进入 */
设置动画需要过渡的属性样式
}
.xxx-leave-to {
/* 设置离开到什么状态 */
设置动画需要过渡的属性样式
}
transition与keyframes的结合动画使用
- 自己写一个@keyframes的动画剧本
- 然后在xx-enter-active里用,就代表进入用这个动画剧本
- 在xx-leave-active里用,就代表离开用这个动画剧本
多元素动画
多元素动画必须用transition-group包住,且每个子元素必须设置一个key,其它和单元素动画是一样的
- transition只能用在单个元素
- 如果要多个元素用动画,就用
<transition-group>
包起来 - 并且每个被 包起来的标签必须加key,且key不可重复
不管是单元素动画还是多元素动画,进入时都会有一个类叫 xx-enter-active
组件的基本使用
把某个界面或者说某个小功能,封装起来就叫组件(就是对html css js的一个综合封装),组件也是Vue的实例,所以它也有自己的data和methods以及生命周期钩子等
如何在组件中引入其它组件
- 如果要运行的组件叫App.vue,那么也可以直接vue serve不加文件名
- 引入组件步骤:
- import 组件名 from '组件的路径’
- 在需要引入的父组件里,写components属性(跟data同级),这是一个对象,对象里写 这个组件名就行了
components:{
son
}
- 在需要用的地方写这个组件名字的标签
- 引入子组件时可以再把子组件名字改了,但是一般不改
- 包含别人的叫父组件,被包含的叫子组件
- assets文件夹放静态资源:图片、css文件、字体文件
- 导入别的组件时,可以不写后缀.vue,它会自动帮你找.vue
组件中如何使用外部插件
- 先下载包
npm i 包名
npm i axios
- 导包
import 名字 from '包名'
- 用包
名字叫什么就用什么
组件间的传值
如果A组件中引入了B组件 ,这样我们称A组件为父组件,B为子组件
- 父传子
- 在使用子组件的标签上,加ref=“名字”
- 再使用 this.$refs.名字 就能得到子组件对象,相当于就是子组件里面的this,所以给它属性赋值就相当于传值了
- 子传父
- 在子组件里写 this.$parent就能找到父组件对象,就直接再给它属性赋值就相当于传值了
Vue-cli项目创建
文档
vue_cli:脚手架,管理项目的工具、以及把项目翻译成浏览器认识的文件,相当于把.vue文件翻译成.html,.css,.js
快速原型开发:每次用脚手架启动和新建项目会很慢和麻烦,所以这个单文件组件服务让我们可以快速的把.vue文件跑起来
先安装vue_cli
npm install -g @vue/cli
再安装快速原型开发
npm install -g @vue/cli-service-global
创建项目
vue create 项目名
-
项目名不要用大写,不要用关键字,例如项目名叫 vue 等
-
实际开发中,用项目的英文名,例如:微信 叫 vue create wechat
-
项目创建后,可以cd 进入到项目目录
-
再执行 npm run serve 可以把项目跑起来
npm run serve
Vue-cli项目结构
其他
天知道案例总结
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>天知道</title>
<link rel="stylesheet" href="css/reset.css" />
<link rel="stylesheet" href="css/iconfont.css" />
<link rel="stylesheet" href="css/main2.css" />
<style>
.tem .iconfont {
font-size: 50px;
}
/* 进入的动画体 */
.wealist-enter-active{
transition:all 1s
}
.wealist-enter-active:nth-child(2){
transition-delay: 0.2s;
}
.wealist-enter-active:nth-child(3){
transition-delay: 0.4s;
}
.wealist-enter-active:nth-child(4){
transition-delay: 0.6s;
}
.wealist-enter-active:nth-child(5){
transition-delay: 0.8s;
}
/* 进入的动画前的状态 */
.wealist-enter{
opacity: 0;
transform: translateY(100px);
}
</style>
</head>
<body>
<div class="wrap" id="app">
<div class="search_form">
<div class="logo"><img src="img/logo.png" alt="logo" /></div>
<div class="form_group">
<input
type="text"
v-model.lazy="city"
class="input_txt"
placeholder="北京"
@keyup.enter="search"
/>
<button class="input_sub " @click="search" :class="{loading:isLoading}">搜 索</button>
</div>
<div class="hotkey" @click="clickHot">
<a href="javascript:;">北京</a>
<a href="javascript:;">上海</a>
<a href="javascript:;">广州</a>
<a href="javascript:;">深圳</a>
</div>
</div>
<ul class="weather_list">
<transition-group name="wealist">
<li v-for="(item, index) in list.forecast" :key="index">
<div class="info_type">
<!-- 雨 -->
<span class="iconfont" v-if="item.type.indexOf('雨')!=-1"></span>
<!-- 晴 -->
<span class="iconfont" v-else-if="item.type.indexOf('晴')!=-1"></span>
<!-- 阴 -->
<span class="iconfont" v-else-if="item.type.indexOf('阴')!=-1"></span>
<!-- 雪 -->
<span class="iconfont" v-else-if="item.type.indexOf('雪')!=-1"></span>
<!-- 云 -->
<span class="iconfont" v-else-if="item.type.indexOf('云')!=-1"></span>
<!-- 雷 -->
<span class="iconfont" v-else-if="item.type.indexOf('雷')!=-1"></span>
<!-- 雹 -->
<span class="iconfont" v-else-if="item.type.indexOf('雹')!=-1"></span>
<!-- 雾 -->
<span class="iconfont" v-else="item.type.indexOf('雾')!=-1"></span>
</div>
<div class="info_temp"> {
{
item.high}} </b><br /> {
{
item.low}} </div>
<div class="info_date"><b> {
{
list.city}} </b><span> {
{
item.date}} </span></div>
</li>
</transition-group>
</ul>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.bootcss.com/axios/0.19.0/axios.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
city: '',
list:[],
isLoading:false
},
methods: {
search(){
if(this.city.trim()==''){
window.alert('请输入正确的城市名称');
}else{
// 1.加载loading动画
this.isLoading=true
// 2.清空list列表
this.list= []//空相当于false,加载数据从没有到有相当于进入动作
// 3.请求
this.query(this.city);
}
},
query(city){
axios({
url:'http://wthrcdn.etouch.cn/weather_mini',
method:'get',
params: {
city:city}
}).then(res=>{
//成功回调
console.log(res)
if(res.data.status==1000){
setTimeout(()=>{
// 将响应的数据赋值给list,vue会自动渲染,相当于进入动作
this.list=res.data.data
// 加载后取消动画
this.isLoading = false
},500)
}else{
window.alert('请正确输入需要查询的城市')
}
});
},
clickHot(e){
this.city=e.target.text
this.search();
}
},
created() {
// 初始化
this.query('北京')
},
})
</script>
</body>
</html>
总结:
ref的基本使用
Vue里面专门用来获取dom元素的
- 用法
- 在需要找的标签行内写ref=“名字”
- 哪里要用就在哪里写this.$refs.名字
- 只要给某个标签加了ref属性,那么就可以在vue的实例的$refs里找到
- 注意
- ref的名字也可以一样,但是永远只能找到最后一个,所以我们一般也不会给标签起同一个ref
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box{
width: 200px;
height: 150px;
border: 1px solid #000;
overflow: auto;
}
</style>
</head>
<body>
<div id="app">
<!-- scrollTop不是行内属性,用v-bind来绑定也没用 -->
<!-- 用vue的方法是完成不了的 -->
<!-- 我们使用一些插件的时候需要传入dom元素,那么这个时候也可以用ref来找到 -->
<!-- 找到这个元素,再 .scrollTop = 999 -->
<!-- 所以这个时候就需要在vue里面找到dom元素 -->
<!-- ref是一个行内属性,相当于在vue中这个标签起了一个名字 -->
<div class="box" ref="box">
<p>这是p标签1</p>
<p>这是p标签2</p>
<p>这是p标签3</p>
<p>这是p标签4</p>
<p>这是p标签5</p>
<p>这是p标签6</p>
<p>这是p标签7</p>
<p>这是p标签8</p>
<p>这是p标签9</p>
<p>这是p标签10</p>
</div>
<!-- <div ref="xxxx">{
{
我是第二个div}}</div> -->
<button @click="toEnd">滚到最后</button>
<button @click="toUp">滚到顶部</button>
</div>
<script src="./vue.js"></script>
<script>
new Vue({
el:'#app',
data:{
},
methods: {
toEnd(){
console.log(this.$refs)
console.log(this.$refs.box)
console.log(this.$refs['box'])
// 也可以找,但是比较麻烦,vue有专门找到dom元素的方法
// let box = document.querySelector('.box')
// box.scrollTop = 9999
this.$refs.box.scrollTop = 9999
},
toUp(){
this.$refs.box.scrollTop=0
}
}
})
</script>
</body>
</html>
$nextTick使用
- 它是setTimeout的高级版本,它是一个异步操作,就是帮我们算好了数据渲染到页面所需要的时间然后再执行图的内部操作
- 是下一次更新后来调用的一个回调函数
以下摘自博客https://www.cnblogs.com/haishen/p/10807691.html
-
$nextTick
是在下次DOM更新循环结束之后执行延迟回调,在修改数据之后使用$nextTick
,则可以在回调中获取更新后的DOM(dom的改变是发生在nextTick()之后),这个方法作用是当数据被修改后使用这个方法,会回调获取更新后的dom再render出来 -
$.nextTick()作用:在下次dom更新循环结束之后,执行延迟回调。在修改数据之后立即使用这个方法,获得更新后的dom
-
在以下两个情况下需要用到Vue.nextTick()
1、Vue声明周期的created() 钩子函数进行的DOM操作一定要放在Vue.nextTick() 的回调函数中,因为created() 执行的时候DOM实际上并未进行任何渲染,此时进行DOM操作无异于徒劳,所以此处一定要将DOM操作的js代码放进Vue.nextTick()的回调函数中。 -
与之对应的就是mounted 钩子函数,因为该函数执行时所有的DOM挂载和渲染都已完成,此时再钩子函数中进行任何DOM操作都不会有问题。
-
2、在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的DOM结构的时候,这个操作应该放进$.nextTick() 的回调函数中
简而言之,如果你在数据改变之后的操作跟改变之后的DOM有关,那么就应该使用Vue.nextTick()