方方-前端体系课程(六)

文章目录

55 webpack(上)

55.1 课前准备

55.2 用webpack转义JS

目标1: 用webpack转义JS

# ./node_modules/.bin/webpack等价
# 访问本地项目的webpack
npx webpack

55.3 初始化webpack.config.js

55.4 webpack配置entry和output

目标2: 理解文件名中hash的用途(便于添加缓存)

HTTP缓存, 响应头中的Cache-Control

首页是不能做缓存的, 没得通知的人了

目标3: 用webpack生成HTML

所有关于webpack的插件都–dev, 因为用户用不到.
目标4: 用webpack生成css: JS生成style方式

禁止双击预览html

http-server命令

# http-server . -c-1 等价
hs . -c-1

55.5 webpack-dev-server

--open会默认打开浏览器
webpack-dev-server --open

webpack dev server 不会生成dist目录, 是内存中就搞定了.

55.6 使用插件提取CSS文件

目标4: 用webpack生成css: CSS抽成文件

55.7 使用两个webpack config文件(上)

55.8 使用两个webpack config文件(中)

55.9 使用两个webpack config文件(下)

56 webpack(中)

56.1 loader vs plugin (上)

在这里插入图片描述

56.2 loader vs plugin (下)

面试经常问:
webpack loader 和webpack plugin

webpack loader是用来加载文件的, 比如: 可以加载JS文件, 把JS的文件转义成为低版本浏览器支持的JS文件.可以加载CSS文件, 将CSS的文件变成页面上的style标签或者其他处理还有就是加载图片文件, 对图片进行优化.

webpack plugin是用来扩展webpack的功能的, 比如: 通过HTMLWebpackPlugin插件, 用来生产HTML文件的, 还有就是通过MINICSSExtractPlugin插件, 把css抽取CSS代码成为CSS文件.

56.3 引入SCSS

目标5: 用webpack引入sass
node-sass过时了, 应该用dart-sass

github说要自己下载dart-sass或node-sass但是我没有下, 就可以运行程序了, 是之前下了么???

56.4 引入LESS和stylus

目标6: 用webpack引入LESS和stylus
SASS, LESS和Stylus完全没区别

56.5 使用file-loader引入图片

目标7: 用webpack引入图片

56.6 webpack import()懒加载

目标7: 用懒加载
面试经常问

懒加载就是不是进入页面的时候再加, 后续进行一些操作进行加载,比如点击之后, 然后加载出来.

56.7 github部署

master分支展示发开代码, gh-pages分支展示效果.

命令过多可以用sh脚本

git stash pop

回到上一个分支

git checkout -

57 【Vue全解】起手式

57.1 Vue在中国很火吗

57.2 自学线路图

57.3 使用@vue/cli 搭建项目

在这里插入图片描述
在这里插入图片描述

57.4 关于vue.js和vue.runtime.js的使用说明

vue.js 是完整版
vue.runtime.js是非完整版

57.5 vue.js和vue.runtime.js的使用

vue实例

57.6 vue单文件组件

打印Demo.vue的render

console.log(Demo.render.toString())
//打印结果
function() {
  var _vm = this
  var _h = _vm.$createElement
  var _c = _vm._self._c || _h
  return _c("div", { staticClass: "red" }, [
    _vm._v(" " + _vm._s(_vm.n) + " "),
    _c("button", { on: { click: _vm.add } }, [_vm._v("+1")])
  ])
}

57.7 SEO基本原理

57.8 总结, 命名规范

58 Vue构造选项

58.1 创建Vue 实例

在这里插入图片描述

58.2 new Vue有哪些选项

el: 替换的HTML部分, 容器或者挂载点
template或render只能用一个, 因为template是完整版用, 非完整版是render
propsdata,renderError, errorCaptured, parent用的少

在这里插入图片描述
红色: 好好学, 必学, 几句话就可以说明白的.
黄色: 高级属性,
绿色: 直接可以会
蓝色: 不常用, 可学可不学
紫色: 比较特殊, 需要讲解一下
灰色: 很不常用, 用的时候看文档

