├── .browserslistrc
├── .eslintrc.js
├── .gitignore
├── README.md
├── babel.config.js
├── package-lock.json
├── package.json
├── postcss.config.js
├── public
├── favicon.ico
└── index.html
├── src
├── App.vue
├── api
│ ├── account.js
│ ├── article.js
│ ├── common.js
│ ├── skill.js
│ └── zone.js
├── assets
│ ├── css
│ │ ├── default.scss
│ │ ├── mixin.scss
│ │ └── reset.css
│ ├── image
│ │ ├── 404.jpg
│ │ ├── Article-herader.jpg
│ │ ├── Skill-header.jpg
│ │ ├── active-acu.png
│ │ ├── active-me.png
│ │ ├── admin.png
│ │ ├── bg.jpeg
│ │ ├── blog.gif
│ │ ├── github.jpg
│ │ ├── normal-acu.png
│ │ ├── normal-me.png
│ │ ├── search.png
│ │ ├── skill.png
│ │ ├── touxiang.jpg
│ │ ├── 书-2.png
│ │ ├── 书.png
│ │ ├── 奖杯.png
│ │ ├── 文件.png
│ │ ├── 日历.png
│ │ ├── 星星.png
│ │ ├── 检查.png
│ │ ├── 灯泡.png
│ │ ├── 蜡笔.png
│ │ ├── 讲话气泡.png
│ │ ├── 证书.png
│ │ └── 铅笔.png
│ └── js
│ │ └── rem.js
├── components
│ ├── count-up
│ │ ├── count-to.vue
│ │ └── index.js
│ ├── dialogImg.vue
│ ├── global.js
│ ├── notFound.vue
│ └── top
│ │ └── index.vue
├── filters
│ └── index.js
├── main.js
├── mixin
│ ├── delTouch.js
│ ├── loading.js
│ └── touchMove.js
├── plugin
│ ├── match-media
│ │ ├── index.js
│ │ ├── lib
│ │ │ └── helper.js
│ │ └── template
│ │ │ └── mask.vue
│ ├── top
│ │ ├── index.js
│ │ ├── lib
│ │ │ └── helper.js
│ │ └── template
│ │ │ └── top.vue
│ └── vue-load
│ │ ├── index.js
│ │ ├── lib
│ │ ├── helper.js
│ │ └── load.js
│ │ └── template
│ │ └── loading.vue
├── router
│ ├── index.js
│ └── routes.js
├── store
│ ├── actions.js
│ ├── index.js
│ ├── mutation-types.js
│ ├── mutations.js
│ └── state.js
├── utils
│ ├── code.js
│ ├── fastClick.js
│ ├── index.js
│ ├── jsonp.js
│ ├── request.js
│ └── touchMove.js
└── views
│ ├── Article
│ ├── List.vue
│ ├── body
│ │ ├── DesignPattern.vue
│ │ ├── QuestionsCSS.vue
│ │ ├── QuesttionsJS.vue
│ │ └── vertualDom.vue
│ ├── content
│ │ └── index.vue
│ └── index.vue
│ ├── Home
│ ├── Card
│ │ ├── Calendar.vue
│ │ ├── MenuIcon.vue
│ │ └── index.vue
│ └── index.vue
│ ├── Menu
│ ├── Me.vue
│ ├── Nav.vue
│ └── index.vue
│ ├── Skill
│ └── index.vue
│ └── Zone
│ ├── Acu.vue
│ ├── Me.vue
│ ├── Tabar.vue
│ ├── TreeMenu.vue
│ └── index.vue
├── study
├── Questions
│ ├── index.css
│ ├── index.html
│ ├── 二分查找.js
│ ├── 原型.js
│ ├── 工厂模式.js
│ ├── 设计模式之原型模式.js
│ └── 设计模式之构建者模式.js
└── diffDom
│ ├── diffDom.js
│ ├── index.html
│ └── vertualDom.js
├── test.js
└── vue.config.js
/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not ie <= 8
4 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true
5 | },
6 | extends: ["plugin:vue/essential", "@vue/prettier"],
7 | rules: {
8 | "no-console": process.env.NODE_ENV === "production" ? "error" : "off",
9 | "no-debugger": process.env.NODE_ENV === "production" ? "error" : "off"
10 | },
11 | parserOptions: {
12 | parser: "babel-eslint"
13 | }
14 | };
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | dist
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 |
14 | # Editor directories and files
15 | .idea
16 | .vscode
17 | *.suo
18 | *.ntvs*
19 | *.njsproj
20 | *.sln
21 | *.sw*
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | ## vue-blog
4 |
5 | 前后端分离的个人博客 🛠️
6 | 在线访问:
7 | [移动端](http://cc.ztsky.cn)
8 | [PC 端](http://cc.ztsky.cn:8011)
9 |
10 | ## 技术栈
11 |
12 | ```
13 | 移动端: vue-cli3 vue2.x vant-ui
14 | PC 端 umi react antd-ui
15 | admin: vue-cli3 vue2.x element-ui
16 | 服务器: egg sequelize mysql redis nginx
17 | ```
18 |
19 | ## 运行
20 |
21 | ```
22 | 所需环境 node
23 | 下载依赖:npm install
24 | 项目启动:npm run serve 打开 localhost:8010
25 | 项目打包:npm run build
26 | ```
27 |
28 | ## 客户端效果
29 |
30 | 
31 |
32 | ## 后台管理
33 |
34 | 
35 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ["@vue/app"]
3 | };
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "blog",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve ",
7 | "build": "vue-cli-service build",
8 | "build-load": "vue-cli-service build --target lib --name vue-load src/plugin/vue-load/index.js",
9 | "lint": "vue-cli-service lint"
10 | },
11 | "dependencies": {
12 | "animate.css": "^3.7.0",
13 | "axios": "^0.18.0",
14 | "babel-preset-es2015": "^6.24.1",
15 | "countup": "^1.8.2",
16 | "fastclick": "^1.0.6",
17 | "mavon-editor": "^2.6.17",
18 | "optimize-css-assets-webpack-plugin": "^5.0.1",
19 | "postcss-px2rem": "^0.3.0",
20 | "uglifyjs-webpack-plugin": "1.3.0",
21 | "vant": "^1.4.8",
22 | "vue": "^2.5.17",
23 | "vue-js-grid": "^1.0.1",
24 | "vue-particles": "^1.0.9",
25 | "vue-router": "^3.0.1",
26 | "vuex": "^3.0.1"
27 | },
28 | "devDependencies": {
29 | "@vue/cli-plugin-babel": "^3.0.3",
30 | "@vue/cli-plugin-eslint": "^3.0.3",
31 | "@vue/cli-service": "^3.0.3",
32 | "@vue/eslint-config-prettier": "^3.0.3",
33 | "babel-plugin-import": "^1.8.0",
34 | "babel-polyfill": "^6.26.0",
35 | "node-sass": "^4.9.3",
36 | "sass-loader": "^7.1.0",
37 | "vue-template-compiler": "^2.5.17"
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | autoprefixer: {},
4 | "postcss-px2rem": {
5 | remUnit: 37.5
6 | }
7 | }
8 | };
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z253573760/vue-blog/7c3396427bc3e9783b0a95c0e59db86d710d7bef/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
13 |
14 |
15 |
16 |
17 |
18 | 灿灿's Blog
19 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
7 |
13 |
14 |
15 |
16 |
19 |
20 |
21 |
22 |
23 |
25 |
26 |
27 |
28 |
29 |
95 |
96 |
129 |
--------------------------------------------------------------------------------
/src/api/account.js:
--------------------------------------------------------------------------------
1 | import axios from "../utils/request";
2 |
3 | export const getUserInfo = function() {
4 | return axios.get(`/account/info`);
5 | };
6 |
--------------------------------------------------------------------------------
/src/api/article.js:
--------------------------------------------------------------------------------
1 | import axios from "../utils/request";
2 | import qs from "qs";
3 | export const getArticleList = function (pageOpts) {
4 | return axios.get(`/article?${qs.stringify(pageOpts)}`);
5 | };
6 |
7 | export const getArticle = function (id) {
8 | return axios.get(`/article/${id}`);
9 | };
--------------------------------------------------------------------------------
/src/api/common.js:
--------------------------------------------------------------------------------
1 | import axios from "../utils/request";
2 |
3 | export const getIp = function() {
4 | return axios.get(`/ip`);
5 | };
6 |
7 | export const getWether = function() {
8 | return axios.get(`/wether`);
9 | };
10 |
--------------------------------------------------------------------------------
/src/api/skill.js:
--------------------------------------------------------------------------------
1 | import axios from "../utils/request";
2 |
3 | export const getSkillList = function() {
4 | return axios.get(`/skill`);
5 | };
6 |
--------------------------------------------------------------------------------
/src/api/zone.js:
--------------------------------------------------------------------------------
1 | import axios from "../utils/request";
2 | import qs from "qs";
3 | export const getZoneList = function (pageSize, current) {
4 | const params = { pageSize, current };
5 | return axios.get(`/zone?${qs.stringify(params)}`);
6 | };
7 |
--------------------------------------------------------------------------------
/src/assets/css/default.scss:
--------------------------------------------------------------------------------
1 | @function px2rem($px){
2 | $rem: 37.5px;
3 | @return($px/$rem) + rem
4 | };
5 |
6 | $fontSize:px2rem(16px);
7 |
--------------------------------------------------------------------------------
/src/assets/css/mixin.scss:
--------------------------------------------------------------------------------
1 | @import "./default.scss";
2 |
3 | .bg {
4 | height: 100%;
5 | background-size: 100% 100%;
6 | text-align: center;
7 | padding: px2rem(80px);
8 | }
--------------------------------------------------------------------------------
/src/assets/css/reset.css:
--------------------------------------------------------------------------------
1 | * {
2 | -webkit-box-sizing: border-box;
3 | -moz-box-sizing: border-box;
4 | box-sizing: border-box;
5 | }
6 | *:before,
7 | *:after {
8 | -webkit-box-sizing: border-box;
9 | -moz-box-sizing: border-box;
10 | box-sizing: border-box;
11 | }
12 | body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, code, form, fieldset, legend, input, button, textarea, p, blockquote, th, td {
13 | margin: 0;
14 | padding: 0;
15 | }
16 | body,html{
17 | background: #fff;
18 | color: #555;
19 | font-size: 14px;
20 | height:100%;
21 | width:100%;
22 | font-family: "Arial", "Microsoft YaHei", "黑体", "宋体", sans-serif;
23 | }
24 | td, th, caption {
25 | font-size: 14px;
26 | }
27 | h1, h2, h3, h4, h5, h6 {
28 | font-weight: normal;
29 | font-size: 100%;
30 | }
31 | address, caption, cite, code, dfn, em, strong, th, var {
32 | font-style: normal;
33 | font-weight: normal;
34 | }
35 | a {
36 | color: #555;
37 | text-decoration: none;
38 | }
39 | a:hover {
40 | text-decoration: underline;
41 | }
42 | img {
43 | border: none;
44 | vertical-align: middle;
45 | }
46 | ol, ul, li {
47 | list-style: none;
48 | }
49 | input, textarea, select, button {
50 | font: 14px "Arial", "Microsoft YaHei", "黑体", "宋体", sans-serif;
51 | }
52 | table {
53 | border-collapse: collapse;
54 | }
55 | html {
56 | overflow-y: scroll;
57 | }
58 | .clearfix:before,
59 | .clearfix:after {
60 | content: " ";
61 | display: inline-block;
62 | height: 0;
63 | clear: both;
64 | visibility: hidden;
65 | }
66 | .clearfix {
67 | *zoom: 1;
68 | }
69 |
70 | /*公共类*/
71 | .fl {
72 | float: left
73 | }
74 | .fr {
75 | float: right
76 | }
77 | .al {
78 | text-align: left
79 | }
80 | .ac {
81 | text-align: center
82 | }
83 | .ar {
84 | text-align: right
85 | }
86 | .hide {
87 | display: none
88 | }
--------------------------------------------------------------------------------
/src/assets/image/404.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z253573760/vue-blog/7c3396427bc3e9783b0a95c0e59db86d710d7bef/src/assets/image/404.jpg
--------------------------------------------------------------------------------
/src/assets/image/Article-herader.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z253573760/vue-blog/7c3396427bc3e9783b0a95c0e59db86d710d7bef/src/assets/image/Article-herader.jpg
--------------------------------------------------------------------------------
/src/assets/image/Skill-header.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z253573760/vue-blog/7c3396427bc3e9783b0a95c0e59db86d710d7bef/src/assets/image/Skill-header.jpg
--------------------------------------------------------------------------------
/src/assets/image/active-acu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z253573760/vue-blog/7c3396427bc3e9783b0a95c0e59db86d710d7bef/src/assets/image/active-acu.png
--------------------------------------------------------------------------------
/src/assets/image/active-me.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z253573760/vue-blog/7c3396427bc3e9783b0a95c0e59db86d710d7bef/src/assets/image/active-me.png
--------------------------------------------------------------------------------
/src/assets/image/admin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z253573760/vue-blog/7c3396427bc3e9783b0a95c0e59db86d710d7bef/src/assets/image/admin.png
--------------------------------------------------------------------------------
/src/assets/image/bg.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z253573760/vue-blog/7c3396427bc3e9783b0a95c0e59db86d710d7bef/src/assets/image/bg.jpeg
--------------------------------------------------------------------------------
/src/assets/image/blog.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z253573760/vue-blog/7c3396427bc3e9783b0a95c0e59db86d710d7bef/src/assets/image/blog.gif
--------------------------------------------------------------------------------
/src/assets/image/github.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z253573760/vue-blog/7c3396427bc3e9783b0a95c0e59db86d710d7bef/src/assets/image/github.jpg
--------------------------------------------------------------------------------
/src/assets/image/normal-acu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z253573760/vue-blog/7c3396427bc3e9783b0a95c0e59db86d710d7bef/src/assets/image/normal-acu.png
--------------------------------------------------------------------------------
/src/assets/image/normal-me.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z253573760/vue-blog/7c3396427bc3e9783b0a95c0e59db86d710d7bef/src/assets/image/normal-me.png
--------------------------------------------------------------------------------
/src/assets/image/search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z253573760/vue-blog/7c3396427bc3e9783b0a95c0e59db86d710d7bef/src/assets/image/search.png
--------------------------------------------------------------------------------
/src/assets/image/skill.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z253573760/vue-blog/7c3396427bc3e9783b0a95c0e59db86d710d7bef/src/assets/image/skill.png
--------------------------------------------------------------------------------
/src/assets/image/touxiang.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z253573760/vue-blog/7c3396427bc3e9783b0a95c0e59db86d710d7bef/src/assets/image/touxiang.jpg
--------------------------------------------------------------------------------
/src/assets/image/书-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z253573760/vue-blog/7c3396427bc3e9783b0a95c0e59db86d710d7bef/src/assets/image/书-2.png
--------------------------------------------------------------------------------
/src/assets/image/书.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z253573760/vue-blog/7c3396427bc3e9783b0a95c0e59db86d710d7bef/src/assets/image/书.png
--------------------------------------------------------------------------------
/src/assets/image/奖杯.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z253573760/vue-blog/7c3396427bc3e9783b0a95c0e59db86d710d7bef/src/assets/image/奖杯.png
--------------------------------------------------------------------------------
/src/assets/image/文件.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z253573760/vue-blog/7c3396427bc3e9783b0a95c0e59db86d710d7bef/src/assets/image/文件.png
--------------------------------------------------------------------------------
/src/assets/image/日历.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z253573760/vue-blog/7c3396427bc3e9783b0a95c0e59db86d710d7bef/src/assets/image/日历.png
--------------------------------------------------------------------------------
/src/assets/image/星星.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z253573760/vue-blog/7c3396427bc3e9783b0a95c0e59db86d710d7bef/src/assets/image/星星.png
--------------------------------------------------------------------------------
/src/assets/image/检查.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z253573760/vue-blog/7c3396427bc3e9783b0a95c0e59db86d710d7bef/src/assets/image/检查.png
--------------------------------------------------------------------------------
/src/assets/image/灯泡.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z253573760/vue-blog/7c3396427bc3e9783b0a95c0e59db86d710d7bef/src/assets/image/灯泡.png
--------------------------------------------------------------------------------
/src/assets/image/蜡笔.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z253573760/vue-blog/7c3396427bc3e9783b0a95c0e59db86d710d7bef/src/assets/image/蜡笔.png
--------------------------------------------------------------------------------
/src/assets/image/讲话气泡.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z253573760/vue-blog/7c3396427bc3e9783b0a95c0e59db86d710d7bef/src/assets/image/讲话气泡.png
--------------------------------------------------------------------------------
/src/assets/image/证书.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z253573760/vue-blog/7c3396427bc3e9783b0a95c0e59db86d710d7bef/src/assets/image/证书.png
--------------------------------------------------------------------------------
/src/assets/image/铅笔.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/z253573760/vue-blog/7c3396427bc3e9783b0a95c0e59db86d710d7bef/src/assets/image/铅笔.png
--------------------------------------------------------------------------------
/src/assets/js/rem.js:
--------------------------------------------------------------------------------
1 | // !(function(n, e) {
2 | // var t = n.documentElement,
3 | // i = "orientationchange" in window ? "orientationchange" : "resize",
4 | // d = function() {
5 | // var n = t.clientWidth;
6 | // //n && (t.style.fontSize = (n > 750 ? 750 : n) / 750 * 100 + "px")
7 | // n && (t.style.fontSize = (n / 750) * 100 + "px");
8 | // };
9 | // n.addEventListener &&
10 | // (e.addEventListener(i, d, !1),
11 | // d(),
12 | // n.addEventListener("DOMContentLoaded", d, !1));
13 | // })(document, window);
14 | !(function(doc, win) {
15 | var docEl = doc.documentElement,
16 | resizeEvt = "orientationchange" in window ? "orientationchange" : "resize",
17 | recalc = function() {
18 | var clientWidth = docEl.clientWidth;
19 | if (!clientWidth) return;
20 | docEl.style.fontSize = 20 * (clientWidth / 320) + "px";
21 | };
22 | if (!doc.addEventListener) return;
23 | win.addEventListener(resizeEvt, recalc, false);
24 | doc.addEventListener("DOMContentLoaded", recalc, false);
25 | })(document, window);
26 |
--------------------------------------------------------------------------------
/src/components/count-up/count-to.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
欢迎第{{ init }}位访客
7 |
8 |
13 | 确定
14 |
15 |
16 |
17 |
18 |
19 |
20 |
202 |
249 |
--------------------------------------------------------------------------------
/src/components/count-up/index.js:
--------------------------------------------------------------------------------
1 | import countTo from "./count-to.vue";
2 | export default countTo;
3 |
--------------------------------------------------------------------------------
/src/components/dialogImg.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
![]()
4 |
5 |
6 |
7 |
21 |
25 |
--------------------------------------------------------------------------------
/src/components/global.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 |
3 | function capitalizeFirstLetter(string) {
4 | return string.charAt(0).toUpperCase() + string.slice(1);
5 | }
6 |
7 | const requireComponent = require.context(
8 | ".",
9 | false,
10 | /\.vue$/
11 | //找到components文件夹下以.vue命名的文件
12 | );
13 |
14 | requireComponent.keys().forEach(fileName => {
15 | const componentConfig = requireComponent(fileName);
16 |
17 | const componentName = capitalizeFirstLetter(
18 | fileName.replace(/^\.\//, "").replace(/\.\w+$/, "")
19 | //因为得到的filename格式是: './baseButton.vue', 所以这里我们去掉头和尾,只保留真正的文件名
20 | );
21 |
22 | Vue.component(componentName, componentConfig.default || componentConfig);
23 | });
24 |
--------------------------------------------------------------------------------
/src/components/notFound.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
15 |
16 |
17 |
25 |
--------------------------------------------------------------------------------
/src/components/top/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
46 |
69 |
--------------------------------------------------------------------------------
/src/filters/index.js:
--------------------------------------------------------------------------------
1 | export const fmtDate = function (obj) {
2 | var date = new Date(obj);
3 | var y = 1900 + date.getYear();
4 | var m = "0" + (date.getMonth() + 1);
5 | var d = "0" + date.getDate();
6 | return y + "-" + m.substring(m.length - 2, m.length) + "-" + d.substring(d.length - 2, d.length);
7 | }
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import App from "@/App.vue";
3 | import router from "@/router";
4 | import store from "@/store";
5 | import Vant from "vant";
6 | import VueParticles from "vue-particles";
7 | import "@/assets/css/reset.css";
8 | import "@/assets/css/mixin.scss";
9 | import "@/assets/js/rem.js";
10 | import "@/utils/fastClick.js";
11 | import "@/components/global.js";
12 | import Grid from "vue-js-grid";
13 | import * as filters from "./filters";
14 | import mavonEditor from "mavon-editor";
15 | import "mavon-editor/dist/css/index.css";
16 |
17 |
18 | //自己封装的插件
19 | import Loading from "@/plugin/vue-load";
20 | import MatchMedia from "@/plugin/match-media";
21 | import Top from "@/plugin/top";
22 | Vue.use(mavonEditor);
23 | Vue.use(Loading);
24 | Vue.use(MatchMedia);
25 | Vue.use(Top);
26 | Vue.use(Grid);
27 | Vue.use(Vant);
28 | Vue.use(VueParticles);
29 |
30 | Object.keys(filters).forEach(key => {
31 | Vue.filter(key, filters[key]);
32 | });
33 |
34 | Vue.directive("color", {
35 | bind(el, bindding) {
36 | el.style.color = bindding.value;
37 | }
38 | });
39 |
40 | Vue.config.productionTip = false;
41 | const vue = new Vue({
42 | router,
43 | store,
44 | render: h => h(App)
45 | }).$mount("#app");
46 |
47 | window.vue = vue;
--------------------------------------------------------------------------------
/src/mixin/delTouch.js:
--------------------------------------------------------------------------------
1 | import handler from "@/utils/touchMove";
2 |
3 | const delTouch = {
4 | created() {
5 | document.body.removeEventListener("touchmove", handler, false);
6 | },
7 | activated() {
8 | document.body.removeEventListener("touchmove", handler, false);
9 | }
10 | };
11 | export default delTouch;
12 |
--------------------------------------------------------------------------------
/src/mixin/loading.js:
--------------------------------------------------------------------------------
1 | const loadding = {
2 | created() {
3 | this.$loading.show();
4 | setTimeout(() => this.$loading.hide(), 1000);
5 | }
6 | };
7 | export default loadding;
8 |
--------------------------------------------------------------------------------
/src/mixin/touchMove.js:
--------------------------------------------------------------------------------
1 | import handler from "@/utils/touchMove";
2 |
3 | const touchMove = {
4 | created() {
5 | document.body.addEventListener("touchmove", handler, false);
6 | },
7 | activated() {
8 | document.body.addEventListener("touchmove", handler, false);
9 | }
10 | };
11 | export default touchMove;
12 |
--------------------------------------------------------------------------------
/src/plugin/match-media/index.js:
--------------------------------------------------------------------------------
1 | import Mask from "./template/mask";
2 | const loadingPlugin = {
3 | install(Vue) {
4 | const MaskVue = Vue.extend(Mask);
5 | const $vm = new MaskVue({
6 | el: document.createElement("div")
7 | });
8 |
9 | document.body.appendChild($vm.$el);
10 | }
11 | };
12 | export default loadingPlugin;
13 |
--------------------------------------------------------------------------------
/src/plugin/match-media/lib/helper.js:
--------------------------------------------------------------------------------
1 | export function orientate(vm) {
2 | window.addEventListener(
3 | "onorientationchange" in window ? "orientationchange" : "resize",
4 | () => {
5 | if (window.orientation === 180 || window.orientation === 0) {
6 | // "竖屏状态!
7 | vm.show = false;
8 | }
9 | if (window.orientation === 90 || window.orientation === -90) {
10 | // "横屏屏状态!
11 | vm.show = true;
12 | }
13 | },
14 | false
15 | );
16 | }
17 |
--------------------------------------------------------------------------------
/src/plugin/match-media/template/mask.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
42 |
60 |
--------------------------------------------------------------------------------
/src/plugin/top/index.js:
--------------------------------------------------------------------------------
1 | import Top from "./template/top";
2 | const loadingPlugin = {
3 | install(Vue) {
4 | const TopVue = Vue.extend(Top);
5 | const $vm = new TopVue({
6 | el: document.createElement("div")
7 | });
8 |
9 | document.body.appendChild($vm.$el);
10 | }
11 | };
12 | export default loadingPlugin;
--------------------------------------------------------------------------------
/src/plugin/top/lib/helper.js:
--------------------------------------------------------------------------------
1 | export function smoothScroll() {
2 | const currentScroll =
3 | document.documentElement.scrollTop || document.body.scrollTop;
4 | if (currentScroll > 0) {
5 | window.requestAnimationFrame(smoothScroll);
6 | window.scrollTo(0, currentScroll - currentScroll / 5);
7 | }
8 | }
--------------------------------------------------------------------------------
/src/plugin/top/template/top.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
46 |
70 |
--------------------------------------------------------------------------------
/src/plugin/vue-load/index.js:
--------------------------------------------------------------------------------
1 | import load from "./lib/load";
2 | const loadingPlugin = {
3 | install(Vue) {
4 | load(Vue);
5 | }
6 | };
7 | export default loadingPlugin;
8 |
--------------------------------------------------------------------------------
/src/plugin/vue-load/lib/helper.js:
--------------------------------------------------------------------------------
1 | export function isString(str) {
2 | return Object.prototype.toString.call(str) === "[object string]";
3 | }
4 |
--------------------------------------------------------------------------------
/src/plugin/vue-load/lib/load.js:
--------------------------------------------------------------------------------
1 | import Load from "../template/loading";
2 | export default function(Vue) {
3 | const Loading = Vue.extend(Load);
4 | const $vm = new Loading({
5 | el: document.createElement("div")
6 | });
7 | document.body.appendChild($vm.$el);
8 | const loading = {
9 | show() {
10 | $vm.show = true;
11 | },
12 | hide() {
13 | $vm.show = false;
14 | }
15 | };
16 | Vue.prototype.$loading = loading;
17 | }
18 |
--------------------------------------------------------------------------------
/src/plugin/vue-load/template/loading.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
21 |
102 |
--------------------------------------------------------------------------------
/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import Router from "vue-router";
3 | import routes from "./routes";
4 | Vue.use(Router);
5 |
6 | export default new Router({
7 | mode: "history",
8 | base: process.env.BASE_URL,
9 | routes
10 | });
11 |
--------------------------------------------------------------------------------
/src/router/routes.js:
--------------------------------------------------------------------------------
1 | export default [
2 | {
3 | path: "/",
4 | // redirect: "/home",
5 | name: "home",
6 | meta: {
7 | title: "首页",
8 | icon: require("@/assets/image/日历.png")
9 | },
10 | component: () => import("@/views/Home")
11 | },
12 | {
13 | path: "*",
14 | redirect: "/"
15 | },
16 | {
17 | path: "/404",
18 | name: "notFound",
19 | component: () => import("@/components/notFound")
20 | },
21 | {
22 | path: "/skill",
23 | name: "skill",
24 | meta: {
25 | title: "学习",
26 | icon: require("@/assets/image/铅笔.png")
27 | },
28 | component: () => import("@/views/Skill")
29 | },
30 | {
31 | path: "/zone",
32 | name: "zone",
33 | meta: {
34 | title: "Zone",
35 | icon: require("@/assets/image/星星.png")
36 | },
37 | component: () => import("@/views/Zone"),
38 | children: [
39 | {
40 | path: "/",
41 | component: () => import("@/views/Zone/Acu")
42 | },
43 | {
44 | path: "me",
45 | component: () => import("@/views/Zone/Me")
46 | }
47 | ]
48 | },
49 | {
50 | path: "/article",
51 | name: "article",
52 | meta: {
53 | title: "笔记",
54 | icon: require("@/assets/image/书.png")
55 | },
56 | component: () => import("@/views/Article"),
57 | children: [
58 | {
59 | path: "/",
60 | component: () => import("@/views/Article/List")
61 | },
62 | {
63 | path: ":id",
64 | component: () => import("@/views/Article/content/index")
65 | }
66 | ]
67 | },
68 | {
69 | path: "component",
70 | name: "component",
71 | meta: {
72 | title: "暂无",
73 | icon: require("@/assets/image/蜡笔.png")
74 | }
75 | // component: () => import("@/views/Article")
76 | }
77 | ];
78 |
--------------------------------------------------------------------------------
/src/store/actions.js:
--------------------------------------------------------------------------------
1 | import { getIp } from "@/api/common";
2 | import { getUserInfo } from "@/api/account";
3 | const actions = {
4 | async getIp({ commit }) {
5 | const { data } = await getIp();
6 | commit("saveIp", data);
7 | },
8 | async getUser({ commit }) {
9 | const {
10 | data: { info }
11 | } = await getUserInfo();
12 | commit("saveUser", info);
13 | }
14 | };
15 | export default actions;
16 |
--------------------------------------------------------------------------------
/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import Vuex from "vuex";
3 | import state from "./state";
4 | import mutations from "./mutations";
5 | import actions from "./actions";
6 | Vue.use(Vuex);
7 |
8 | export default new Vuex.Store({
9 | state,
10 | mutations,
11 | actions
12 | });
13 |
--------------------------------------------------------------------------------
/src/store/mutation-types.js:
--------------------------------------------------------------------------------
1 | export const CHANGE_MENU = "CHANGE_MENU";
2 |
--------------------------------------------------------------------------------
/src/store/mutations.js:
--------------------------------------------------------------------------------
1 | import * as types from "./mutation-types";
2 | const mutations = {
3 | [types.CHANGE_MENU](state) {
4 | state.menuShow = !state.menuShow;
5 | },
6 | saveSubjects(state, data) {
7 | state.subjectList = data;
8 | },
9 | saveIp(state, data) {
10 | state.count = data.count;
11 | state.isNew = data.isNew;
12 | state.ip = data;
13 | },
14 | saveUser(state, data) {
15 | state.user = data;
16 | },
17 | changeNavShow(state, data) {
18 | state.navShow = data;
19 | }
20 | };
21 |
22 | export default mutations;
23 |
--------------------------------------------------------------------------------
/src/store/state.js:
--------------------------------------------------------------------------------
1 | const state = {
2 | menuShow: false,
3 | subjectList: [],
4 | count: 0,
5 | isNew: false,
6 | navShow: true,
7 | ip: {
8 | city: "厦门",
9 | region: "福建"
10 | },
11 | user: {
12 | address: "",
13 | avatar: "",
14 | nick_name: "",
15 | remark: "",
16 | job: ""
17 | }
18 | };
19 |
20 | export default state;
21 |
--------------------------------------------------------------------------------
/src/utils/code.js:
--------------------------------------------------------------------------------
1 | export const SUCCESS = 0;
2 | export const ERROR = 1;
3 |
--------------------------------------------------------------------------------
/src/utils/fastClick.js:
--------------------------------------------------------------------------------
1 | import FastClick from "fastclick"; //vue框架开发H5正确运用fastclick
2 |
3 | // if ("addEventListener" in document) {
4 | // document.addEventListener(
5 | // "DOMContentLoaded",
6 | // function() {
7 | // FastClick.attach(document.body);
8 | // },
9 | // false
10 | // );
11 | // }
12 | FastClick.attach(document.body);
13 |
--------------------------------------------------------------------------------
/src/utils/index.js:
--------------------------------------------------------------------------------
1 | export const fmtDate = function (obj) {
2 | var date = new Date(obj);
3 | var y = 1900 + date.getYear();
4 | var m = "0" + (date.getMonth() + 1);
5 | var d = "0" + date.getDate();
6 | return (
7 | y +
8 | "-" +
9 | m.substring(m.length - 2, m.length) +
10 | "-" +
11 | d.substring(d.length - 2, d.length)
12 | );
13 | };
14 |
15 |
16 | function smoothScroll() {
17 | const currentScroll =
18 | document.documentElement.scrollTop || document.body.scrollTop;
19 | if (currentScroll > 0) {
20 | window.requestAnimationFrame(smoothScroll);
21 | window.scrollTo(0, currentScroll - currentScroll / 5);
22 | }
23 | }
24 | export const goScrollTop = smoothScroll
--------------------------------------------------------------------------------
/src/utils/jsonp.js:
--------------------------------------------------------------------------------
1 | import orginJSONP from "jsonp";
2 | import qs from "qs";
3 | export default function jsonp(url, data, option) {
4 | url = `${url}?${qs.stringify(data)}`;
5 | return new Promise((resolve, reject) => {
6 | orginJSONP(url, option, (err, data) => {
7 | if (!err) {
8 | resolve(data);
9 | } else {
10 | reject(err);
11 | }
12 | });
13 | });
14 | }
15 |
--------------------------------------------------------------------------------
/src/utils/request.js:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 |
3 | import {
4 | Notify
5 | } from "vant";
6 | import router from "../router";
7 | import {
8 | ERROR,
9 | SUCCESS
10 | } from "@/utils/code";
11 | axios.defaults.timeout = 10000;
12 | // const baseURL =
13 | // process.env.NODE_ENV === "development"
14 | // ? "/api"
15 | // : "http://www.zhoucanyu.cn/api";
16 | axios.defaults.baseURL = "/api";
17 | axios.defaults.headers.post["Content-Type"] =
18 | "application/x-www-form-urlencoded";
19 |
20 | axios.interceptors.request.use(
21 | function (config) {
22 | // 在发送请求之前做些什么
23 | //config.headers['X-Token'] = getToken() // 让每个请求携带token--['X-Token']为自定义key 请根据实际情况自行修改
24 | return config;
25 | },
26 | function (error) {
27 | return Promise.reject(error);
28 | }
29 | );
30 | axios.interceptors.response.use(
31 | function (response) {
32 | if (!(response.status >= 200 && response.status < 300)) {
33 | return response;
34 | }
35 | if (response.data.code !== SUCCESS) {
36 | window.vue.$loading.hide();
37 | Notify("服务器错误");
38 | throw "服务器错误";
39 | }
40 | return response.data;
41 | },
42 | function (error) {
43 | return Promise.reject(error);
44 | }
45 | );
46 |
47 | export default axios;
--------------------------------------------------------------------------------
/src/utils/touchMove.js:
--------------------------------------------------------------------------------
1 | function handler(event) {
2 | event.preventDefault();
3 | }
4 | // window.onload = function() {
5 | // document.body.addEventListener("touchmove", handler, false);
6 | // };
7 | export default handler;
8 |
--------------------------------------------------------------------------------
/src/views/Article/List.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
10 |
11 |
12 |
52 |
70 |
71 |
--------------------------------------------------------------------------------
/src/views/Article/body/DesignPattern.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{title}}
4 |
一、构造器模式
5 |

