Todo list implement with Vue
页面逻辑不是很复杂,多个组件共同维护一个todos
数组,通过Vue的双向绑定,自动渲染todos
到页面上。
注意数据最好集中处理,子组件不要修改父组件的数据,而是通过$emit
向外触发一个事件(相当于给组件定义了一个类似于click
的原生事件)。
接下来的工程化才是重点。:fist_raised::fist_raised::fist_raised:
| package-lock.json
| package.json
| postcss.config.js
+---build
| webpack.config.base.js
| webpack.config.client.js
|
+---client
| | app.vue
| | index.js
| |
| +---assets
| | +---images
| | | a.jpg
| | | beijing.jpg
| | | bg.png
| | | checked.svg
| | | unChecked.svg
| | |
| | \---styles
| | footer.styl
| | global.styl
| | test-stylus.styl
| | test.css
| |
| \---views
| +---layout
| | footer.jsx
| | header.vue
| |
| \---todo
| item.vue
| tabs.vue
| todo.vue
|
+---dist
|
\---node_modules
build
文件夹放webpack配置文件webpack.config.base.js
包含公用的配置,例如vue-loader
,babel-loader
,url-loader
webpack.config.client.js
里区分开发环境和生产环境,配置了插件,webpack-dev-server
,stylus-loader
等
client
是关于客户端渲染的文件app.vue
所有组件文件的集中地index.js
入口文件,渲染了整个appviews
存放组件,其中layout
文件夹放公共组件(header, footer),todo
文件夹放app组件assets
文件夹放图片和样式
dist
文件夹是webpack打包文件的输出路径node_modules
是安装的第三方依赖库
-
vue-style-loader可以实现样式的模块热更新
-
rimraf可以删除dist目录
rimraf dist
preserveWhitespace
:防止标签中的空格对页面造成影响extractCSS
: Vue文件中的css是否单独打包cssModules
- 安装eslint, eslint-plugin-standard, eslint-plugin-promise, eslint-plugin-import, eslint-plugin-node.
- 如果要在vue文件里用eslint,还要装eslint-plugin-html
- package.json里面设置命令
"lint": "eslint --ext .js --ext .vue --ext .jsx clint/"
- 自动修改使用,加
"--fix"
准备:指定import Vue from 'vue'的来源
在webpack config里面设置resolve.alias['vue']。
vue.esm.js和vue.runtime.esm.js的区别在于,是否允许在js中使用模板
app.$data
, app.$props
, app.$el
app.$options
, app.$root
, app.$children
app.$slots
, app.$scopedSlots
app.$refs
:快速定位到模板里某一个节点或组件
app.$isServer
:服务端渲染
app.$watch
, app.$on
,
app.$forceUpdate
:强制重新渲染
app.$set()
:类似于defineProperty
里设置setter
- beforeCreate和created => 组件创建
- beforeMount和mounted=> 组件挂载到dom节点上
- beforeUpdate和updated => 数据更新时
- beforeDestory和destoryed => 组件销毁
- activated和deactivated => 和keep alive有关
当创建Vue实例时,会首先触发beforeCreate和created函数,如果实例中指定了挂载的节点(vm.$el
),会触发beforeMount和mounted函数。从beforeMount到mounted的过程中间,vue会根据template执行render函数,render结束后,才触发mounted函数。
其余声明周期函数都需要有特定的情况才会触发
基本操作:v-bind
, v-html
, v-on
相当于一个getter方法
- 与method相比,开销更小,因为computed只有当依赖的数据变化时才会计算, 当数据没有变化时, 它会读取缓存数据
- 如果一个数据需要经过复杂计算就用 computed
- 如果一个数据需要被监听并且对数据做一些操作就用 watch
不要在computed里面修改依赖值!!(watch也是)
- v-text: 绑定的值是固定的
- v-html: 绑定一段html
- v-show/ v-if: v-if会从文档流里删除,引起重绘和回流(重排)
- v-for: 注意绑定
:key
- v-model: 通常用在input,注意
:value
可以实现父子/爷孙之间的组件通信
子组件通过Vue.component定义
- data必须是函数,并且返回一个新建的对象,而不能是全局的对象(闭包? 防止子组件间的数据同步)
- Vue.extend,可以声明式的定义组件
const component = { .. ... }
const CompVue = Vue.extend(component)
new CompVue ({
el:"#root"
})
组件里面放什么是调用的时候决定的
// 定义时
<div :style="style">
<div class="header">
<slot name="header"></slot> // 具名插槽
</div>
<div class="body">
<slot name="body"></slot>
</div>
</div>
// 组件使用时
<comp-one>
<span slot="header">this is header</span>
<span slot="body">this is body</span>
</comp-one>
目的:在使用组件时,想在组件里使用组件内定义的data
// 定义时
<div :style="style">
<div>
<slot value="header"></slot>
</div>
</div>
// 组件使用时
<comp-one>
<span slot-scope="props">{{props.value}}</span> // props是定义的名字而已
</comp-one>
创建虚拟dom?
render(createElement) {
return createElement('标签或者组件名字', {标签或组件上的属性}, [标签或组件里的内容])
}
路由:
- 以前:链接输入之后输入到后端,进行模板渲染,产生一个新的html,返回到浏览器,浏览器再显示
- 现在:页面跳转不经过服务器,渲染内容来自前端js
使用vue-router和webpack需要设置webpack中的devServer:
historyApiFallback: {
index: '/index.html'
}
router-view
:根据路由取得对应的模板内容。
mode
去掉地址中的#linkActiveClass
,linkExactActiveClass
给链接的样式classscrollBehavior
设置跳转时的滚动状态fallback
不一定所有的浏览器都支持vue的路由,fallback一套哈希的
其他操作
a. 在<router-view>
上包裹transition
可以设定页面切换时的动画
b. 路由的传参,例如path: '/app/:id'
,还可以声明props: true
c. 导航守卫,每次路由跳转时会先后执行router.beforeEach(), router.beforeResolve(), router.afterEach()
- router.beforeEach()可以进行一些路由的校验
是一个store
// 创建一个store
Vue.use(Vuex) // 这个一定要在定义store前做
const store = new Vuex.Store({
state: {
count: 0
},
mutations: { // 修改count值
updateCount (state, num){
state.count = num
}
}
})
export default store
应用store:在应用的入口文件(index.js)里import,然后new Vue里声明
state里面放数据,getters相当于是vuex里面的computed,然后在app.vue里面通过计算属性(可以利用mapState和mapGetters)返回this.$store.getters.XXX,并渲染在页面上
-
target要设成'node',因为是在node上跑的
-
output:
output: { libraryTarget: 'commonjs2', filename: 'server-entry.js', path: path.join(__dirname, '../server-build') },
-
externals--设置依赖哪些包?也就是packages.json里面的“dependencies”(安装的时候用-S),而devDependencies主要是一些打包的工具,安装的时候用-D
-
插件---一定要用vue-server-renderer
学个骨灰盖饭,好难啊,看不懂