filter表面上很有用, 但实际没啥用, 尽量不要用它. 用methods来代替它.

vue的 data 有bug

58.3 el和data选项

el 和.$mount("") 一样

58.4 methods, components, 四个钩子

为什么组件地方的data 要使用函数而不是对象.
简单来说就是如果遇到同时引用这个组件问题的时候, 因为引入组件的时候是需要实例化(new Vue(Demo))2次, 地址相同一个地方修改了, 另一个地方也相应修改了. 也就是这个组件的内存地址是一样的. 但是是函数返回回来的对象则是不同的地址.

除了main.js里面data 可以写对象, 其他组件地方都要写函数形式.

methods有个bug, 就是每次渲染都会执行, 即使没有变化但是也会执行.

模块化就是把独立的功能放到一个地方

引入组件的3种方式:

console.log(window.Vue)

const Vue = window.Vue

Vue.config.productionTip = false
import Demo from './Demo.vue'

Vue.component("Demo2", {
  template: `
    <div>demo2</div>
  `
})

new Vue({
  components:{
    Demo,
    Demo3: {
      template: `
        <div>demo3</div>
      `
    }
  },
  data() {
    return {
      n: 0,
      array: [1, 2, 3, 4]
    }
  },
  template: `
    <div class="red">
      {{n}}
      <button @click="add">+1</button>
      <Demo/>
      <Demo2/>
      <Demo3/>
      <hr>
      {{filter()}}
    </div>
  `,
  methods: {
    add(){
      this.n += 1
    },
    filter(){
      return this.array.filter(i => i % 2 === 0)
    }
  }
}).$mount('#ben')

组件: 可以组合的物件

文件名要用小写
组件用大写开头

面试点: destroyed怎么用呢

58.1 Props

:可以传data中的变量和methods的方法.
但是不加:, 传的就是字符串

//data中的n
<Demo :message="n"/>
//传的字符串n
<Demo message="n"/>
<Demo :fn="add"/>

58.1 总结

59 【Vue全解】数据响应式

59.1 getter和setter

对应vue.js的文档 深入响应式原理部分

getter

let obj2 = {: "高",: "圆圆",
  get 姓名() {
    return this.+ this.;
  },
  age: 18
};

console.log("需求二:" + obj2.姓名);
// 总结:getter 就是这样用的。不加括号的函数,仅此而已。

setter

let obj3 = {: "高",: "圆圆",
  get 姓名() {
    return this.+ this.;
  },
  set 姓名(xxx){
    this.= xxx[0]
    this.= xxx.slice(1)
  },
  age: 18
};

obj3.姓名 = '高媛媛'

console.log(`需求三:姓 ${obj3.},名 ${obj3.}`)
//总结:setter 就是这样用的。用 = xxx 触发 set 函数

Object.defineProperty用法, 当对象实例化好后, 又想添加getter,setter时候使用.

let obj3 = {: "高",: "圆圆",
  get 姓名() {
    return this.+ this.;
  },
  set 姓名(xxx) {
    this.= xxx[0];
    this.= xxx.slice(1);
  },
  age: 18
};

var _xxx = 0

Object.defineProperty(obj3, "xxx", {
  get(){
    return _xxx
  },
  set(value){
    _xxx = value
  }
})


obj3.姓名 = "高媛媛";

console.log(`需求三:姓 ${obj3.},名 ${obj3.}`);
console.log(obj3)

59.2 Object.defineProperty

59.3 代理和监听

59.4 现场飙车看Vue.js源代码

59.5 小结

59.6 Vue的data的bug

59.7 数组的变异方法

59.8 纠错$set作用于数组时, 不会添加监听

59.9 ES 5的写法(不重要)

59.10 总结

60 【Vue全解】computed 和 watch

60.1 计算属性

性别不要用sex用gender

筛选男女代码1

// 引用完整版 Vue,方便讲解
import Vue from "vue/dist/vue.js";

Vue.config.productionTip = false;
let id = 0;
const createUser = (name, gender) => {
  id += 1;
  return { id, name, gender };
};

