学习vue

vue如何新建一个项目(超详细哦) - 简书

 

MVVM

Model(json数据)-View(html视图)-ViewModel(用来关联前两者,实现数据和视图的双向绑定)

用vue举例:

Model就是其中的生命周期、data、methods等有关数据操作的内容

View就是template中的html属性部分,即页面展示的样子

ViewModel就是template中和数据有关联的部分,如v-bind动态绑定Model中数据、v-for循环Model中的数据,等这些操作的部分。

优点:

可复用性:把一些数据逻辑放到一个ViewModel 中,让很多 view 来重用。比如vue中的组件可以被复用。

低耦合:view和model没有直接联系在一起

vue目录结构

├── build/               # Webpack 配置目录
├── dist/                # build 生成的生产环境下的项目
├── config/               # Vue基本配置文件,可以设置监听端口,打包输出等
├── node_modules/                # 依赖包,通常执行npm i会生成
├── src/                 # 源码目录(开发的项目文件都在此文件中写)
│   ├── assets/            # 放置需要经由 Webpack 处理的静态文件,通常为样式类文件,如css,sass以及一些外部的js
│   ├── components/        # 公共组件
│   ├── filters/           # 过滤器
│   ├── store/         # 状态管理
│   ├── routes/            # 路由,此处配置项目路由
│   ├── services/          # 服务(统一管理 XHR 请求)
│   ├── utils/             # 工具类
│   ├── views/             # 路由页面组件
│   ├── App.vue             # 根组件
│   ├── main.js             # 入口文件
├── index.html         # 主页,打开网页后最先访问的页面
├── static/              # 放置无需经由 Webpack 处理的静态文件,通常放置图片类资源
├── .babelrc             # Babel 转码配置
├── .editorconfig             # 代码格式
├── .eslintignore        # (配置)ESLint 检查中需忽略的文件(夹)
├── .eslintrc            # ESLint 配置
├── .gitignore           # (配置)在上传中需被 Git 忽略的文件(夹)
├── package.json         # 本项目的配置信息,启动方式
├── package-lock.json         # 记录当前状态下实际安装的各个npm package的具体来源和版本号
├── README.md         # 项目说明(很重要,便于其他人看懂)

指令:带有 v- 前缀的特殊 attribute。

*动态参数

1.可以用方括号括起来的 JavaScript 表达式作为一个指令的参数

<a v-bind:[attributeName]="url"> ... </a>

2.空格和引号,放在 HTML attribute 名里是无效的。变通的办法是使用没有空格或引号的表达式,或用计算属性替代这种复杂表达式。

<!-- 这会触发一个编译警告 --> <a v-bind:['foo' + bar]="value"> ... </a>

 3.DOM 中使用模板时 (直接在一个 HTML 文件里撰写模板),还需要避免使用大写字符来命名键名,因为浏览器会把 attribute 名全部强制转为小写

4.缩写:v-bind为“:”,v-on为“@”

vue框架的watch:

使用watch监听数据时,有三个选项,handler,deep,immediate

2.1vue使用watch来响应数据的变化。

2.2当值第一次绑定时,不会执行监听函数,只有值发生改变才会执行

2.3 immediate属性:如果我们需要在最初绑定值的时候也执行函数,则就需要用到immediate属性。比如当父组件向子组件动态传值时,子组件props首次获取到父组件传来的默认值时,也需要执行函数,此时就需要将immediate设为true。immediate表示在watch中首次绑定的时候,是否执行handler,值为true则表示在watch中声明的时候,就立即执行handler方法,值为false,则和一般使用watch一样,在数据发生变化的时候才执行handler。

2.4 deep属性:

设置deep: true 则可以监听到cityName.name的变化,此时会给cityName的所有属性都加上这个监听器,当对象属性较多时,每个属性值的变化都会执行handler。如果只需要监听对象中的一个属性值,则可以做以下优化:使用字符串的形式监听对象属性。

vue框架中数据渲染该放在created阶段还是mounted阶段:

3.1  理解:

created:在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成视图。($el还未被创建)

mounted:在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作。(el属性创建并挂载完成)

如果在mounted钩子函数中请求数据可能导致页面闪屏问题

其实就是加载时机问题,放在created里会比mounted触发早一点,如果在页面挂载完之前请求完成的话就不会看到闪屏了。

计算属性和方法

计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。如果你不希望有缓存,请用方法来替代。

父子组件之间的通信

路由

1*过程清理:

①先npm install vue-router 安装路由插件,此时配置文件中的依赖项会加多一个router属性。

②紧接着创建一个放路由的文件router进行路由配置(需导入依赖项)。

③再来到根组件App.vue中将路由跳转(router-link)路由显示(router-view)配置出来

④再在入口文件main.js中引入该依赖项(记得要放入实例中)。

⑤当有子路由时,需要在父路由跳转到的组件中放置子路由相关的路由跳转(router-link)路由显示(router-view)【也可以使用push方法实现跳转】(也就是根组件中点击了父路由的router-link内容,根组件router-view处会显示子路由的router-link内容,再点击子路由的router-link内容,父路由的router-view处会显示子路由页面内容)

2*访问路由的两种方式:

标签导航<router-link><router-link>是通过转义为<a></a>标签进行跳转,其中router-link标签中的to属性会被转义为a标签中的href属性;

编程式导航:我们可以通过this.$router.push()这个方法来实现编程式导航,当然也可以实现参数传递,这种编程式导航一般是用于按钮点击之后跳转。*this.$router.push('home')  push方法会向 history 栈添加一个新的记录