6 |
二、原型模式
7 |

8 |
三、建造者模式
9 |

10 |
四、工厂模式
11 |

12 |
13 |
14 |
23 |
44 |
--------------------------------------------------------------------------------
/src/views/Article/body/QuestionsCSS.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{title}}
4 |
1.CSS的盒模型,绝对定位和相对定位
5 |

6 |
2. 清除浮动
7 |

8 |
3.如何保持浮层水平垂直居中
9 |

10 |
4.样式的层级关系,选择器优先级,样式冲突,以及抽离样式模块
11 |

12 |
5.px和em和rem的区别,CSS中link 和@import的区别是?
13 |

14 |
15 |
16 |
25 |
46 |
--------------------------------------------------------------------------------
/src/views/Article/body/QuesttionsJS.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{title}}
4 |
1.JavaScript 里有哪些数据类型,解释清楚 null 和 undefined,解释清楚原始数据类型和引用数据类型。比如讲一下 1 和 Number(1)的区别
5 |

6 |
2. prototype是什么东西,原型链的理解,什么时候用prototype
7 |

8 |

9 |
16 |
17 |
18 |
27 |
48 |
--------------------------------------------------------------------------------
/src/views/Article/body/vertualDom.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{body.title}}
4 |
5 |
6 | 写网页时,我们会经常使用JS来操作一些DOM元素来完成我们的业务需求,
7 | 但是其实dom是很慢的,而且操作DOM的性能损耗非常的巨大,所以我们使用JS构造
8 | 一个对象(虚拟DOM)让我们要把DOM的操作全部反应在这个JS对象身上,最终再把这
9 | 个JS对象映射到真是DOM中交给浏览器渲染。
10 |
11 |