new Vue({
  data() {
    return {
      users: [
        createUser("方方", "男"),
        createUser("圆圆", "女"),
        createUser("小新", "男"),
        createUser("小葵", "女")
      ],
      displayUsers: []
    };
  },
  created() {
    this.displayUsers = this.users;
  },
  methods: {
    change(String) {
      if (String === "") {
        this.displayUsers = this.users;
      } else if (String === "male") {
        this.displayUsers = this.users.filter(u => u.gender === "男");
      } else if (String === "female") {
        this.displayUsers = this.users.filter(u => u.gender === "女");
      }
    }
  },
  // 如何给三个按钮加事件处理函数
  // 思路一:点击之后改 users
  // 思路二:使用 computed
  template: `
    <div>
      <div>
        <button @click="change('')">全部</button>
        <button @click="change('male')">男</button>
        <button @click="change('female')">女</button>
      </div>
      <ul>
        <li v-for="u in displayUsers" :key="u.id">
          {{u.name}} - {{u.gender}}
        </li>
      </ul>
    </div>
  `
}).$mount("#app");

筛选男女代码2, 用计算属性

// 引用完整版 Vue,方便讲解
import Vue from "vue/dist/vue.js";

Vue.config.productionTip = false;
let id = 0;
const createUser = (name, gender) => {
  id += 1;
  return { id, name, gender };
};

new Vue({
  data() {
    return {
      users: [
        createUser("方方", "男"),
        createUser("圆圆", "女"),
        createUser("小新", "男"),
        createUser("小葵", "女")
      ],
      gender: ""
    };
  },
  computed: {
    displayUsers() {
      const hash = {
        male: "男",
        female: "女"
      };
      const { users, gender } = this;
      if (gender === "") {
        return this.users;
      } else if (typeof gender === "string") {
        return users.filter(u => u.gender === hash[gender]);
      } else {
        throw new Error("gender 的值意外的值");
      }
    }
  },
  methods: {
    setGender(string) {
      this.gender = string;
    }
  },
  // 如何给三个按钮加事件处理函数
  // 思路一:点击之后改 users
  // 思路二:使用 computed
  template: `
    <div>
      <div>
        <button @click="setGender('')">全部</button>
        <button @click="setGender('male')">男</button>
        <button @click="setGender('female')">女</button>
      </div>
      <ul>
        <li v-for="u in displayUsers" :key="u.id">
          {{u.name}} - {{u.gender}}
        </li>
      </ul>
    </div>
  `
}).$mount("#app");

60.2 watch的两个例子

60.3 watch的deep选项

60.4 完整用法

60.5 computed v.s. watch

61 【Vue全解】模板、指令与修饰符

61.1 三种写模版的方式

第一种: 完整版写法, 直接卸载HTML
第二种: 完整版写法, 写在template中
template的div会被替换
第三种:不完整写法, 写在xxx.vue中
<template></template>中不是HTML语法是XML语法, 原因是更容易解析.
在这里插入图片描述

引入xxx.vue文件 import Xxx需要大写, 区分原生的标签.

61.2 v-html v-on v-bind v-if v-for v-show

{{}}不支持if else
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
v-show是是通过css来实现的

61.3 指令与修饰符

在这里插入图片描述
在这里插入图片描述

61.4 .sync修饰符

vue中的<template></template>的this可以直接省略

62. 【Vue全解】进阶构造属性

62.1 Directive指令

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

62.2 Mixin混入

在这里插入图片描述

62.3 Extends继承, 扩展

尽量先用Mixin

62.4 Provide和Inject

62.5 总结

在这里插入图片描述

63 【Vue全解】表单与v-model

63.1 基本用法

对应vue.js的表单输入绑定章

  • 输入框
<template>
  <div id="app">
    <input v-model="message" placeholder="edit me">
    <p>Message is: {{ message }}</p>
    <button @click="x">点击</button>
  </div>
</template>

<script>