3*path:'name'和path:'/name'的区别:

如果加/则会被当作根目录,否则当前的路径会嵌套在之前的路径中。

4*动态路由:

 通过获取路径显示的内容并放到页面上,就可以将路由变成动态的,即/后面加需要用到的数据。

route:首先它是个单数,译为路由,即我们可以理解为单个路由或者某一个路由;

routes:它是个复数,表示多个的集合才能为复数;即我们可以理解为多个路由的集合,JS中表示多种不同状态的集合的形式只有数组和对象两种,事实上官方定义routes是一个数组;所以我们记住了,routes表示多个数组的集合

router:译为路由器,上面都是路由,这个是路由器,我们可以理解为一个容器包含上述两个或者说它是一个管理者,负责管理上述两个;举个常见的场景的例子:当用户在页面上点击按钮的时候,这个时候router就会去routes中去查找route,就是说路由器会去路由集合中找对应的路由

route$route对象表示当前的路由信息(当前激活的路由对象),包含了当前 URL 解析得到的信息。包含当前的路径,参数,query对象等

1.路由元信息meta:

*每个路由都有一个meta元数据字段用来自定义信息,供页面组件或路由钩子函数使用

*$route.meta.***  获取meta数据

*window.document.title = to.meta.***  可改变网页标题,用户登录鉴权

2.路由中导航钩子中next()方法:进行管道中的下一个钩子

3.$route.path:当前路由路径,解析为绝对路径eg. /foo/bar

4.$route.params:路径/foo?user=1,则有 $route.query.user == 1

5.$route.matched:数组对象,包含当前路由的所有嵌套路径片段的路由记录(routes 配置数组中的对象副本 (还有在 children 数组))

6.$route.query:

7.$route.fullPath:解析完后的url

router:$router对象是全局路由的实例,是router构造方法的实例。

*this.$router.go(-1)  

 *this.$router.replace('/')  replace方法是替换当前的页面,

路由权限

**1 导航守卫:

用来判断页面是否需要跳转,需要在router中的index.js文件夹下使用router.beforeEach((to,from,next) => {.....})

/*

“to”: 即将要进入的目标 路由对象;(这个对象中包含name,params,meta等属性

"from": 当前导航正要离开的路由对象;(这个对象中包含name,params,meta等属性)

“next”: Function: 确保要调用 next 方法,否则钩子就不会被 resolved。这个当中还可以传一些参数,具体可以看官方文档。

*/

**2 routes{}中的meta属性:用于进行权限控制,不同用户的访问权限不同:

如:当点击进入/blog页面时,如果不符合条件则跳转到/login

vuex中的modules

Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块,

**store文件结构:

**index.js中动态引入modules:

const modulesFiles = require.context('./modules', true, /\.js$/)

// you do not need `import app from './modules/app'`
// it will auto require all vuex module from modules file
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
  // set './app.js' => 'app'
  const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
  const value = modulesFiles(modulePath)
  modules[moduleName] = value.default
  return modules
}, {})

const store = new Vuex.Store({
  modules,
  getters
})

export default store

 **简单的引入:

import Vue from 'vue'
import Vuex from 'vuex'

import bus from './module/app'
import app from './module/errorLog'

Vue.use(Vuex)
export default new Vuex.Store({
    state: {
        // 这里是根vuex状态
    },
    mutations: {
        // 这里是根vuex状态
    },
    actions: {
        // 这里是根vuex状态
    },
    modules: { // 子vuex状态模块注册
        namespaced: true, // 为了解决不同模块命名冲突的问题
        app,
        errorLog
    }
})

**modules中的errorLog.js文件规范:

const state = {
  logs: []
}

const mutations = {
  ADD_ERROR_LOG: (state, log) => {
    state.logs.push(log)
  },
  CLEAR_ERROR_LOG: (state) => {
    state.logs.splice(0)
  }
}

const actions = {
  addErrorLog({ commit }, log) {
    commit('ADD_ERROR_LOG', log)
  },
  clearErrorLog({ commit }) {
    commit('CLEAR_ERROR_LOG')
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}

**工具类utils.js中使用:

// 引入 这里的store 就相当于页面中的 this.$store

import store from '@/store'

export const setCurUser = (user) => {
    let curUser = store.app.user
    if(!curUser) {
        store.commit("app/setUser", user)  /*文件名/函数名*/
        return user
    }    
    return curUser
}
 

vuex中的actions

vuex中action应该怎么分发事件

作用域插槽和自定义事件有什么区别呢?

slot、作用域插槽,你真的懂了吗?_sunhonghui9527的博客-CSDN博客_slot作用域插槽

vue中组件的data为什么必须是一个函数而不能是一个对象实例?

首先需要理解对象实际存储的是数据存储的地址值,任何地方修改该对象中的属性,实际修改的是同一份数据的值。

组件最终会被多个页面复用,也就是说,如果data保存的是一个地址值(一个对象实例),那么所有复用该组件的页面使用的都是同一份数据的值(这份数据变成公有的),一旦一个调用该组件的地方修改了该值,也就是修改了公有数据,所有调用该组件的地方数据都会改变。

而用函数来存储数据,使它return一个对象实例,也就是每个复用该组件的地方使用的数据实际是函数中新创建并return的对象(开辟了不同的存储空间,指向不同的地址值)。

待更新

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值