访客输入区域弹出/收起的动态效果

点击【说点什么】的时候,从下往上弹出可选的对话内容。
FireShot Capture 010 - 与芒果聊天中 - localhost.png

此时再次点击空白区域,对话框又会向下收起来。

HTML部分

在index.html里搜索“说点什么”,可以看到这是一个div。

<div id="prompt-head">
    <div class="say-something">说点什么……</div>
    <a href="#" class="close-btn"
        v-on:click="togglePrompt(false)"></a>
</div>

注意到里面有一个v-on:click的点击事件绑定。虽然是个前端小白,可我还是认识html里的onclick事件的。可这里的v-on是什么鬼?整容了?
google了一下,发现这个v-on是使用了Vue框架后的写法。
Vue框架是一个js框架,我没接触过,正好一起学学。这里我们知道v-on:click就相当于原来的onclick就可以了。再看绑定的函数名猜也能猜到这个是用来切换显示状态的。这里传递的参数是false,应该是收起的意思。
继续找,又有一处“说点什么”的div

<div id="input-hint" class="say-something"
    v-on:click="togglePrompt(true)"
    :class="{'clickable': !isXianzheTyping }">
    <span v-if="!isXianzheTyping">说点什么……</span>
    <span v-if="isXianzheTyping">羡辙正在输入中</span>
</div>

这里应该是未弹出时显示的最下边那一条底栏了。在机器人未输入的状态(isXianzheTyping控制)下底栏文字显示“说点什么”并且允许点击,点击后调用togglePrompt(true),弹出访客输入区域。
页面的定义就是这些了。

js的部分

我们在index.js中找到togglePrompt函数。

togglePrompt(toShow) {
    if (this.isXianzheTyping) {
        // don't prompt if xianzhe is typing
        return;
    }

    this.hasPrompt = toShow;
}

很简单,只是判断了一下当前状态是否允许弹出(html那边已经控制过clickable了,这里有点重复),然后简单的将传入的true/false值赋给this.hasPrompt变量就结束了。
这么神奇?this.hasPrompt = toShow;这一句js指令是怎么控制页面元素的呢?这个hasPrompt一定跟页面元素有什么不可告人的关系。
我们回到index.html查找hasPrompt,果然,找到了
<div id="mobile" :class="{ 'has-prompt': hasPrompt }">
这里又出现新东西了,:class=...这种写法也是Vue框架里的,作用是将页面元素绑定到js变量上。这里将hasPrompt变量绑定在has-prompt这个class名上了。
好吧,我们继续找has-prompt的class定义,看看那边有什么东西。既然是class,那一定在css文件夹中了。翻了一通,在css/_mobile.prompt.scss里找到了。

#prompt {
    position: absolute;
    bottom: 0%;
    transform: translateY(100%);
    z-index: 100;

    width: 100%;

    box-shadow: 0 0 30px 0 rgba(0, 0, 0, 0.2);
    transition-duration: $prompt-animation-duration;
    transition-property: transform;

    #mobile.has-prompt & {
        transform: translateY(0);
    }
}

OK,这里的css定义里就是最终实际控制弹出/收起动画的地方了。等等,哪里不对劲?文件名很诡异啊,我记得css文件应该是.css啊,而且index.html里并没有引用这个.scss文件啊。这个.scss文件又是什么玩意???我这个前端小白一路上全都是不认识的玩意儿啊!没办法,又google了一下,简单来说scss是css的预编译语言,提供了css本来没有的比如变量定义等功能方便css的编写。写完以后再编译成标准的css供html使用。关于怎么编译,后面的系列文章里再说明吧,一下子东西太多了不好消化。这里先简单的理解成css就好了,语法其实都差不多的。
继续,这一段css里面关于显示动态效果的是下面几句:

  • transform: translateY(xx%);
    指定动画的类型是Y轴移动,xx表示偏移量。
  • transition-duration: xx;
    指定动画持续时间xx表示时间。
    这里作者用了一个变量$prompt-animation-duration来代替,这个变量可以在另一个scss文件css\_variables.scss里找到:$prompt-animation-duration: 0.3s;

到这里基本上就可以猜到了,当js文件里对变量hasPrompt赋值的时候,Vue框架在背后做了大量工作,最后相当于直接控制了页面上某个绑定元素的css样式,从而控制这个元素的各种行为。比如弹出,收起,放大,缩小,都是可以做到的。这样看来,Vue框架确实很强大。

试试改一改

改一下弹出方式

/* 修改前:transform: translateY(100%); */
/* 弹出方式变成横向弹出 */
transform: translateX(100%);

再改一下位置

#mobile.has-prompt & {
    /* 修改前:transform: translateY(0); */
    /* 修改弹出后的位置 */
    transform: translateY(-100%);
}

变成这样了
FireShot Capture 013 - 与芒果聊天中 - localhost.png

整理一下流程

  1. html:引入Vue框架
  2. js:创建Vue对象并同时将这个对象绑定到页面上某个元素。在这里是“id=mobile”的div。然后在Vue对象里定义各种data,其中就有hasPrompt变量。
  3. html:将hasPrompt的变量,继续绑定在mobile的class“has-prompt”上。
  4. scss:使用被绑定的class“has-prompt”,为不同的class状态编写不同的行为。
  5. js:根据需要对js变量hasPrompt赋值,即可影响被绑定页面元素的样式和状态。(比如弹出/收起)

本文小结

从一个简单的弹出/收起动画效果引出这么多我从没接触过的概念还是挺意外的。可见现在的前端技术的发展有多迅速,我多年以前的那些原生html/js/css的概念已经跟不上现在开发的要求了。一定要保持对新技术的敏感,持续学习才行。

系列文章

Last modification:July 11, 2020
If you think my article is useful to you, please feel free to appreciate