export default {
  name: 'App',

  data(){
    return{
      message: "aaa"
    }
  },
  methods:{
    x(){
      this.message = "Jonathon Ben"
    }
  }
}
</script>
  • 多行文本
<template>
  <div id="app">
    <textarea v-model="message" placeholder="add multiple lines"></textarea>
    <p>Message is: {{ message }}</p>
    <button @click="x">点击</button>
  </div>
</template>

<script>

export default {
  name: 'App',

  data(){
    return{
      message: "aaa"
    }
  },
  methods:{
    x(){
      this.message = "Jonathon Ben"
    }
  }
}
</script>

有了Vue之后就尽量少用id

  • 复选框
<template>
    <div id="app">
        爱好: {{x}}
        <hr>
        <label>
            <input type="checkbox" v-model="x" value="抽烟">
            <span>抽烟</span>
        </label>
        <label>
            <input type="checkbox" v-model="x" value="喝酒">
            <span>喝酒</span>
        </label>
        <label>
            <input type="checkbox" v-model="x" value="打牌">
            <span>打牌</span>
        </label>
        <label>
            <!-- value中的值需要是数字, 使用动态绑定 -->
            <input type="checkbox" v-model="x" :value="1">
            <span>1</span>
        </label>
    </div>
</template>

<script>

    export default {
        name: 'App',

        data() {
            return {
                message: "aaa",
                x: []
            }
        },
    }
</script>

  • 单选框
<template>
    <div id="app">
        爱好: {{x}}
        <hr>
        <label>
            <input type="radio" v-model="x" name="want" value="抽烟">
            <span>抽烟</span>
        </label>
        <label>
            <input type="radio" v-model="x" name="want" value="喝酒">
            <span>喝酒</span>
        </label>
        <label>
            <input type="radio" v-model="x" name="want" value="打牌">
            <span>打牌</span>
        </label>
        <label>
            <!-- value中的值需要是数字, 使用动态绑定 -->
            <input type="radio" v-model="x" name="want" :value="1">
            <span>1</span>
        </label>
    </div>
</template>

<script>

    export default {
        name: 'App',

        data() {
            return {
                message: "aaa",
                x: "喝酒"
            }
        },
    }
</script>

  • 下拉框
<template>
    <div id="app">
        爱好: {{x}}
        <hr>
        <select v-model="x">
            <option value="">请选择</option>
            <option v-for="item in array" :value="item.value" :key="item.value">{{item.text}}</option>
        </select>
    </div>
</template>

<script>

    export default {
        name: 'App',

        data() {
            return {
                array: [
                    {
                        text: "抽烟", value: "抽烟"
                    },
                    {
                        text: "喝酒", value: "喝酒"
                    },
                    {
                        text: "打牌", value: "打牌"
                    },
                    {
                        text: 1, value: 1
                    },

                ],
                message: "aaa",
                x: ""
            }
        },
    }
</script>
  • 下拉多选框
<template>
    <div id="app">
        爱好: {{x}}
        <hr>
        <select multiple v-model="x">
            <option value="">请选择</option>
            <option v-for="item in array" :value="item.value" :key="item.value">{{item.text}}</option>
        </select>
    </div>
</template>

<script>

    export default {
        name: 'App',

        data() {
            return {
                array: [
                    {
                        text: "抽烟", value: "抽烟"
                    },
                    {
                        text: "喝酒", value: "喝酒"
                    },
                    {
                        text: "打牌", value: "打牌"
                    },
                    {
                        text: 1, value: 1
                    },

                ],
                message: "aaa",
                x: ""
            }
        },
    }
</script>
  • form表单

form 添加了button后, 默认回车就可以提交了

<template>
    <div id="app">
        登录{{user.username + user.password}}
        <hr>
        <!-- .prevent阻止默认事件 -->
        <form @submit.prevent="onSubmit">
            <label>
                <span>用户名</span>
                <input type="text" v-model="user.username">
            </label>
            <br>
            <label>
                <span>密码:</span>
                <input type="password" v-model="user.password">
            </label>

            <!-- 注释为button标准写法 -->
            <!-- <button type="submit">提交</button> -->
            <button>提交</button>
        </form>
    </div>
