[TOC]
## 前言
本文主要总结了vue实际开发项目当中应该如何解决一些实际的开发问题,可能你认为很简单,但短时间内也许你并没解决思路的。
## 常见技术解答
### for循环中针对ui样式的特征性样式或者事件
- 针对ui有特定的数据字段进行判断(也叫数据模型方法)
这种书数据的要求比较高,且要求你能够找到比较好的对应关系,需要针对class进行特征性的组件渲染。当你需要改变时改变数据即可重新渲染达到改变样式的目的。
~~~
<li v-for="item of list" :key="item.id" :class="item.status?'color':''" @click="changeColor(item.id)">{{item.name}}</li>
return {
list:[
{id:1,status:true,name:1111},
{id:2,status:true,name:222}]
}
methods:{
changeColor(id){
this.list.map((item)=>{
if(item.id==id){
item.status=!item.status;
}
return item;
})
}
}
~~~
- 传入对应的参数以及事件源,可以进行相应的判断改变class
特点更加灵活,也可以根据需要传入你需要传入的item属性参数进行与class的匹配判断,不用改变接口返回的数据结构。
~~~
<li v-for="item of list" :key="item.id" @click="changeColor($event)">{{item.name}}</li>
return {
list:[
{id:1,name:1111},
{id:2,name:222}]
}
changeColor(e){
let el=e.target;
if(el.classList.contains("color")){
el.classList.remove("color")
}else{
el.classList.add("color")
}
}
~~~
### 计算属性方法的使用
问题描述:如果你的计算属性依赖于data的部分,而你的data对应的字段在data里没有申明,只是在请求接口时进行申明赋值,那么当接口请求时,虽然数据发生了变化,但是计算属性的值不会发生更新。
解决方案 :需要你在data里申明你计算属性依赖的字段,哪怕是空或者null
### 事件执行顺序问题
问题描述 :定义了输入框blur,再按钮点击事件问题,其中默认click的话,执行顺序是先执行blur再执行click.如果你需要场景在点击的时候不执行blur的事件
解决方案:
1 常规方案 :
需要吧点击事件变成@mousedown.prevent ,前者会让点击优于blur执行,后者会阻止blur执行
2 el-input并不生效,可以用计时器延迟执行
将失去焦点的事件计时器延迟执行,然后点击事件里清除定时器,也是可以只执行点击事件逻辑的
### 路由参数变化组件不更新
问题描述 :路由参数变化,但是组件没有对应的更新,主要是因为一般获取参数写在了created路由钩子函数中,路由参数变化的时候,这个生命周期不会重新执行。
解决方案1:watch监听router
~~~
watch: {
// 方法1
'$route' (to, from) { //监听路由是否变化
if(this.$route.params.articleId){// 判断条件1 判断传递值的变化
//获取文章数据
}
}
//方法2 判断页面路径
'$route'(to, from) {
if (to.path == "/page") { /// 判断条件2 监听路由名 监听你从什么路由跳转过来的
this.message = this.$route.query.msg
}
}
//方法 3 设置路径变化时的处理函数
'$route': {
handler: 'resetData',
immediate: true
}
}
~~~
解决方案2 :为了实现这样的效果可以给router-view添加一个不同的key,这样即使是公用组件,只要url变化了,就一定会重新创建这个组件。
```
<router-view :key="$route.fullpath"></router-view>
```
解决方案3 :如果组件被放在<keep-alive>中的话,可以把获取新数据的方法放在activated钩子,代替原来在created、mounted钩子中获取数据的任务
### 异步函数中使用this无法指向vue实例对象
问题描述 : 在定时器或者其他异步函数中使用传统的func导致this指向不到vue实例,主要原因是因为this指向的问题,详细的可以参考我的《神奇的this》这篇文章。
解决方案 :用箭头函数或者指定变量赋值为this(其他一些不能用箭头函数的地方自己也要注意)
### 定时器在组件销毁后还在执行
问题描述 :一些耗费性能的计时器或者动画在组件销毁之后还是执行的,导致性能变低。
解决方案 :在销毁组件的生命周期中销毁定时器或者一些动画的js
~~~
//组件销毁前执行的钩子函数,跟其他生命周期钩子函数的用法相同。
beforeDestroy(){
//我通常是把setInterval()定时器赋值给this实例,然后就可以像下面这么停止。
clearInterval(this.intervalId);
},
~~~
这里也给出第二种方案,通过$once这个事件侦听器器在定义完定时器之后的位置来清除定时器。以下是完整代码:
~~~
const timer = setInterval(() =>{
// 某些定时器操作
}, 500);
// 通过$once来监听定时器,在beforeDestroy钩子可以被清除。
this.$once('hook:beforeDestroy', () => {
clearInterval(timer);
})
~~~
类似于其他需要在当前页面使用,离开需要销毁的组件(例如一些第三方库的picker组件等等),都可以使用此方式来解决离开后以后在背后运行的问题。
如果不清楚$once、$on、$off的使用,这里送上官网的地址教程,在[程序化的事件侦听器](https://cn.vuejs.org/v2/guide/components-edge-cases.html#%E7%A8%8B%E5%BA%8F%E5%8C%96%E7%9A%84%E4%BA%8B%E4%BB%B6%E4%BE%A6%E5%90%AC%E5%99%A8)那里。
### 组件名与引入时大小写不一致导致报错
问题描述:
~~~
This can lead to unexpected behavior when compiling on a filesystem with other case-semantic.
Use equal casing. Compare these module identifiers:
~~~
解决方案 :需要严格对应组件的大小写,避免低级错误
### 动态添加的dom没有样式
问题描述:作为常识我们知道style中的样式都会追加scoped,这样针对模板dom中的样式就可以生效,但其生效后的最终样式并不是我们写的样式名,而是编码后的,所以我们在js中拼接上的dom结构样式并不会生效。
解决思路:
1 当添加的部分样式不会太多,而且是动态加载的,可以将其设置为非scopred的
2 将添加dom部分用的样式放到非scoped样式标签中
3 将添加的部分,如果有必要,可以另外写一个页面拆分的vue组件
拓展 :
项目中引入的其他ui框架的样式,如果你想覆盖修改,也是需要不加scoped的,如果你想整个项目覆盖,就可以在src/styles下定义customer-element.scss 这样的来重写覆盖样式。
### vue中直接修改对象数据,页面视图不更新
问题描述 :你的数据对象类型,没有在data中进行定义,就没有增加对其的监听绑定,当你直接去使用或者定义数据时,会导致这个数据的vm视图层不会及时更新.
解决方案:这时候需要你将其定义到data中就会增加对其的监听。
备注:与此同理,你需要增加监听的数据或者变化的数据如果需要数据变化时马上更新,都要定义到data一份。
### vue中直接修改数组数据,页面视图不更新
问题描述 :在常规理解中,视图与数据是双向绑定的,但是有时候修改data的数组或者对象值,视图不会更新 。
~~~
data() { // data数据
return {
arr: [1,2,3],
obj:{
a: 1,
b: 2
}
};
},
// 数据更新 数组视图不更新
this.arr[0] = 'OBKoro1';
this.arr.length = 1;
console.log(arr);// ['OBKoro1'];
// 数据更新 对象视图不更新
this.obj.c = 'OBKoro1';
delete this.obj.a;
console.log(obj); // {b:2,c:'OBKoro1'}
~~~
解决方案 :由于js的限制,Vue 不能检测以上数组的变动,以及对象的添加/删除,很多人会因为像上面这样操作,出现视图没有更新的问题。
1 this.$set(你要改变的数组/对象,你要改变的位置/key,你要改成什么value)
~~~
this.$set(this.arr, 0, "OBKoro1"); // 改变数组
this.$set(this.obj, "c", "OBKoro1"); // 改变对象
~~~
2 数组原生方法触发视图更新:
splice()、 push()、pop()、shift()、unshift()、sort()、reverse()
推荐使用splice方法会比较好自定义,因为slice可以在数组的任何位置进行删除/添加操作
3 替换数组
比方说:你想遍历这个数组/对象,对每个元素进行处理,然后触发视图更新。
~~~
// 文档中的栗子: filter遍历数组,返回一个新数组,用新数组替换旧数组
example1.items = example1.items.filter(function (item) {
return item.message.match(/Foo/)
})
~~~
- [codepen地址,可以进行问题重现](https://codepen.io/robinson90/pen/ZRWyYX)
### 需要无脑重复某内容
~~~
<div v-for="n in 5">
<span>这里会被渲染5次,渲染模板{{n}}</span>
</div>
~~~
### babel-plugin-transform-runtime使用
* 出现问题:这个插件可以兼容并转化大部分的es6语法,但是部分语法也是不能转化或者存在具体问题的。
1. 异步加载组件时,会产生 polyfill 代码冗余
2. 不支持对全局函数与实例方法的 polyfill。不支持全局函数(如:Promise、Set、Map),Set 跟 Map 这两种数据结构应该大家用的也不多,影响较小。但是 Promise 影响可能就比较大了。不支持实例方法(如:'abc'.include('b')、['1', '2', '3'].find((n) => n 等等),这个限制几乎废掉了大部分字符串和一半左右数组的新特性。
而两个问题的原因均归因于 babel-plugin-transform-runtime 采用了沙箱机制来编译我们的代码(即:不修改宿主环境的内置对象)。由于异步组件最终会被编译为一个单独的文件,所以即使多个组件中使用了同一个新特性(例如:Object.keys()),那么在每个编译后的文件中都会有一份该新特性的 polyfill 拷贝。如果项目较小可以考虑不使用异步加载,但是首屏的压力会比较大。
* 解决方案:一般情况下 babel-plugin-transform-runtime 能满足大部分的需求,当不满足需求时,推荐使用完整的 babel-polyfill。
* 首先,从项目中移除 babel-plugin-transform-runtime,卸载该依赖: `npm un babel-plugin-transform-runtime -D`,
* 接着修改 babel 配置文件
~~~
// .babelrc
{
//...
"plugins": [
// - "transform-runtime"
]
//...
}
~~~
* 然后,安装 babel-polyfill 依赖:
`npm i babel-polyfill -D`
* 最后,在入口文件中导入
~~~
// src/main.js
import 'babel-polyfill'
~~~
### ES6 import 引用问题
在 ES6 中,模块系统的导入与导出采用的是引用导出与导入(非简单数据类型),也就是说,如果在一个模块中定义了一个对象并导出,在其他模块中导入使用时,导入的其实是一个变量引用(指针),如果修改了对象中的属性,会影响到其他模块的使用。
通常情况下,系统体量不大时,我们可以使用 JSON.parse(JSON.stringify(str)) 简单粗暴地来生成一个全新的深度拷贝的 数据对象。不过当组件较多、数据对象复用程度较高时,很明显会产生性能问题,这时我们可以考虑使用 Immutable.js。
鉴于这个原因,进行复杂数据类型的导出时,需要注意多个组件导入同一个数据对象时修改数据后可能产生的问题。
此外,模块定义变量或函数时即便使用 let 而不是 const,在导入使用时都会变成只读,不能重新赋值,效果等同于用 const 声明。
### 动态懒加载组件
背景:在webpack的新特性中支持组件的懒加载,也就是说我们可以在加载到该路由的时候再把这部分脚本进行加载,同时这个在项目进行打包的时候,对应的文件也会被单独打包,对于首屏优化以及其他页面的资源加载优化都是非常好的。这也要求我们在每个页面组件使用组件的时候尽量按需引入,提升体验。
问题场景:那么我们需要解决的问题是:
0 webpack是静态解析路径的,直接传入变量并不可行
1 每次都写一串加载组件的代码很不方便,是否可以支持写成一个加载组件的方法
2 是否支持区分生产和开发环境,因为开发环境使用懒加载会导致热更新,导致更新变慢,所以开发环境使用全量默认加载,生产环境使用懒加载
解决方案如下 :
1 webpack的路径使用变量拼接,必须预先给出一个相对路径,然后把具体的组件路径在传入
2 用一个箭头函数,将需要传入的组件名或者相对路径传入
3 用process.env.NODE_ENV确定使用哪种加载方式
代码如下:
在原来的router/index.js中,定义一个加载组件的_import方法。
~~~
// router/index.js
const _import = require('./_import_' + process.env.NODE_ENV)
//使用时
{
path: '/',
name: 'HelloWorld',
component: _import('HelloWorld')
},
// router/_import_development.js
module.exports = file => require('@/views/' + file + '.vue').default // vue-loader at least v13.0.0+
// router/_import_production.js 如果你加载的vue不是这个路径 请自定义哦
module.exports = file => () => import('@/views/' + file + '.vue')
~~~
**注意事项:**
1 如果配置完之后,可能会有部分样式文件或者图片引入的src路径之外的,比如说static,报错找不到对应的文件,这时候需要改为根路径static的路径就可以解决这个报错?你需要装的模块:sass-loader,node-sass,stylus,stylus-loader,style-loader,css-loader,url-loader即可。具体的包需要进一步确定。
2 在具体的页面中,如果你想懒加载组件,也是如此的写法
```
import vOther from '@/components/other'
//修改后
const vOther = () => import('@/components/other')
```
### vue中的data必须为函数
**场景** :vue入门的人可能在页面单独引入vue的时候,直接使用data为对象类型的,并没有问题,但是在spa应用中,如果组件中的data为对象类型就会报错。
**解决方案** :data换为函数,返回对象类型的键值对。
拓展 :你可能知道要这样做,这里稍微科普下原因,主要是因为根组件只会用一次,所以可以用对象,而子组件可能在一个应用中被多次使用,为了避免多个组件使用同一数据互相影响,所以讲data约定为了返回函数类型,返回需要的对象,以此保证子组件在数据渲染的时候不会互相影响。
### 有父子标签关系的自定义组件渲染失败
**场景** :在自定义组件的时候,很多时候需要将ul下的li标签,table下的tr\td标签进行封装为自定义组件,但直接使用自定义组件会导致其最终生成的位置不是我们想要的。截图如下:
~~~
Vue.component("row",{
template:'<tr><td>{{content}}</td></tr>',
data(){
return {
content:'this is a row'
}
},
})
~~~
![](https://box.kancloud.cn/5c44cd9258f16d1add4c41625b7cc6fd_494x314.png)
![](https://box.kancloud.cn/983d443988a8e4817a1cea1610c58d7e_600x322.png)
**解决方案** :原因是因为html会进行标签解析,tbody下的标签必须为tr,其他的同理。那么我们可以将其子标签设置为原来的标签类型,然后用is="selfComponent" 来解决这个问题。
`<tr is="row"></tr>`
- [vueComponents使用](https://codepen.io/robinson90/pen/GGjmyx)
拓展:
- 不要将渲染vue的容器元素定位到html或者body上,否则提示:` Do not mount Vue to <html> or <body> - mount to normal elements instead.`
- 确保有在vue新建实例的时候将el属性绑定到一个html模板的标签上
### ref使用
**场景** :虽然vue不建议直接操作dom,但是在复杂的场景中,我们需要进行dom的操作,这时候就可以借助ref实现。比如下面我们举一个简单的例子,通过ref获取dom节点,拿到其内容。
**解决方案** :
~~~
<div @click="handleClick" ref="hello">hello world
</div>
handleClick(){
console.log(this.$refs.hello)
}
~~~
- 拓展案例 :实现计数器加和
场景 :假设我们有两个计数器组件的实例,现在需要用ref的方案得到两个计数器的加和。
代码如下:
~~~
<counter ref="one" @change="handleChange"></counter>
<counter ref="two" @change="handleChange"></counter>
<span>{{total}}</span>
Vue.component("counter",{
template:"<div @click='change'>{{number}}</div>",
data(){
return {
number:0}
},
methods:{
change(){
this.number++;
this.$emit("change")
}
}
})
//app父组件方法
handleChange(){
this.total=this.$refs.one.number+this.$refs.two.number
},
~~~
- 拓展认知 :
this.$refs.name中如果是原生标签,拿到的是原生标签的节点,如果是组件,拿到的是组件的引用。
如果你用.name获取不到,可以尝试用【name】方式。
- [vueRefDemo使用](https://codepen.io/robinson90/pen/OERmra)
## 参考文档
- [vue项目实践中的一些问题](http://mp.weixin.qq.com/s/fgFOvWBC_P78hG154gyXYQ)
- 前端工程化
- 架构总纲
- 001
- 美团技术架构
- 前端工程化说明
- 历史背景说明
- 架构说明
- 前端工程化技术栈
- 技术文档说明
- 功能模块说明
- 前端模块管理器简介
- 框架对比分析
- vue&react&ng对比分析(一)
- vue&react&ng对比分析(二)
- vue&react&ng对比分析(三)
- 工程化专题系列
- 需要解决的问题
- 001
- 002
- 003
- 常见代码错误
- jslint中常见的错误
- css规范常见错误
- html规范常见错误
- 工程化目录
- 工程化初始化
- 项目构建流程
- 项目打包优化
- 上线与迭代注意事项
- 前端部署发布
- jetkins部署
- 部署需求整理
- 前端监控
- 工程化实践指南
- dock持续部署
- 系列文章
- 插拔式前端的设计
- 其他实践
- 工程化的前端管理
- 宋小菜借鉴
- 大前端团队介绍
- 人员组成
- 人员发展
- 研发流程
- 任务分类
- 前端基础建设与架构
- 技术栈以及技术方案
- 业务目录大纲
- 前端大纲
- api管理
- 后端api工具
- 前端easymock
- api拦截与代理
- api优化
- api请求时长策略设计
- 前端架构专题
- 架构专题一
- 产品原型对接
- 与ui对接
- 图片专题
- 图片工程化大纲
- 图片优化
- 图标字体
- 图标字体vs雪碧图
- 工程化的前端矩阵
- 蚂蚁金服前端矩阵分享
- BFF架构
- 概念解析
- 前端脚手架
- 初始化项目
- 个性化配置
- 部署与发布
- 性能优化专题
- http专题
- https常识
- http优化1
- http优化2
- http优化3
- http缓存
- 常规web性能优化攻略
- 性能优化大纲
- 样式优化
- js优化
- 第三方依赖优化
- 代码分割优化
- 图片优化
- 打包优化
- 服务器优化
- 缓存优化
- 交互优化
- pc事件优化
- 手机事件优化
- 推荐文章
- 01
- 前端安全专题
- 前端安全大纲
- 前端第三方库
- seo优化
- web框架的对比
- 001
- 学习资源
- 珠峰前端架构
- npm教程
- npm入门
- cnpm入门
- cnpm搭建
- 你该知道的js模块
- browserSync
- opn
- js-cookie
- npm-script进阶
- 入门篇
- 进阶篇
- 高阶篇
- 实践篇
- yarn入门
- nodejs教程
- axios&&fetch
- xhr
- axios
- fetch
- babel专题
- babel入门
- profill入门
- nodejs入门
- 快速入门
- 大纲介绍
- node基础
- global obj
- assert断言
- procss-进程
- child_process子进程
- cluster集群
- console控制台
- crypto-加密
- dgram-数据报
- dns-域名服务器
- error-异常
- events-事件
- global-全局变量
- http-基本协议
- https-安全协议
- modules-模块
- os-操作系统
- path-路径
- querystring-查询字符串
- readline-逐行读取
- fs-文件系统
- net-网络操作
- 命令行工具
- 内存泄露
- 代码的组织与部署
- 异步编程
- orm模块
- 异步编程解决方案
- node-lessons
- 环境准备
- nodejs实践
- 项目搭建
- 异步优化
- 创建web和tcp服务器
- 终端问答程序
- 爬虫系统
- mongleDb
- mongoDB简介
- 基本使用
- 实用技巧
- 汇总001
- 饿了么后台搭建
- nodejs干货
- 沪江基于node的实践
- 苏宁基于nodejs优化
- 基于nodejs开发脚手架
- 书籍干货
- 深入浅出nodejs
- 异步I/O(一)
- gulp教程
- gulp入门
- gulp常用插件(1)
- gulp常用插件(2)
- gulp创建目录
- 经验普及贴
- webpack教程
- webpack入门
- 简单入门
- entry配置
- output配置
- 插件使用01
- 插件使用02
- loader使用
- dev-server介绍
- 构建css
- css模块化
- 使用less和sass
- 构建图片
- 引入字体
- babel配置攻略
- eslint
- 001
- webpack进阶
- 分不同文件检出
- 优化打包大小
- 优化打包速度
- 自定义配置
- 单页以及多页如何配置
- 优化实践
- 文章导读
- 001
- 优化指南
- 参考列表
- webpack4
- 多入口程序构建
- 参考教程
- 项目实践
- 环境区分
- 常见问题
- 解读webpack
- 从vuejs权威指南中解决
- 深入浅出webpack
- rollup
- 入门
- parcel
- 入门篇
- express教程
- nuxt教程
- 入门
- 基本入门
- koa教程
- koa基本入门
- koa开发注意事项
- koa实践指南
- 关于路由
- koa优化指南
- 001
- Vuejs
- vuejs入门系列
- vue-cli入门
- vue2基本认识
- vuejs入门教程
- 样式绑定
- vuex入门学习笔记
- vue组件生命周期
- 组件的使用
- vue-router入门
- vue-filter
- 计算属性使用
- 开发注意事项
- mixins
- 组件通讯
- vuejs进阶
- 进阶资源
- router进阶
- 官网介绍
- 前进与后退优化
- keep-alive基本使用
- keep-alive原理详解
- 钩子函数进阶
- 计算属性&监听&方法
- vue服务端渲染技术
- 项目实践之路
- 实践大纲
- 插槽专题篇
- vue-cli升级
- 进阶入门
- vuejs架构
- nuxt
- vuejs项目实践
- vue实践常见问题
- 001
- 002
- 003
- 004
- 005
- 改造api参数探索
- 007
- 008
- 009
- 010
- 项目技术栈
- vue性能问题以及优化方案
- vue-spa应用的理解
- vue-ssr的部署与使用
- 滴滴出行实践案例
- 2.0重构
- vue-element-admin实践
- 准备工作
- 菜单设计
- 权限设计
- 依赖模块
- vue-betterScroll
- 性能优化懒加载
- 京东组件实践
- vue2项目小结
- vue探索与实践
- 去哪实践
- 介绍
- 饿了么项目实践
- 项目解析
- vue骨架屏实践
- vue生态推荐
- ui框架
- elementUI
- 001
- 002
- VUE-material
- vant-ui
- 解读入门
- iview
- 使用问题汇总
- vux
- mint-ui
- loadmore
- vue资源导航
- vueconf
- 源码解读
- vm
- 双向绑定
- 基本原理
- 数组双向绑定
- 报错机制
- 封装方法
- 运行环境
- 入门
- 指令
- vue-router解读
- util
- vue-props
- 流程逻辑
- 推荐文章
- 源码解读
- 文章导读
- 001
- vuejs实战
- 基础篇
- 进阶篇
- 实践篇
- 面试专题
- angularjs教程
- angularjs入门系列
- 基本入门
- ng2入门
- ng进阶
- ng项目实践
- 源码解读
- typescript
- reactjs教程
- reactjs入门系列
- react的基本入门
- react组件
- virtalDom认识
- react-cli入门
- react组件的生命周期
- 基本知识点
- react-router教程
- react进阶
- 基本实践
- react加载性能优化指南
- react属性封装
- 进阶45讲
- 01概述
- 02jsx
- 06高阶组件&函数子组件
- contextApi
- react-router
- 入门章节
- 进阶
- 高阶组件
- react进阶组件
- 基本介绍
- render props
- render props的封装
- render props getter
- react-native入门
- 源码解读
- 001
- 002-reactDemo
- 参考教程
- 参考教程1
- 了解react-hooks
- ui框架
- pc端ui框架推荐
- 项目实践
- weatherApp
- 001
- 002
- 不同生命周期使用场景
- react项目结构和组件的命名
- 常见问题解答
- 参考书籍
- react全栈
- 前言
- react与redux进阶
- 常见误解
- 反模式
- react设计模式与最佳实践
- 7美化组件
- 7.2行内样式
- 7.4css模块
- 深入react技术栈
- react学习手册
- 序
- mobx教程
- 入门
- 大佬推荐
- 001
- react面试
- 001
- linux教程
- linux入门
- 基本入门
- 文件管理
- 文件传输
- 文档编辑
- 磁盘管理
- 磁盘维护
- 网络通讯
- 系统管理
- 系统设置
- 备份压缩
- 设备管理
- 查看系统信息
- linux其他
- webhook
- rsync入门教程
- ssh免登陆设置
- 安装nodejs
- nginx教程
- 入门教程
- 安装
- 基本配置
- 服务基本使用
- 高性能nginx
- 001
- pm2教程
- shell教程
- 入门大纲
- echo命令
- 参考文献
- linux常用命令2
- linux常见问题
- 001
- python
- 入门教程
- 机器学习
- 准备工作
- 服务器常识
- tomcat
- 入门常识
- iis
- redis教程
- 入门第一篇
- redis进阶
- 项目实践
- redis使用问题
- mongleDB
- 入门
- 使用进阶
- 项目实践
- 常见问题
- electron
- 入门系列
- 前言
- 小程序
- 入门
- 准备工作
- 路由
- 参考文档
- 001
- 小程序开发--双路视频调研
- 准备工作
- 参考资源
- 参考网址
- docker
- 入门
- 基本认识
- 安装与使用
- docker安装nginx
- docker安装jetkins(1)
- docker部署jenkins(2)
- 进阶
- 实践总结
- docker群分享
- docker部署前端应用
- 文章导读
- docker其他
- 网络安全
- 入门
- 大纲
- 项目解析
- schoolpal.web
- 功能模块大纲
- 目录结构大纲
- 前端国际化
- 国际化方案
- 其他
- bower入门教程
- weex
- 入门
- memcached
- 入门
- sails
- 入门