12 |

13 |

14 |

15 |

16 |
17 |
18 |
40 |
70 |
--------------------------------------------------------------------------------
/src/views/Article/content/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{title}}
4 |
5 |
7 | {{item.title}}
8 |
9 |
10 |
11 | {{updateTime|fmtDate}}
12 |
13 |
19 |
20 |
21 |
63 |
92 |
--------------------------------------------------------------------------------
/src/views/Article/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
27 |
28 |
56 |
--------------------------------------------------------------------------------
/src/views/Home/Card/Calendar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{weekday}}
8 |
9 |
{{date}}
10 |
11 |
12 |
13 |
53 |
100 |
--------------------------------------------------------------------------------
/src/views/Home/Card/MenuIcon.vue:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
38 |
68 |
--------------------------------------------------------------------------------
/src/views/Home/Card/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 | {{city}} {{wether.tem1}} {{wether.wea}}
8 | {{wether.air_tips}}
10 |
11 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
46 |
81 |
--------------------------------------------------------------------------------
/src/views/Home/index.vue:
--------------------------------------------------------------------------------
1 |
2 | {}">
4 |
20 |
21 |
22 |
23 |
24 |
25 |
31 |
48 |
--------------------------------------------------------------------------------
/src/views/Menu/Me.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
10 |
{{user.nick_name}}
11 |
{{user.address}}
12 |
13 |
14 |
15 |
30 |
31 |
51 |
--------------------------------------------------------------------------------
/src/views/Menu/Nav.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
{{item.meta.title}}
11 |
![]()
12 |
13 |
14 |
15 |
16 |
17 |
38 |
39 |
69 |
--------------------------------------------------------------------------------
/src/views/Menu/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
19 |
20 |
29 |
--------------------------------------------------------------------------------
/src/views/Skill/index.vue:
--------------------------------------------------------------------------------
1 |
2 | {}">
4 |
5 |
7 |
8 |
12 |
14 |
18 | {{props.item.title}}
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
58 |
59 |
102 |
--------------------------------------------------------------------------------
/src/views/Zone/Acu.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
12 |
13 |
14 |
15 |
60 |
61 |
77 |
--------------------------------------------------------------------------------
/src/views/Zone/Me.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
10 |
11 |
12 |
48 |
49 |
57 |
--------------------------------------------------------------------------------
/src/views/Zone/Tabar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ACU
6 |
7 |
8 |
9 | Me
10 |
11 |
12 |
13 |
14 |
15 |
39 |
53 |
--------------------------------------------------------------------------------
/src/views/Zone/TreeMenu.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
9 |
10 | -
11 | +
12 |
13 |
14 | {{item.title}}
15 |
16 |
17 |
18 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
61 |
85 |
--------------------------------------------------------------------------------
/src/views/Zone/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
56 |
64 |
--------------------------------------------------------------------------------
/study/Questions/index.css:
--------------------------------------------------------------------------------
1 | /* 1.CSS的盒模型,绝对定位和相对定位 */
2 | box-sizing属性可以为三个值之一.
3 | content-box[default]: border和padding不计算入width之内
4 | border-box : padding计算入width内
5 | padding-box: border和padding计算入width之内,其实就是怪异模式了
6 |
7 | 绝对定位相对定位 都是相对于父级元素所做的位移动,只不过绝对定位会
8 | 脱离文档流
9 |
10 | 1.利用flexbox布局
11 | 2.利用绝对定位与transform
12 | 3.利用定位与margin:auto
13 | 4.margin-left:0 margin-left:0
14 |
15 | 1.样式的层级关系:公有样式,私有样式
16 | 2.选择器优先级:(!important>)id选择器>
17 | class选择器(属性选择器/伪类选择器)>标签选择器(伪元素选择器)
18 | 3.样式冲突:如果同个元素有两个或以上冲突的CSS规则
19 |
20 | 1.px:浏览器像素单位
21 | 2.em:继承父级元素的字体大小
22 | 3.rem:相对HTML根节点
23 | 4.:link加载优先@import,@import可以同时加载其他CSS
--------------------------------------------------------------------------------
/study/Questions/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Document
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
52 |
53 |
--------------------------------------------------------------------------------
/study/Questions/二分查找.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 二分查找
3 | * @param {*} arr
4 | * @param {*} item
5 | * @param {*} start
6 | * @param {*} end
7 | */
8 |
9 | function findIndex(arr, item, start = 0, end = arr.length - 1) {
10 | if (start >= end) {
11 | return -1;
12 | }
13 | const midd = parseInt((start + end) / 2);
14 | if (arr[midd] === item) {
15 | return midd;
16 | }
17 | if (item < arr[midd]) {
18 | return findIndex(arr, item, start, midd - 1);
19 | } else {
20 | return findIndex(arr, item, midd + 1, end);
21 | }
22 | }
23 | const result = findIndex([1, 2, 3, 4, 5], 3);
24 |
25 | /**
26 | * 快排
27 | */
28 | function qucikSort(_arr) {
29 | if (_arr.length < 1) return _arr;
30 | // const midd = parseInt(arr.length / 2);
31 | const [base, ...arr] = _arr;
32 | const left = [];
33 | const right = [];
34 | for (const item of arr) {
35 | if (item < base) left.push(item);
36 | else right.push(item);
37 | }
38 | return [...qucikSort(left), base, ...qucikSort(right)];
39 | }
40 | const arr = qucikSort([3, 9, 5, 2, 4, -1]);
41 | console.log(arr);
42 | /**
43 | * 冒泡
44 | */
45 | function bubbleSort(arr) {
46 | for (let i = 0; i < arr.length; i++) {
47 | for (let j = 0; j < arr.length - 1 - i; j++) {
48 | if (arr[j] > arr[j + 1]) {
49 | [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
50 | }
51 | }
52 | }
53 | return arr;
54 | }
55 | const arr2 = bubbleSort([3, 9, 5, 2, 4, -1]);
56 | console.log(arr2);
57 |
--------------------------------------------------------------------------------
/study/Questions/原型.js:
--------------------------------------------------------------------------------
1 | let _undefined;
2 | console.log(_undefined); //undefined
3 | const num = 1;
4 | console.log(num); //1
5 | const str = "helloworld";
6 | console.log(str); //"helloworld"
7 | const bool = false || true;
8 | console.log(bool); //true
9 | // 以上为基础类型 原始数据类型
10 | const arr = [];
11 | console.log(arr); //[]
12 | const obj = { a: 1 };
13 | console.log(obj); //{ a: 1 };
14 | function name(params) {
15 | return params;
16 | }
17 | console.log(name);
18 | // 以上为引用类型
19 |
20 | console.log(null === false); //false
21 | console.log(null === true); //false
22 | console.log(undefined === false); //false
23 | console.log(undefined === true); //false
24 | console.log(undefined === null); //false
25 | console.log(undefined === undefined); //true
26 | console.log(null === null); //true
27 | /**
28 | * null表示空指针对象 且typeof(null) == 'object'
29 | * undefined 表示声明未定义
30 | */
31 | const _null = null;
32 | let __undefined;
33 | if (_null || __undefined) {
34 | console.log("null 和 undefined 在逻辑运算符中均为false");
35 | }
36 | console.log("-----------------");
37 | console.log(1 === Number(1));
38 | var a = Number(1); // 1
39 | var b = new Number(1); // Number {[[PrimitiveValue]]: 1}
40 | var c = 1;
41 | console.log(typeof a); // number
42 | console.log(typeof b); // object 由构造函数构建的是一个Object
43 | console.log(typeof c); // number
44 | console.log(a === b); // false
45 |
46 | /**
47 | * 每个函数都有一个prototype属性,
48 | * 这个属性是指向一个对象的引用,
49 | * 这个对象称为原型对象,原型对象
50 | * 包含函数实例共享的方法和属性,
51 | * 也就是说将函数用作构造函数调用
52 | * (使用new操作符调用)的时候,
53 | * 新创建的对象会从原型对象上继承属
54 | * 性和方法。不像传统的面向对象语言,
55 | * Javascript的继承机制基于原型,而
56 | * 不是Class类。
57 | */
58 | function Bar() {
59 | let a = 1; // 私有属性
60 | // 私有方法
61 | const fn = function() {
62 | console.log(a);
63 | };
64 | }
65 | const bar = new Bar();
66 | console.log(bar.a); //undefined
67 | console.log(bar.fn); //undefined
68 | /**
69 | * 把私有变量变成静态类型变量
70 | * 但是从构造函数中实例出来的
71 | * 对象还是没办法拿到 属性和方法
72 | */
73 | function Bar2() {
74 | Bar2.a = 1; // 私有属性
75 | // 私有方法
76 | Bar2.fn = function() {
77 | console.log(a);
78 | };
79 | }
80 |
81 | Bar2.speak();
82 | console.log(Bar2.a); //1
83 | console.log(Bar2.fn); //func
84 | const bar2 = new Bar2();
85 | console.log(bar2.a); //undefined
86 | console.log(bar2.fn); //undefined
87 | /**
88 | * 接下来实例出2个对象
89 | * 只对一个 实例进行属性的更改
90 | * 发现另外一个实例的属性没有被改变
91 | */
92 | function Bar3() {
93 | this.a = 1;
94 | this.fn = function() {};
95 | }
96 | const bar3_1 = new Bar3();
97 | const bar3_2 = new Bar3();
98 | bar3_2.a = 100;
99 | bar3_2.fn = [];
100 | console.log(bar3_1.a); //100
101 | console.log(bar3_1.fn); //[]
102 | console.log(bar3_2.a); //1
103 | console.log(bar3_2.fn); //func
104 | /**
105 | * 换一种写法
106 | * 把构造函数的属性
107 | * 挂到ProtoType中
108 | * 结果一致
109 | * prototype的作用 :
110 | * 我们在创建对象之后来改变对象的属性和方法
111 | * 所有 实例共享prototype上的所有属性
112 | * 并且每个实例改变自身属性的同时,与其他实例互不影响
113 | * 当我们引用别人的 类时 有时候会需要添加一些属性
114 | * 就可以直接使用prototype方法 为每个通过类实例出来的
115 | * 对象添加属性和方法
116 | */
117 | function Bar4() {}
118 | Bar4.prototype.a = 1;
119 | Bar4.prototype.fn = function() {};
120 | console.log(Bar4.prototype);
121 | const bar4_1 = new Bar4();
122 | const bar4_2 = new Bar4();
123 | bar4_2.a = 100;
124 | bar4_2.fn = [];
125 | console.log(bar4_1.a); //1
126 | console.log(bar4_1.fn); //func
127 | console.log(bar4_2.a); //100
128 | console.log(bar4_2.fn); //[]
129 |
--------------------------------------------------------------------------------
/study/Questions/工厂模式.js:
--------------------------------------------------------------------------------
1 | function Student() {}
2 | function Teacher() {}
3 |
4 | function studentFactory() {
5 | return new Student();
6 | }
7 |
8 | function teacherFactory() {
9 | return new Teacher();
10 | }
11 | function school(type) {
12 | let factory = null;
13 | switch (type) {
14 | case "student":
15 | factory = studentFactory;
16 | break;
17 | case "teacher":
18 | factory = teacherFactory;
19 | break;
20 | default:
21 | throw "没有这个工厂";
22 | }
23 | return factory;
24 | }
25 | var _student = school("student")();
26 | var _teacher = school("teacher")();
27 | console.log(_student);
28 | console.log(_teacher);
29 |
--------------------------------------------------------------------------------
/study/Questions/设计模式之原型模式.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 1构造器模式
3 | */
4 | function Student1ES5(name, sex, age) {
5 | this.math = 100;
6 | this.english = 80;
7 | this.name = name;
8 | this.sex = sex;
9 | this.age = age;
10 | this.sumSubject = function() {
11 | return this.math + this.english;
12 | };
13 | }
14 | class Student1ES6 {
15 | constructor(name, sex, age) {
16 | this.name = name;
17 | this.sex = sex;
18 | this.age = age;
19 | this.math = 100;
20 | this.english = 80;
21 | }
22 | sumSubject() {
23 | return this.math + this.english;
24 | }
25 | }
26 | const cc1 = new Student1ES5("灿灿", "男", 18);
27 | console.log(cc1);
28 | const cc2 = new Student1ES6("灿灿", "男", 18);
29 | console.log(cc2);
30 | /**
31 | * 2 原型模式
32 | * es6的没变化和构造器一样
33 | */
34 | function Student2ES5(name, sex, age) {
35 | this.math = 100;
36 | this.english = 80;
37 | this.name = name;
38 | this.sex = sex;
39 | this.age = age;
40 | }
41 | Student2ES5.prototype.sumSubject = function() {
42 | return this.math + this.english;
43 | };
44 | class Student2ES6 {
45 | constructor(name, sex, age) {
46 | this.name = name;
47 | this.sex = sex;
48 | this.age = age;
49 | this.math = 100;
50 | this.english = 80;
51 | }
52 | sumSubject() {
53 | return this.math + this.english;
54 | }
55 | }
56 | console.log(Student2ES6);
57 |
--------------------------------------------------------------------------------
/study/Questions/设计模式之构建者模式.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 构建者模式
3 | * es5
4 | */
5 | function Student() {}
6 |
7 | function BuildStudent() {
8 | this.student = new Student();
9 | }
10 | BuildStudent.prototype.setName = function(name) {
11 | this.student.name = name;
12 | };
13 | BuildStudent.prototype.setSex = function(sex) {
14 | if (sex != "男" && sex != "女") {
15 | throw "性别错误";
16 | }
17 | this.student.sex = sex;
18 | };
19 | BuildStudent.prototype.setHairLength = function(length) {
20 | if (
21 | (this.student.sex === "男" && length > 1) ||
22 | (this.student.sex === "女" && length > 25)
23 | ) {
24 | throw "头发太长";
25 | }
26 | this.student.length = length;
27 | };
28 | BuildStudent.prototype.build = function() {
29 | return this.student;
30 | };
31 | var builder = new BuildStudent();
32 | try {
33 | builder.setName("灿灿");
34 | builder.setSex("男");
35 | builder.setHairLength(1);
36 | var student = builder.build();
37 | } catch (err) {
38 | throw err;
39 | }
40 | console.log(student);
41 |
--------------------------------------------------------------------------------
/study/diffDom/diffDom.js:
--------------------------------------------------------------------------------
1 | class Diff {
2 | /**
3 | * 比较2个虚拟DOM
4 | * @param { Element } oldTree 旧虚拟DOM
5 | * @param { Element } newTree 新虚拟DOM
6 | */
7 | constructor(oldTree, newTree) {
8 | const patches = {}; //补丁集合
9 | this.index = 0;
10 | this.walk(oldTree, newTree, this.index, patches);
11 | this.patches = patches; //补丁集合
12 | }
13 | get ATTR() {
14 | return "ATTR";
15 | }
16 | get TEXT() {
17 | return "TEXT";
18 | }
19 | diffChildren(oldChildren, newChildren, patches) {
20 | oldChildren.forEach((child, idx) => {
21 | this.index += 1;
22 | this.walk(child, newChildren[idx], this.index, patches);
23 | });
24 | }
25 | /**
26 | *
27 | * @param { Element } oldNode 旧虚拟DOM
28 | * @param { Element } newNode 新虚拟DOM
29 | * @param { int } index 索引
30 | * @param { object } patches 补丁对象
31 | */
32 | walk(oldNode, newNode, index, patches) {
33 | const curPatches = [];
34 | // 判断2个节点是否为文本类型
35 | if (this.isString(oldNode) && this.isString(newNode)) {
36 | // 判断2个文本类型的文本是否一样
37 | if (oldNode !== newNode) {
38 | curPatches.push({ type: this.TEXT, text: newNode });
39 | patches[index] = curPatches;
40 | }
41 | return;
42 | }
43 | if (oldNode.type === newNode.type) {
44 | const attrs = this.diffAttr(oldNode.props, newNode.props);
45 | // 如果attr有值 新旧节点有改变 把改变的属性 添加到补丁数组中
46 | if (Object.keys(attrs).length > 0) {
47 | curPatches.push({ type: this.ATTR, attrs });
48 | }
49 | this.diffChildren(oldNode.children, newNode.children, patches);
50 | // 将元素和补丁对应起来放入大补丁包中
51 | curPatches.length && (patches[index] = curPatches);
52 | }
53 | }
54 | /**
55 | * 比较属性
56 | * @param { Element } oldNode 旧虚拟DOM
57 | * @param { Element } newNode 新虚拟DOM
58 | * @return { object } patch 补丁对象
59 | */
60 | diffAttr(oldAttrs, newAttrs) {
61 | const patch = {};
62 | for (const key in oldAttrs) {
63 | // 判断 oldAttrs 的属性是否有被改变
64 | // 若改变 则给patch记录这个属性
65 | oldAttrs[key] !== newAttrs[key] && (patch[key] = newAttrs[key]);
66 | }
67 | for (const key in newAttrs) {
68 | // 判断 newAttrs 的属性是否有添加
69 | // 若改变 则给patch记录这个属性
70 | !oldAttrs.hasOwnProperty(key) && (patch[key] = newAttrs[key]);
71 | }
72 | return patch;
73 | }
74 |
75 | isString(node) {
76 | return Object.prototype.toString.call(node) === "[object String]";
77 | }
78 | }
79 |
80 | console.log(Diff);
81 |
--------------------------------------------------------------------------------
/study/diffDom/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/study/diffDom/vertualDom.js:
--------------------------------------------------------------------------------
1 | class Element {
2 | /**
3 | * @param { string } type 标签类型
4 | * @param { object } props dom 属性
5 | * @param { array } children 子元素
6 | */
7 | constructor(type, props, children) {
8 | this.type = type;
9 | this.props = props;
10 | this.children = children;
11 | }
12 | // 创建虚拟DOM
13 | static createElement(type, props, children) {
14 | return new this(type, props, children);
15 | }
16 | /**
17 | * 给虚拟DOM 创建属性
18 | * @param { DomElement } node
19 | * @param { string } key
20 | * @param { string } val
21 | */
22 | setAttr(node, key, val) {
23 | switch (key) {
24 | case "value": //node 是一个Input 或者 Textarea
25 | if (
26 | node.tagName.toUpperCase() === "INPUT" ||
27 | node.tagName.toUpperCase() === "TEXTAREA"
28 | ) {
29 | node.value = val;
30 | } else {
31 | node.setAttribute(key, val);
32 | }
33 | break;
34 | case "style":
35 | node.style.cssText = val;
36 | break;
37 | default:
38 | node.setAttribute(key, val);
39 | break;
40 | }
41 | }
42 | // 将虚拟DOM 渲染为真是DOM
43 | /**
44 | *
45 | * @param { Element } vNode Element 的实例 虚拟DOM
46 | * @return { DomElement } el 真实DOM
47 | */
48 | render(vNode = this) {
49 | let el = document.createElement(vNode.type);
50 | for (const key in vNode.props) {
51 | this.setAttr(el, key, vNode.props[key]);
52 | }
53 | vNode.children.forEach(child => {
54 | child =
55 | child instanceof Element
56 | ? this.render(child)
57 | : document.createTextNode(child);
58 | el.appendChild(child);
59 | });
60 | return el;
61 | }
62 | }
63 | /**
64 | * dom diff
65 | * 1. js对象 模拟 vertualDom
66 | * 2. 把vertualDom 转成 真是DOM
67 | * 3. 如果有时间发生修改了vertualDom比较2个vertualDom的
68 | * 差异得到差异对象
69 | * 4. 把差异对象应用到真是DOM树上
70 | */
71 | console.log(Element);
72 |
--------------------------------------------------------------------------------
/test.js:
--------------------------------------------------------------------------------
1 | function flatten(arr) {
2 | return [].concat(...arr.map(_ => (Array.isArray(_) ? flatten(_) : _)));
3 | }
4 | class Group {
5 | constructor(list = []) {
6 | this.list = list;
7 | }
8 | // 将数据过滤整理 摊平
9 | get arr() {
10 | const arr = this.list.map((_, index) => {
11 | return _.boxList
12 | .filter(_ => _.checked === true)
13 | .map(_ => ({
14 | value: _.value,
15 | key: index
16 | }));
17 | });
18 | return flatten(arr);
19 | }
20 | get group() {
21 | const arr = this.list.map((_, index) => ({ id: index }));
22 | return arr;
23 | }
24 |
25 | get groupBy() {
26 | const groups = this.groups;
27 | const groupBy = this.arr.reduce((groups, item) => {
28 | groups[item.key] = [...(groups[item.key] || []), item];
29 | return groups;
30 | }, {});
31 | return groupBy;
32 | }
33 | get key() {
34 | if (!this.group.length) return null;
35 | return this.group[0].id;
36 | }
37 |
38 | render(key = this.key, index = 0, result = []) {
39 | if (key === null) return [];
40 | const bar = [];
41 | const data = this.arr.find(_ => _.key === key);
42 | const data2 = this.arr.filter(_ => _.key !== key);
43 | // console.log(data2);
44 | return [data, ...data2];
45 | }
46 | get num() {
47 | const arr = [];
48 | for (let i in this.groupBy) {
49 | arr.push(this.groupBy[i].length);
50 | }
51 | let num = 1;
52 | for (const item of arr) {
53 | num = num * item;
54 | }
55 | return num;
56 | }
57 | }
58 |
59 | const list = [
60 | {
61 | name: "规格名字1",
62 | val: "",
63 | boxList: [
64 | { value: "Apple", checked: true },
65 | { value: "Pear", checked: true }
66 | ]
67 | },
68 | {
69 | name: "规格名字2",
70 | boxList: [
71 | { value: "Orange", checked: true },
72 | { value: "Grape", checked: true }
73 | ],
74 | val: ""
75 | },
76 | {
77 | name: "规格名字3",
78 | boxList: [
79 | { value: "Banner", checked: true },
80 | { value: "Strawberry", checked: true }
81 | ],
82 | val: ""
83 | }
84 | ];
85 |
86 | //const result = new Group(list);
87 | // console.log(result.arr);
88 | // console.log(result.groupBy);
89 | // console.log(result.num);
90 | // const foo = result.render();
91 | // console.log(foo);
92 |
93 | const a = ["apple", "orange", "banner"];
94 | const b = ["apple", "orange", "Strawberry"];
95 | const c = ["apple", "Grape", "banner"];
96 | const d = ["apple", "Grape", "Strawberry"];
97 | const e = ["Pear", "orange", "banner"];
98 | const f = ["Pear", "orange", "Strawberry"];
99 | const g = ["Pear", "Grape", "banner"];
100 | const h = ["Pear", "Grape", "Strawberry"];
101 |
102 | const arr = [["Apple", "Pear"], ["Orange", "Grape"], ["Banner", "Apple"]];
103 |
104 | let results = [];
105 | let result = [];
106 |
107 | function doExchange(arr, index) {
108 | for (var i = 0; i < arr[index].length; i++) {
109 | result[index] = arr[index][i];
110 | if (index != arr.length - 1) {
111 | doExchange(arr, index + 1);
112 | } else {
113 | results.push(result.join(","));
114 | }
115 | }
116 | }
117 | console.log(results);
118 |
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | // vue.config.js
2 |
3 | const path = require("path");
4 | const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
5 | // const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
6 |
7 | function resolve(dir) {
8 | return path.join(__dirname, dir);
9 | }
10 |
11 | module.exports = {
12 | runtimeCompiler: true, //是否使用包含运行时编译器的 Vue 构建版本
13 | baseUrl: process.env.NODE_ENV === "production" ? "/" : "/",
14 | // baseUrl: process.env.NODE_ENV === "production" ? "/" : "/",
15 | productionSourceMap: false, //不在production环境使用SourceMap
16 | css: {
17 | loaderOptions: {
18 | less: {
19 | javascriptEnabled: true
20 | }
21 | }
22 | },
23 | lintOnSave: process.env.NODE_ENV !== "production",
24 | configureWebpack: config => {
25 | //入口文件
26 | config.entry.app = ["babel-polyfill", "./src/main.js"];
27 | //删除console插件
28 | const plugins = [
29 | new UglifyJsPlugin({
30 | uglifyOptions: {
31 | compress: {
32 | warnings: false,
33 | drop_console: true,
34 | drop_debugger: true
35 | },
36 | output: {
37 | // 去掉注释内容
38 | comments: true
39 | }
40 | },
41 | sourceMap: false,
42 | parallel: true
43 | })
44 | ];
45 | config.externals = {
46 | vue: "Vue",
47 | "vue-router": "VueRouter",
48 | axios: "axios",
49 | vuex: "Vuex",
50 | Vant: "vant"
51 | };
52 | config.performance = {
53 | maxAssetSize: 100000000,
54 | maxEntrypointSize: 400000000
55 | };
56 |
57 | if (process.env.NODE_ENV == "production") {
58 | config.plugins = [...config.plugins, ...plugins];
59 | }
60 | },
61 | //允许对内部的 webpack 配置进行更细粒度的修改。
62 | chainWebpack: config => {
63 | //命名
64 | config.resolve.alias
65 | .set("SRC", resolve("src"))
66 | .set("ASSET", resolve("src/assets"))
67 | .set("VIEW", resolve("src/components/page"))
68 | .set("COMPONENT", resolve("src/components/common"))
69 | .set("UTIL", resolve("src/utils"))
70 | .set("SERVICE", resolve("src/services"));
71 |
72 | //打包文件带hash
73 | config.output.filename("[name].[hash].js").end();
74 |
75 | //为了补删除换行而加的配置
76 | config.module
77 | .rule("vue")
78 | .use("vue-loader")
79 | .loader("vue-loader")
80 | .tap(options => {
81 | // modify the options...
82 | options.compilerOptions.preserveWhitespace = true;
83 | return options;
84 | });
85 | },
86 | devServer: {
87 | //跨域
88 | port: 8010, // 端口号
89 | open: false, //配置自动启动浏览器
90 | // host: "localhost",
91 | proxy: {
92 | // 配置跨域处理 可以设置多个
93 | "/api": {
94 | //target: "http://localhost:7001",
95 | target: "http://119.29.165.40:8010",
96 | changeOrigin: true
97 | }
98 | }
99 | }
100 | };
101 |
--------------------------------------------------------------------------------