</template>

<script>

    export default {
        name: 'App',

        data() {
            return {
                user: {
                    username: "",
                    password: ""
                }
            }
        },
        methods:{
            onSubmit(){
                console.log(this.user)
            }
        }
    }
</script>

63.2 三个修饰器

  • .lazy
    v-model
    1 input事件, 键盘 鼠标 等任何输入设备
    2 change事件, 只在input失去焦点时触发
  • .number
    过滤只留下数字
  • .trim
    消除左右两边空格
<template>
    <div id="app">
        登录{{user}}
        <hr>
        <!-- .prevent阻止默认事件 -->
        <form @submit.prevent="onSubmit">
            <label>
                <span>用户名</span>
                <input type="text" v-model.lazy.trim="user.username">
            </label>
            <br>
            <label>
                <span>年龄</span>
                <input type="text" v-model.number="user.age">
            </label>
            <br>
            <label>
                <span>密码:</span>
                <input type="password" v-model="user.password">
            </label>

            <!-- 注释为button标准写法 -->
            <!-- <button type="submit">提交</button> -->
            <button>提交</button>
        </form>
    </div>
</template>

<script>

    export default {
        name: 'App',

        data() {
            return {
                user: {
                    username: "",
                    age: 0,
                    password: ""
                }
            }
        },
        methods: {
            onSubmit() {
                console.log(this.user)
            }
        }
    }
</script>

63.3 v-model

input是一个元素所以要用$event.target.value

v-model的等价写法<input type="text" :value="user.username" @input="user.username = $event.target.value">

app.vue

<template>
    <div id="app">
        登录{{user}}
        <hr>
        <!-- .prevent阻止默认事件 -->
        <form @submit.prevent="onSubmit">
            <label>
                <span>用户名</span>
                <!--自定义input只需要$event, 可能为了input区分-->
                <MyInput :value="user.username" @input="user.username = $event"/>
            </label>
            <br>

            <label>
                <span>年龄</span>
                <input type="text" v-model.number="user.age">
            </label>
            <br>
            <label>
                <span>密码:</span>
                <input type="password" v-model="user.password">
            </label>

            <!-- 注释为button标准写法 -->
            <!-- <button type="submit">提交</button> -->
            <button>提交</button>
        </form>
    </div>
</template>

<script>
    import MyInput from "./MyInput.vue";
    export default {
        name: 'App',
        components:{
            MyInput
        },
        data() {
            return {
                user: {
                    username: "",
                    age: 0,
                    password: ""
                }
            }
        },
        methods: {
            onSubmit() {
                console.log(this.user)
            }
        }
    }
</script>

MyInput.vue

<template>
    <div class="red warpper" >
        <input type="text" :value="value" @input="$emit('input', $event.target.value)
        ">
    </div>
</template>
<script>
    export default {
        name: "MyInput",
        props:{
            value:{
                type: String
            }
        }
    }
</script>

<style scoped>
    .red{
        background: red;
    }

    .warpper{
        display: inline-block;
    }
</style>

63.4 如何使用ant-design-vue

如何查看一个项目是否维护,eg: element 查看commit最后提交日期 不要使用3个月内没有维护的前端组件. 因为前端变化特别快.
在这里插入图片描述
在这里插入图片描述

函数使用on不使用handle, 一是因为简洁, 而是表达直观.

先安装ant design
main.js

import Vue from 'vue';
import Antd from 'ant-design-vue';
import App from './App';
import 'ant-design-vue/dist/antd.css';

Vue.use(Antd);

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')

app.vue

<template>
    <a-form
            id="components-form-demo-normal-login"
            :form="form"
            class="login-form"
            @submit.prevent="onSubmit"
    >
        <a-form-item>
            <a-input
                v-decorator="[
                  '用户名:',
                  { rules: [
                      { required: true, message: '用户名不能为空' }] },
                ]"
                placeholder="用户名"
            >
                <a-icon slot="prefix" type="user" style="color: rgba(0,0,0,.25)"/>
            </a-input>
        </a-form-item>
        <a-form-item>
            <a-input
                v-decorator="[
                  '密码:',
                  { rules: [{ required: true, message: '密码不能为空' }] },
                ]"
                type="password"
                placeholder="密码"
                >
                <a-icon slot="prefix" type="lock" style="color: rgba(0,0,0,.25)"/>
            </a-input>
        </a-form-item>
        <a-form-item>
            <a-button type="primary" html-type="submit" class="login-form-button">登录</a-button>
        </a-form-item>
    </a-form>
</template>

<script>
    export default {
        name: 'App',
        beforeCreate() {
            this.form = this.$form.createForm(this, {name: 'normal_login'});
        },
        methods: {
            onSubmit() {
                // e.preventDefault();
                // @submit.prevent="onSubmit" 等价于.prevent
                this.form.validateFields((err, values) => {
                    if (!err) {
                        console.log('data: ', values);
                    } else {
                        console.log("err: ", err);
                    }
                });
            }
        }
    }
</script>
<style scoped>
    #components-form-demo-normal-login .login-form {
        max-width: 300px;
    }
    #components-form-demo-normal-login .login-form-forgot {
        float: right;
    }
    #components-form-demo-normal-login .login-form-button {
        width: 100%;
    }
</style>

64 【Vue全解】Vue Router - 前端路由实现思路

64.1 目录

64.2 路由是什么

路由就是分发请求
路由器就是 分发请求的机器.

64.3 优化代码

index.html

<!doctype html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>router</title>
</head>
<body>
    <a href="#1">go to 1</a>
    <a href="#2">go to 2</a>
    <a href="#3">go to 3</a>
    <a href="#4">go to 4</a>
    <div id="app"></div>

    <div id="div1" style="display: none">1</div>
    <div id="div2" style="display: none">2</div>
    <div id="div3" style="display: none">3</div>
    <div id="div4" style="display: none">4</div>
    <div id="div404" style="display: none">404</div>

    <script src="./src/index.js"></script>
</body>
</html>

index.js

function route(){
    //获取用户想去哪
    let number = window.location.hash.substr(1) || 1
    let app = document.querySelector("#app")
    //获取界面
    let div = document.querySelector(`#div${number}`)
    if(!div){
        div = document.querySelector("#div404")
    }
    //渲染界面
    div.style.display = "block"
    if(app.children.length > 0){
        app.children[0].style.display = "none"
        document.body.appendChild(app.children[0])
    }
    //展示界面
    app.appendChild(div)
}
route()

//检测hash改变
window.addEventListener("hashchange", ()=>{
    console.log("路由改变了");
    route()
})

64.4 路由表

index.html

<!doctype html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>router</title>
</head>
<body>
    <a href="#1">go to 1</a>
    <a href="#2">go to 2</a>
    <a href="#3">go to 3</a>
    <a href="#4">go to 4</a>
    <div id="app"></div>
    <div id="div404" style="display: none">404</div>

    <script src="./src/index.js"></script>
</body>
</html>

index.js

const div1 = document.createElement("div")
div1.innerHTML = "1"
const div2 = document.createElement("div")
div2.innerHTML = "2"
const div3 = document.createElement("div")
div3.innerHTML = "3"
const div4 = document.createElement("div")
div4.innerHTML = "4"
const routeTable = {
    "1": div1,
    "2": div2,
    "3": div3,
    "4": div4
}

function route(){
    //获取用户想去哪
    let number = window.location.hash.substr(1) || 1
    let app = document.querySelector("#app")
    //获取界面
    let div = routeTable[number.toString()]
    if(!div){
        div = document.querySelector("#div404")
    }
    //渲染界面
    div.style.display = "block"

    //展示界面
    app.innerHTML = ""
    app.appendChild(div)
}
route()

//检测hash改变
window.addEventListener("hashchange", ()=>{
    console.log("路由改变了");
    route()
})

在这里插入图片描述
嵌套路由

64.5 history模式

hashbang 谷歌针对hash路由问题的方案

index.html

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
    />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>router</title>
  </head>
  <body>
    <a class="link" href="/1">go to 1</a>
    <a class="link" href="/2">go to 2</a>
    <a class="link" href="/3">go to 3</a>
    <a class="link" href="/4">go to 4</a>
    <div id="app"></div>
    <div id="div404" style="display: none">404</div>

    <script src="./src/index.js"></script>
  </body>
</html>

index.js

let app = document.querySelector("#app");
const div1 = document.createElement("div");
div1.innerHTML = "1";
const div2 = document.createElement("div");
div2.innerHTML = "2";
const div3 = document.createElement("div");
div3.innerHTML = "3";
const div4 = document.createElement("div");
div4.innerHTML = "4";
const routeTable = {
  "/1": div1,
  "/2": div2,
  "/3": div3,
  "/4": div4
};

function route(container) {
  //获取用户想去哪
  let number = window.location.pathname;
  console.log("number: " + number);

  if (number === "/") {
    number = "/1";
  }

  //获取界面
  let div = routeTable[number.toString()];

  if (!div) {
    div = document.querySelector("#div404");
  }
  //渲染界面
  div.style.display = "block";

  //展示界面
  container.innerHTML = "";
  container.appendChild(div);
}

route(app);

const allA = document.querySelectorAll("a.link");
for (let a of allA) {
  a.addEventListener("click", e => {
    e.preventDefault();
    const href = a.getAttribute("href");
    window.history.pushState(null, `page ${href}`, href);
    //通知
    onStateChagne();
  });
}

function onStateChagne() {
  console.log("state change");
  route(app);
}

64.6 history和hash模式的对比

65.7 memory模式

index.html

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
    />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>router</title>
  </head>
  <body>
    <a class="link" href="/1">go to 1</a>
    <a class="link" href="/2">go to 2</a>
    <a class="link" href="/3">go to 3</a>
    <a class="link" href="/4">go to 4</a>
    <div id="app"></div>
    <div id="div404" style="display: none">404</div>

    <script src="./src/index.js"></script>
  </body>
</html>

index.js

let app = document.querySelector("#app");
const div1 = document.createElement("div");
div1.innerHTML = "1";
const div2 = document.createElement("div");
div2.innerHTML = "2";
const div3 = document.createElement("div");
div3.innerHTML = "3";
const div4 = document.createElement("div");
div4.innerHTML = "4";
const routeTable = {
  "/1": div1,
  "/2": div2,
  "/3": div3,
  "/4": div4
};

function route(container) {
  //获取用户想去哪
  let number = window.localStorage.getItem("xxx");
  console.log("number: " + number);

  if (!number) {
    number = "/1";
  }

  //获取界面
  let div = routeTable[number.toString()];

  if (!div) {
    div = document.querySelector("#div404");
  }
  //渲染界面
  div.style.display = "block";

  //展示界面
  container.innerHTML = "";
  container.appendChild(div);
}

route(app);

const allA = document.querySelectorAll("a.link");
for (let a of allA) {
  a.addEventListener("click", e => {
    e.preventDefault();
    const href = a.getAttribute("href");
    window.localStorage.setItem("xxx", href);
    //通知
    onStateChagne();
  });
}

function onStateChagne() {
  console.log("state change");
  route(app);
}

在这里插入图片描述

65.8 如何阅读VueRouter源代码

66【Vue全解】深入讲解 Vue 动画原理

66.1【Vue全解】Vue动画方式1- CSS transition

css 有些属性不需要初始值, 有些属性需要初始值.

不要用show这个单词, 是动词, 用visible

66.2【Vue全解】Vue动画方式2- CSS animation

animation.css库 用来animation动画

66.3【Vue全解】Vue动画方式3- JS操作动画

velocity是用js来控制动画

66.4【Vue全解】Vue动画方式4- 多元素动画

动态组件可以用作tabbar
在这里插入图片描述

66.5【Vue全解】列表动画

列表过渡经常用到, 而且复杂

transition-group

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值